├── .babelrc ├── .circleci └── config.yml ├── .eslintignore ├── .eslintrc.yaml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── pull_request_template.md ├── .gitignore ├── .node-version ├── .npmignore ├── .npmrc ├── .prettierignore ├── .prettierrc.yml ├── .yarnrc ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── pure.d.ts ├── pure.js ├── rollup.config.js ├── scripts └── publish ├── src ├── index.test.ts ├── index.ts ├── pure.test.ts ├── pure.ts └── shared.ts ├── tests ├── types │ ├── errors.test.ts │ ├── fixtures │ │ ├── createTerminalExtraProperty.ts │ │ └── discoverReadersExtraProperty.ts │ ├── index.ts │ └── tsconfig.json └── versions │ ├── .eslintrc.yml │ ├── .gitignore │ ├── scripts │ └── test.sh │ ├── src │ └── index.ts │ └── tsconfig.json ├── tsconfig.json ├── types ├── .eslintrc.yml ├── index.d.ts ├── proto.d.ts └── terminal.d.ts └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } 4 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # This config is equivalent to both the '.circleci/extended/orb-free.yml' and the base '.circleci/config.yml' 2 | version: 2.1 3 | 4 | orbs: 5 | node: circleci/node@5.0.2 6 | workflows: 7 | test_my_app: 8 | jobs: 9 | - node/test: 10 | run-command: ci 11 | pkg-manager: yarn 12 | version: lts 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | examples 4 | tests/types 5 | types/proto.d.ts 6 | -------------------------------------------------------------------------------- /.eslintrc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | root: true 3 | extends: 4 | - eslint:recommended 5 | - plugin:@typescript-eslint/eslint-recommended 6 | - plugin:@typescript-eslint/recommended 7 | - prettier 8 | parser: '@typescript-eslint/parser' 9 | plugins: 10 | - jest 11 | - prettier 12 | - '@typescript-eslint' 13 | env: 14 | jest/globals: true 15 | browser: true 16 | rules: 17 | no-console: 0 18 | func-style: 2 19 | consistent-return: 2 20 | prefer-arrow-callback: 21 | - 2 22 | - allowNamedFunctions: false 23 | allowUnboundThis: false 24 | no-unused-vars: 25 | - 2 26 | - ignoreRestSiblings: true 27 | jest/no-disabled-tests: 2 28 | jest/no-focused-tests: 2 29 | '@typescript-eslint/camelcase': 0 30 | '@typescript-eslint/no-explicit-any': 0 31 | '@typescript-eslint/no-empty-interface': 0 32 | '@typescript-eslint/triple-slash-reference': 0 33 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stripe/terminal-js/6934fc91984ffecd397c240fa3054a97b9ad14ca/.gitattributes -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ### Summary 12 | 13 | 14 | 15 | ### Other information 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Summary & motivation 2 | 3 | 4 | 5 | ### Testing & documentation 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .cache 3 | dist 4 | node_modules 5 | *.log 6 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 18.14.0 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | examples -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | package.json 4 | types/proto.d.ts 5 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | trailingComma: es5 3 | bracketSpacing: false 4 | arrowParens: always 5 | proseWrap: always 6 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | registry "https://registry.npmjs.org/" 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Stripe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terminal JS ES Module 2 | 3 | Use the [Terminal JS SDK](https://stripe.com/docs/terminal/sdk/js) as an ES 4 | module. 5 | 6 | **Note**: This package dynamically loads the Stripe Terminal SDK from 7 | `https://js.stripe.com` and wraps the SDK's global`StripeTerminal` function. To 8 | be 9 | [PCI compliant](https://stripe.com/docs/security/guide#validating-pci-compliance), 10 | you must load the SDK directly from `https://js.stripe.com` by using this 11 | library. You cannot include the dynamically loaded code in a bundle or host it 12 | yourself. 13 | 14 | [![npm version](https://img.shields.io/npm/v/@stripe/terminal-js.svg?style=flat-square)](https://www.npmjs.com/package/@stripe/terminal-js) 15 | 16 | ## Installation 17 | 18 | Use `npm` or `yarn` to install the Terminal JS module: 19 | 20 | ```sh 21 | > npm install @stripe/terminal-js 22 | 23 | > yarn add @stripe/terminal-js 24 | ``` 25 | 26 | ## Usage 27 | 28 | ### `loadStripeTerminal` 29 | 30 | This function returns a `Promise` that resolves with a newly created 31 | `StripeTerminal` object once the Terminal JS SDK has loaded. If necessary, it 32 | will load the SDK for you by inserting the Terminal JS script tag. If you call 33 | `loadStripeTerminal` in a server environment it will resolve to `null`. 34 | 35 | ```js 36 | import {loadStripeTerminal} from '@stripe/terminal-js'; 37 | 38 | const StripeTerminal = await loadStripeTerminal(); 39 | 40 | const terminal = StripeTerminal.create({ 41 | onFetchConnectionToken: async () => { 42 | … 43 | } 44 | }) 45 | ``` 46 | 47 | For more information on how to use the Terminal JS SDK once it loads, please 48 | refer to the 49 | [Terminal JS SDK API reference](https://stripe.com/docs/terminal/js-api-reference) 50 | or follow our [getting started](https://stripe.com/docs/terminal/sdk/js) guide. 51 | 52 | ## TypeScript support 53 | 54 | This package includes TypeScript declarations for the Terminal JS SDK. We 55 | support projects using TypeScript versions >= 3.1. 56 | 57 | Some methods in Terminal JS SDK accept and return objects from the 58 | [Stripe API](https://stripe.com/docs/api). The type declarations in 59 | `@stripe/terminal-js` for these objects in currently track to 60 | [version 2018-08-23](https://stripe.com/docs/api/versioning) of the Stripe API. 61 | If you have code using other versions of the Stripe API you may have to override 62 | type definitions as necessary. 63 | 64 | Note that we may release new [minor and patch](https://semver.org/) versions of 65 | `@stripe/terminal-js` with small but backwards-incompatible fixes to the type 66 | declarations. These changes will not affect the Terminal JS SDK itself. 67 | 68 | ## Ensuring the Terminal JS SDK is available everywhere 69 | 70 | By default, this module will insert a ` 93 | ``` 94 | 95 | ### Importing `loadStripeTerminal` without side effects 96 | 97 | If you would like to use `loadStripeTerminal` in your application, but defer 98 | loading the Terminal JS SDK script until `loadStripeTerminal` is first called, 99 | use the alternative `@stripe/terminal-js/pure` import path: 100 | 101 | ``` 102 | import {loadStripeTerminal} from '@stripe/terminal-js/pure'; 103 | 104 | // Terminal SDK will not be loaded until `loadStripeTerminal` is called 105 | ``` 106 | 107 | ## Terminal JS SDK Documentation 108 | 109 | - [Terminal JS SDK Docs](https://stripe.com/docs/terminal/sdk/js) 110 | - [Terminal JS SDK API Reference](https://stripe.com/docs/terminal/js-api-reference) 111 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ['/src'], 3 | testMatch: [ 4 | '**/__tests__/**/*.+(ts|tsx|js)', 5 | '**/?(*.)+(spec|test).+(ts|tsx|js)', 6 | ], 7 | transform: { 8 | '^.+\\.(ts|tsx)$': 'ts-jest', 9 | }, 10 | testEnvironment: 'jsdom', 11 | globals: { 12 | // Suppress noise about enabling `esModuleInterop` 13 | 'ts-jest': {diagnostics: {ignoreCodes: [151001]}}, 14 | _VERSION: true, 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@stripe/terminal-js", 3 | "version": "0.24.0", 4 | "description": "Stripe Terminal loading utility", 5 | "main": "dist/terminal.js", 6 | "module": "dist/terminal.esm.js", 7 | "jsnext:main": "dist/terminal.esm.js", 8 | "types": "types/index.d.ts", 9 | "scripts": { 10 | "test": "./node_modules/.bin/jest", 11 | "test:versions": "./tests/versions/scripts/test.sh", 12 | "test:types": "./node_modules/.bin/tsc -p ./tests/types && ./node_modules/.bin/jest --roots '/tests/types'", 13 | "lint": "./node_modules/.bin/eslint '{src,types}/**/*.{ts,js}' && yarn prettier-list-different", 14 | "typecheck": "./node_modules/.bin/tsc", 15 | "build": "yarn clean && yarn rollup -c", 16 | "clean": "./node_modules/.bin/rimraf dist", 17 | "ci": "yarn lint && yarn test && yarn test:versions && yarn test:types && yarn typecheck && yarn build", 18 | "prepublishOnly": "echo \"\nPlease use ./scripts/publish instead\n\" && exit 1", 19 | "prettier": "./node_modules/.bin/prettier './**/*.{js,ts,md,html,css}' --write", 20 | "prettier-list-different": "./node_modules/.bin/prettier './**/*.{js,ts,md,html,css}' --list-different" 21 | }, 22 | "keywords": [ 23 | "Stripe", 24 | "Terminal", 25 | "Terminal.js" 26 | ], 27 | "author": "Stripe (https://www.stripe.com)", 28 | "license": "MIT", 29 | "homepage": "https://stripe.com/docs/terminal/sdk/js", 30 | "files": [ 31 | "dist", 32 | "src", 33 | "types", 34 | "pure.js", 35 | "pure.d.ts" 36 | ], 37 | "devDependencies": { 38 | "@babel/core": "^7.7.2", 39 | "@babel/preset-env": "^7.7.1", 40 | "@rollup/plugin-replace": "^2.3.1", 41 | "@types/jest": "^26.0.3", 42 | "@typescript-eslint/eslint-plugin": "^5.2.0", 43 | "@typescript-eslint/parser": "^5.2.0", 44 | "babel-eslint": "^10.1.0", 45 | "babel-jest": "^27.3.1", 46 | "conditional-type-checks": "^1.0.5", 47 | "eslint": "^8.1.0", 48 | "eslint-config-prettier": "^8.3.0", 49 | "eslint-plugin-import": "^2.25.2", 50 | "eslint-plugin-jest": "^25.2.2", 51 | "eslint-plugin-prettier": "^4.0.0", 52 | "jest": "^27.0.4", 53 | "prettier": "^1.19.1", 54 | "protobufjs": "^7.2.4", 55 | "rimraf": "^2.6.2", 56 | "rollup": "^2.79.2", 57 | "rollup-plugin-babel": "^4.3.3", 58 | "rollup-plugin-typescript2": "^0.25.3", 59 | "ts-jest": "^27.0.3", 60 | "typescript": "^3.7.4" 61 | }, 62 | "dependencies": { 63 | "stripe": "^8.222.0", 64 | "ws": "6.2.3" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pure.d.ts: -------------------------------------------------------------------------------- 1 | import {loadStripeTerminal as IloadStripeTerminal} from './src/pure'; 2 | import { 3 | Terminal, 4 | PaymentStatus, 5 | ConnectionStatus, 6 | OutputLogLevel, 7 | TerminalProps, 8 | } from './types/terminal'; 9 | 10 | export * from './types/terminal'; 11 | 12 | export interface StripeTerminal { 13 | create(props: TerminalProps): Terminal; 14 | PaymentStatus: PaymentStatus; 15 | ConnectionStatus: ConnectionStatus; 16 | OutputLogLevel: OutputLogLevel; 17 | } 18 | 19 | export const loadStripeTerminal: typeof IloadStripeTerminal; 20 | -------------------------------------------------------------------------------- /pure.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/pure.js'); 2 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import ts from 'rollup-plugin-typescript2'; 3 | import replace from '@rollup/plugin-replace'; 4 | 5 | import pkg from './package.json'; 6 | 7 | const PLUGINS = [ 8 | ts({ 9 | tsconfigOverride: {exclude: ['**/*.test.ts']}, 10 | }), 11 | babel({ 12 | extensions: ['.ts', '.js', '.tsx', '.jsx'], 13 | }), 14 | replace({ 15 | _VERSION: JSON.stringify(pkg.version), 16 | }), 17 | ]; 18 | 19 | export default [ 20 | { 21 | input: 'src/index.ts', 22 | output: [ 23 | {file: pkg.main, format: 'cjs'}, 24 | {file: pkg.module, format: 'es'}, 25 | ], 26 | plugins: PLUGINS, 27 | }, 28 | { 29 | input: 'src/pure.ts', 30 | output: [{file: 'dist/pure.js', format: 'cjs'}], 31 | plugins: PLUGINS, 32 | }, 33 | ]; 34 | -------------------------------------------------------------------------------- /scripts/publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | IFS=$'\n\t' 5 | 6 | RELEASE_TYPE=${1:-} 7 | 8 | echo_help() { 9 | cat << EOF 10 | USAGE: 11 | ./scripts/publish 12 | 13 | ARGS: 14 | 15 | A Semantic Versioning release type used to bump the version number. Either "patch", "minor", or "major". 16 | EOF 17 | } 18 | 19 | create_github_release() { 20 | if ! command -v hub &> /dev/null 21 | then 22 | create_github_release_fallback 23 | return 24 | fi 25 | 26 | # Get the last two releases. For example, `("v1.3.1" "v1.3.2")` 27 | local versions=($(git tag --sort version:refname | grep '^v' | tail -n 2)) 28 | 29 | # If we didn't find exactly two previous version versions, give up 30 | if [ ${#versions[@]} -ne 2 ]; then 31 | create_github_release_fallback 32 | return 33 | fi 34 | 35 | local previous_version="${versions[0]}" 36 | local current_version="${versions[1]}" 37 | local commit_titles=$(git log --pretty=format:"- %s" "$previous_version".."$current_version"^) 38 | local release_notes="$(cat << EOF 39 | $current_version 40 | 41 | 42 | 43 | 44 | $commit_titles 45 | 46 | ### New features 47 | 48 | ### Fixes 49 | 50 | ### Changed 51 | 52 | EOF 53 | )" 54 | 55 | echo "Creating GitHub release" 56 | echo "" 57 | echo -n " " 58 | hub release create -em "$release_notes" "$current_version" 59 | } 60 | 61 | create_github_release_fallback() { 62 | cat << EOF 63 | Remember to create a release on GitHub with a changelog notes: 64 | 65 | https://github.com/stripe/terminal-js/releases/new 66 | 67 | EOF 68 | } 69 | 70 | # Show help if no arguments passed 71 | if [ $# -eq 0 ]; then 72 | echo "Error! Missing release type argument" 73 | echo "" 74 | echo_help 75 | exit 1 76 | fi 77 | 78 | # Show help message if -h, --help, or help passed 79 | case $1 in 80 | -h | --help | help) 81 | echo_help 82 | exit 0 83 | ;; 84 | esac 85 | 86 | # Validate passed release type 87 | case $RELEASE_TYPE in 88 | patch | minor | major) 89 | ;; 90 | 91 | *) 92 | echo "Error! Invalid release type supplied" 93 | echo "" 94 | echo_help 95 | exit 1 96 | ;; 97 | esac 98 | 99 | # Make sure our working dir is the repo root directory 100 | cd "$(git rev-parse --show-toplevel)" 101 | 102 | echo "Fetching git remotes" 103 | git fetch 104 | 105 | GIT_STATUS=$(git status) 106 | 107 | if ! grep -q 'On branch master' <<< "$GIT_STATUS"; then 108 | echo "Error! Must be on master branch to publish" 109 | exit 1 110 | fi 111 | 112 | if ! grep -q "Your branch is up to date with 'origin/master'." <<< "$GIT_STATUS"; then 113 | echo "Error! Must be up to date with origin/master to publish" 114 | exit 1 115 | fi 116 | 117 | if ! grep -q 'working tree clean' <<< "$GIT_STATUS"; then 118 | echo "Error! Cannot publish with dirty working tree" 119 | exit 1 120 | fi 121 | 122 | echo "Installing dependencies according to lockfile" 123 | yarn -s install --frozen-lockfile 124 | 125 | echo "Linting, testing, and building" 126 | yarn -s run ci 127 | 128 | echo "Tagging and publishing $RELEASE_TYPE release" 129 | yarn -s --ignore-scripts publish --$RELEASE_TYPE --access=public 130 | 131 | echo "Pushing git commit and tag" 132 | git push --follow-tags 133 | 134 | echo "Publish successful!" 135 | echo "" 136 | 137 | create_github_release 138 | -------------------------------------------------------------------------------- /src/index.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | const dispatchScriptEvent = (eventType: string): void => { 4 | const injectedScript = document.querySelector( 5 | 'script[src="https://js.stripe.com/terminal/v1"]' 6 | ); 7 | 8 | if (!injectedScript) { 9 | throw new Error('could not find StripeTerminal script element'); 10 | } 11 | 12 | injectedScript.dispatchEvent(new Event(eventType)); 13 | }; 14 | 15 | describe('Stripe module loader', () => { 16 | afterEach(() => { 17 | const script = document.querySelector( 18 | 'script[src="https://js.stripe.com/terminal/v1"], script[src="https://js.stripe.com/terminal/v1/"]' 19 | ); 20 | if (script && script.parentElement) { 21 | script.parentElement.removeChild(script); 22 | } 23 | delete window.StripeTerminal; 24 | jest.resetModules(); 25 | }); 26 | 27 | it('injects the Terminal script as a side effect after a tick', () => { 28 | require('./index'); 29 | 30 | expect( 31 | document.querySelector('script[src="https://js.stripe.com/terminal/v1"]') 32 | ).toBe(null); 33 | 34 | return Promise.resolve().then(() => { 35 | expect( 36 | document.querySelector( 37 | 'script[src="https://js.stripe.com/terminal/v1"]' 38 | ) 39 | ).not.toBe(null); 40 | }); 41 | }); 42 | 43 | it('does not inject the script when Stripe is already loaded', () => { 44 | require('./index'); 45 | 46 | window.StripeTerminal = jest.fn((key) => ({key})) as any; 47 | 48 | return new Promise((resolve) => setTimeout(resolve)).then(() => { 49 | expect( 50 | document.querySelector( 51 | 'script[src="https://js.stripe.com/terminal/v1"]' 52 | ) 53 | ).toBe(null); 54 | }); 55 | }); 56 | 57 | describe('does not inject a duplicate script when one is already present', () => { 58 | test('when the script does not have a trailing slash', () => { 59 | require('./index'); 60 | 61 | const script = document.createElement('script'); 62 | script.src = 'https://js.stripe.com/terminal/v1'; 63 | document.body.appendChild(script); 64 | 65 | return Promise.resolve().then(() => { 66 | expect( 67 | document.querySelectorAll( 68 | 'script[src="https://js.stripe.com/terminal/v1"], script[src="https://js.stripe.com/terminal/v1/"]' 69 | ) 70 | ).toHaveLength(1); 71 | }); 72 | }); 73 | 74 | test('when the script has a trailing slash', () => { 75 | require('./index'); 76 | 77 | const script = document.createElement('script'); 78 | script.src = 'https://js.stripe.com/terminal/v1/'; 79 | document.body.appendChild(script); 80 | 81 | return Promise.resolve().then(() => { 82 | expect( 83 | document.querySelectorAll( 84 | 'script[src="https://js.stripe.com/terminal/v1"], script[src="https://js.stripe.com/terminal/v1/"]' 85 | ) 86 | ).toHaveLength(1); 87 | }); 88 | }); 89 | }); 90 | 91 | describe.each(['./index', './pure'])( 92 | 'loadStripeTerminal (%s.ts)', 93 | (requirePath) => { 94 | beforeEach(() => { 95 | jest.restoreAllMocks(); 96 | jest.spyOn(console, 'warn').mockReturnValue(); 97 | }); 98 | 99 | it('resolves loadStripeTerminal with Terminal object', async () => { 100 | const {loadStripeTerminal} = require(requirePath); 101 | const stripePromise = loadStripeTerminal(); 102 | 103 | await new Promise((resolve) => setTimeout(resolve)); 104 | window.StripeTerminal = jest.fn() as any; 105 | dispatchScriptEvent('load'); 106 | 107 | return expect(stripePromise).resolves.toBeDefined(); 108 | }); 109 | 110 | it('rejects when the script fails', async () => { 111 | const {loadStripeTerminal} = require(requirePath); 112 | const stripePromise = loadStripeTerminal(); 113 | 114 | await Promise.resolve(); 115 | dispatchScriptEvent('error'); 116 | 117 | await expect(stripePromise).rejects.toEqual( 118 | new Error('Failed to load StripeTerminal') 119 | ); 120 | 121 | expect(console.warn).not.toHaveBeenCalled(); 122 | }); 123 | 124 | it('rejects when Terminal is not added to the window for some reason', async () => { 125 | const {loadStripeTerminal} = require(requirePath); 126 | const stripePromise = loadStripeTerminal(); 127 | 128 | await Promise.resolve(); 129 | dispatchScriptEvent('load'); 130 | 131 | return expect(stripePromise).rejects.toEqual( 132 | new Error('StripeTerminal not available') 133 | ); 134 | }); 135 | } 136 | ); 137 | 138 | describe('loadStripeTerminal (index.ts)', () => { 139 | it('does not cause unhandled rejects when the script fails', async () => { 140 | require('./index'); 141 | 142 | await Promise.resolve(); 143 | dispatchScriptEvent('error'); 144 | 145 | // Turn the task loop to make sure the internal promise handler has been invoked 146 | await new Promise((resolve) => setTimeout(resolve, 0)); 147 | 148 | expect(console.warn).toHaveBeenCalledWith( 149 | new Error('Failed to load StripeTerminal') 150 | ); 151 | }); 152 | }); 153 | }); 154 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import {StripeTerminal} from '../types/index'; 2 | import {loadScript} from './shared'; 3 | 4 | // Execute our own script injection after a tick to give users time to do their 5 | // own script injection. 6 | const stripePromise = Promise.resolve().then(loadScript); 7 | 8 | let loadCalled = false; 9 | 10 | stripePromise.catch((err) => { 11 | if (!loadCalled) { 12 | console.warn(err); 13 | } 14 | }); 15 | 16 | export const loadStripeTerminal = (): Promise => { 17 | loadCalled = true; 18 | 19 | return stripePromise; 20 | }; 21 | -------------------------------------------------------------------------------- /src/pure.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | const SCRIPT_SELECTOR = 4 | 'script[src="https://js.stripe.com/terminal/v1"], script[src="https://js.stripe.com/terminal/v1/"]'; 5 | 6 | describe('pure module', () => { 7 | afterEach(() => { 8 | const script = document.querySelector(SCRIPT_SELECTOR); 9 | if (script && script.parentElement) { 10 | script.parentElement.removeChild(script); 11 | } 12 | 13 | delete window.StripeTerminal; 14 | jest.resetModules(); 15 | }); 16 | 17 | test('does not inject the script if loadStripeTerminal is not called', async () => { 18 | require('./pure'); 19 | 20 | expect(document.querySelector(SCRIPT_SELECTOR)).toBe(null); 21 | }); 22 | 23 | test('it injects the script if loadStripeTerminal is called', async () => { 24 | const {loadStripeTerminal} = require('./pure'); 25 | loadStripeTerminal(); 26 | 27 | expect(document.querySelector(SCRIPT_SELECTOR)).not.toBe(null); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/pure.ts: -------------------------------------------------------------------------------- 1 | import {StripeTerminal} from '../types/index'; 2 | import {loadScript} from './shared'; 3 | 4 | export const loadStripeTerminal = (): Promise => 5 | loadScript(); 6 | -------------------------------------------------------------------------------- /src/shared.ts: -------------------------------------------------------------------------------- 1 | import {StripeTerminal} from '../types/index'; 2 | 3 | // `_VERSION` will be rewritten by `@rollup/plugin-replace` as a string literal 4 | // containing the package.json version 5 | // declare const _VERSION: string; 6 | 7 | const V1_URL = 'https://js.stripe.com/terminal/v1'; 8 | 9 | const injectScript = (): HTMLScriptElement => { 10 | const script = document.createElement('script'); 11 | script.src = V1_URL; 12 | 13 | const headOrBody = document.head || document.body; 14 | 15 | if (!headOrBody) { 16 | throw new Error( 17 | 'Expected document.body not to be null. Terminal requires a element.' 18 | ); 19 | } 20 | 21 | headOrBody.appendChild(script); 22 | 23 | return script; 24 | }; 25 | 26 | // TODO(jdivock): re-enable when we have a proper mechanism to track metrics 27 | 28 | // const registerWrapper = (stripe: any): void => { 29 | // if (!stripe || !stripe._registerWrapper) { 30 | // return; 31 | // } 32 | // 33 | // stripe._registerWrapper({name: 'terminal-js', version: _VERSION}); 34 | // }; 35 | 36 | let stripePromise: Promise | null = null; 37 | 38 | export const loadScript = (): Promise => { 39 | // Ensure that we only attempt to load Stripe.js at most once 40 | if (stripePromise !== null) { 41 | return stripePromise; 42 | } 43 | 44 | stripePromise = new Promise((resolve, reject) => { 45 | if (typeof window === 'undefined') { 46 | // Resolve to null when imported server side. This makes the module 47 | // safe to import in an isomorphic code base. 48 | resolve(null); 49 | return; 50 | } 51 | 52 | if (window.StripeTerminal) { 53 | resolve(window.StripeTerminal); 54 | return; 55 | } 56 | 57 | const script: HTMLScriptElement = 58 | document.querySelector( 59 | `script[src="${V1_URL}"], script[src="${V1_URL}/"]` 60 | ) || injectScript(); 61 | 62 | script.addEventListener('load', () => { 63 | if (window.StripeTerminal) { 64 | resolve(window.StripeTerminal); 65 | } else { 66 | reject(new Error('StripeTerminal not available')); 67 | } 68 | }); 69 | 70 | script.addEventListener('error', () => { 71 | reject(new Error('Failed to load StripeTerminal')); 72 | }); 73 | }); 74 | 75 | return stripePromise; 76 | }; 77 | -------------------------------------------------------------------------------- /tests/types/errors.test.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import {readFileSync} from 'fs'; 3 | 4 | import * as ts from 'typescript'; 5 | 6 | const parsedCommandLine = ts.getParsedCommandLineOfConfigFile( 7 | path.resolve(__dirname, 'tsconfig.json'), 8 | {}, 9 | { 10 | ...ts.sys, 11 | getCurrentDirectory: () => __dirname, 12 | onUnRecoverableConfigFileDiagnostic: () => {}, 13 | } 14 | )!; 15 | 16 | const getError = function(fileName: string) { 17 | const program = ts.createProgram([fileName], parsedCommandLine.options); 18 | const diagnostics = ts.getPreEmitDiagnostics(program); 19 | 20 | return ts.flattenDiagnosticMessageText(diagnostics[0].messageText, '\n'); 21 | }; 22 | 23 | describe('Typescript errors', () => { 24 | test.each([['createTerminalExtraProperty', 'extra_property']])( 25 | '%s', 26 | (fileName, expectedError) => { 27 | expect( 28 | getError(path.resolve(__dirname, `./fixtures/${fileName}.ts`)) 29 | ).toMatch(expectedError); 30 | } 31 | ); 32 | }); 33 | -------------------------------------------------------------------------------- /tests/types/fixtures/createTerminalExtraProperty.ts: -------------------------------------------------------------------------------- 1 | import {loadStripeTerminal} from '../../../types/index'; 2 | 3 | const main = async (): Promise => { 4 | // setup Terminal 5 | const StripeTerminal = (await loadStripeTerminal())!; 6 | 7 | const terminal = StripeTerminal.create({ 8 | onFetchConnectionToken: async () => 'test_token', 9 | extra_property: 'foo', 10 | }); 11 | 12 | terminal.discoverReaders(); 13 | }; 14 | 15 | main(); 16 | -------------------------------------------------------------------------------- /tests/types/fixtures/discoverReadersExtraProperty.ts: -------------------------------------------------------------------------------- 1 | import {loadStripeTerminal} from '../../../types/index'; 2 | 3 | const main = async (): Promise => { 4 | // setup Terminal 5 | const StripeTerminal = (await loadStripeTerminal())!; 6 | 7 | const terminal = StripeTerminal.create({ 8 | onFetchConnectionToken: async () => 'test_token', 9 | }); 10 | 11 | terminal.discoverReaders({ 12 | extraneous: 'property', 13 | }); 14 | }; 15 | 16 | main(); 17 | -------------------------------------------------------------------------------- /tests/types/index.ts: -------------------------------------------------------------------------------- 1 | import {assert, Has} from 'conditional-type-checks'; 2 | 3 | /* 4 | * This code will not run, but will be typechecked as a test. 5 | */ 6 | 7 | import { 8 | loadStripeTerminal, 9 | StripeTerminal as IStripeTerminal, 10 | DiscoverResult, 11 | Reader, 12 | IErrorResponse, 13 | ErrorResponse, 14 | SdkManagedPaymentIntent, 15 | } from '../../types/index'; 16 | 17 | declare const StripeTerminal: IStripeTerminal; 18 | 19 | const main = async () => { 20 | const stripePromise: Promise = loadStripeTerminal(); 21 | 22 | type SrcModule = typeof import('../../src/index'); 23 | 24 | const terminal = StripeTerminal.create({ 25 | onFetchConnectionToken: async () => 'test_token', 26 | }); 27 | 28 | terminal.overrideBaseURL('http://foo'); 29 | 30 | const discoverResult: 31 | | DiscoverResult 32 | | ErrorResponse = await terminal.discoverReaders({ 33 | device_type: 'foo', 34 | }); 35 | 36 | const reader: {reader: Reader} | ErrorResponse = await terminal.connectReader( 37 | { 38 | id: 'id', 39 | object: 'terminal.reader', 40 | device_type: 'verifone_P400', 41 | ip_address: 'address', 42 | serial_number: 'serial', 43 | livemode: false, 44 | device_sw_version: '0.0.0', 45 | label: 'foo', 46 | location: null, 47 | metadata: {}, 48 | status: 'online', 49 | } 50 | ); 51 | 52 | const connReader: Reader = terminal.getConnectedReader(); 53 | 54 | terminal.disconnectReader(); 55 | 56 | const clearResp: {} | ErrorResponse = terminal.clearCachedCredentials(); 57 | 58 | const clearDispResp: {} | ErrorResponse = terminal.clearReaderDisplay(); 59 | 60 | const setDispResp: {} | ErrorResponse = terminal.setReaderDisplay({ 61 | type: 'type', 62 | }); 63 | 64 | const payIntent: 65 | | {paymentIntent: SdkManagedPaymentIntent} 66 | | ErrorResponse = await terminal.collectPaymentMethod('pay_intent'); 67 | }; 68 | 69 | main(); 70 | -------------------------------------------------------------------------------- /tests/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "noEmit": true, 7 | "strict": true 8 | }, 9 | "include": ["./index.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /tests/versions/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | '@typescript-eslint/no-non-null-assertion': 0 3 | -------------------------------------------------------------------------------- /tests/versions/.gitignore: -------------------------------------------------------------------------------- 1 | package.json 2 | yarn.lock 3 | -------------------------------------------------------------------------------- /tests/versions/scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | # Ensure working directory is test directory 6 | cd "$(dirname "$0")/.." 7 | 8 | [ -f package.json ] && rm package.json 9 | yarn init -sy 10 | 11 | versions=( 12 | "next" 13 | "beta" 14 | "latest" 15 | "4.3.5" 16 | "4.2.4" 17 | "4.1.5" 18 | ) 19 | 20 | for version in ${versions[@]}; do 21 | echo "--- Testing with TypeScript version $version" 22 | yarn add -s --no-progress typescript@$version 23 | yarn run tsc 24 | done 25 | -------------------------------------------------------------------------------- /tests/versions/src/index.ts: -------------------------------------------------------------------------------- 1 | import {loadStripeTerminal} from '../../../types/index'; 2 | 3 | const main = async (): Promise => { 4 | // setup Terminal 5 | const StripeTerminal = (await loadStripeTerminal())!; 6 | 7 | const terminal = StripeTerminal.create({ 8 | onFetchConnectionToken: async () => 'test_token', 9 | }); 10 | 11 | terminal.discoverReaders(); 12 | }; 13 | 14 | main(); 15 | -------------------------------------------------------------------------------- /tests/versions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "noEmit": true, 6 | "strict": true, 7 | "moduleResolution": "node", 8 | "types": ["../.."], 9 | "skipLibCheck": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // Let Babel deal with transpiling new language features 4 | "target": "esnext", 5 | 6 | // These are overridden by the Rollup plugin, but are left here in case you 7 | // run `tsc` directly for typechecking or debugging purposes 8 | "outDir": "./dist", 9 | "rootDir": "./src", 10 | 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noEmit": true, 14 | "allowJs": false, 15 | "declaration": false, 16 | "removeComments": false, 17 | "strict": true, 18 | "forceConsistentCasingInFileNames": true 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /types/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | '@typescript-eslint/triple-slash-reference': 0 3 | '@typescript-eslint/adjacent-overload-signatures': 0 4 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { 3 | Terminal, 4 | TerminalProps, 5 | PaymentStatus, 6 | ConnectionStatus, 7 | OutputLogLevel, 8 | } from './terminal'; 9 | 10 | export * from './terminal'; 11 | 12 | export interface StripeTerminal { 13 | create(props: TerminalProps): Terminal; 14 | PaymentStatus: PaymentStatus; 15 | ConnectionStatus: ConnectionStatus; 16 | OutputLogLevel: OutputLogLevel; 17 | } 18 | 19 | export const loadStripeTerminal: () => Promise; 20 | 21 | declare global { 22 | interface Window { 23 | // Terminal's sdk.js must be loaded directly from https://js.stripe.com/v3, which 24 | // places a `StripeTerminal` object on the window 25 | StripeTerminal?: StripeTerminal; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /types/proto.d.ts: -------------------------------------------------------------------------------- 1 | /** Properties of a RequestedCardPresent. */ 2 | interface IRequestedCardPresent { 3 | /** Type of card present information */ 4 | type?: string | null; 5 | 6 | /** Method used by POS to read the card */ 7 | read_method?: string | null; 8 | 9 | /** Reason for card swipe */ 10 | swipe_reason?: string | null; 11 | 12 | /** Encrypted or unencrypted track 2 data (depending on "type" field) */ 13 | track_2?: string | null; 14 | 15 | /** Processing method */ 16 | emv_processing_method?: string | null; 17 | 18 | /** Encrypted or unencrypted EMV data (depending on "type" field) */ 19 | emv_data?: string | null; 20 | 21 | /** The PIN block used in transactions backed by PIN */ 22 | pin_block?: string | null; 23 | 24 | /** Key Serial Number for the PIN block encryption */ 25 | pin_block_ksn?: string | null; 26 | 27 | /** Reader ID from activate */ 28 | reader?: string | null; 29 | 30 | /** Key type used to encrypt track_2 */ 31 | track_2_key_type?: string | null; 32 | 33 | /** Key ID of key used to encrypt track_2 */ 34 | track_2_key_id?: string | null; 35 | 36 | /** KSN used ot encrypt track_2 */ 37 | track_2_ksn?: string | null; 38 | } 39 | /** Properties of a RequestedPaymentMethod. */ 40 | interface IRequestedPaymentMethod { 41 | /** Type of payment method (e.g. "card_present") */ 42 | type?: string | null; 43 | 44 | /** Map of card present parameters */ 45 | card_present?: IRequestedCardPresent | null; 46 | 47 | /** Interac card present */ 48 | interac_present?: IRequestedCardPresent | null; 49 | } 50 | /** Properties of a RefundChargeRequest. */ 51 | interface IRefundChargeRequest { 52 | /** RefundChargeRequest charge */ 53 | charge?: string | null; 54 | 55 | /** RefundChargeRequest reason */ 56 | reason?: string | null; 57 | 58 | /** RefundChargeRequest refund_application_fee */ 59 | refund_application_fee?: boolean | null; 60 | 61 | /** RefundChargeRequest reverse_transfer */ 62 | reverse_transfer?: boolean | null; 63 | 64 | /** RefundChargeRequest payment_method_data */ 65 | payment_method_data?: IRequestedPaymentMethod | null; 66 | 67 | /** RefundChargeRequest amount */ 68 | amount?: number | null; 69 | } 70 | /** Properties of a TipOption. */ 71 | interface ITipOption { 72 | /** REQUIRED: Amount of this tip option */ 73 | amount?: number | null; 74 | 75 | /** Descriptor of the amount, displayed in the button */ 76 | label?: string | null; 77 | } 78 | /** Properties of a TipConfiguration. */ 79 | export interface ITipConfiguration { 80 | /** List of at most 3 options */ 81 | options?: ITipOption[] | null; 82 | 83 | /** Hide the custom amount button */ 84 | hide_custom_amount?: boolean | null; 85 | } 86 | /** Properties of a TipSelection. */ 87 | interface ITipSelection { 88 | /** Amount associated with the selection */ 89 | amount?: number | null; 90 | } 91 | /** CreditCardBrand enum. */ 92 | type CreditCardBrand = 93 | | 'INVALID_CREDIT_CARD_BRAND' 94 | | 'UNKNOWN_CREDIT' 95 | | 'AMERICAN_EXPRESS' 96 | | 'DINERS' 97 | | 'DISCOVER' 98 | | 'JCB' 99 | | 'MASTERCARD' 100 | | 'VISA' 101 | | 'CUP'; 102 | 103 | /** CardEntryMethod enum. */ 104 | type CardEntryMethod = 105 | | 'INVALID_ENTRY_METHOD' 106 | | 'CHIP_READ' 107 | | 'CONTACTLESS' 108 | | 'FSWIPE' 109 | | 'KEYED' 110 | | 'SWIPED' 111 | | 'BARCODE_READ'; 112 | /** Properties of a CardPaymentMethod. */ 113 | interface ICardPaymentMethod { 114 | /** Masked card data */ 115 | masked_pan?: string | null; 116 | 117 | /** The card expiration date */ 118 | expiration_date?: string | null; 119 | 120 | /** Brand of credit card tender, determined by BIN table lookup */ 121 | card_brand?: CreditCardBrand | null; 122 | 123 | /** Entry method of payment */ 124 | card_entry_method?: CardEntryMethod | null; 125 | } 126 | /** Properties of a PaymentMethod. */ 127 | export interface IPaymentMethod { 128 | /** PaymentMethod card_payment */ 129 | card_payment?: ICardPaymentMethod | null; 130 | 131 | /** Tip selection chosen by the cardholder */ 132 | tip_selection?: ITipSelection | null; 133 | } 134 | 135 | interface IPaymentIntentExpandedMethod { 136 | 137 | /** Unique identifier for the Payment Intent object */ 138 | id?: (string|null); 139 | 140 | /** Time at which the Payment Intent object was created. Measured in seconds since the Unix epoch */ 141 | created?: (number|null); 142 | 143 | /** Status of this PaymentIntent */ 144 | status?: (string|null); 145 | 146 | /** Amount intended to be collected by this Payment Intent */ 147 | amount?: (number|null); 148 | 149 | /** Three-letter ISO currency code, in lowercase. Must be a supported currency. */ 150 | currency?: (string|null); 151 | 152 | /** Card present payment source field map */ 153 | source?: (ISource|null); 154 | 155 | /** An arbitrary string to be displayed on your customer's credit card statement. */ 156 | statement_descriptor?: (string|null); 157 | 158 | /** An arbitrary string attached to the object. Often useful for displaying to users. */ 159 | description?: (string|null); 160 | 161 | /** Email address that the receipt for the resulting payment will be sent to. */ 162 | receipt_email?: (string|null); 163 | 164 | /** Whether this charge was made in live mode or not */ 165 | livemode?: (boolean|null); 166 | 167 | /** Last payment error on a charge (if retrieved) */ 168 | last_payment_error?: (IErrorResponse|null); 169 | 170 | /** Meta data in JSON format */ 171 | metadata?: ({ [k: string]: string }|null); 172 | 173 | /** Charges associated with the payment intent */ 174 | charges?: (ICharges|null); 175 | 176 | /** ID for payment method */ 177 | payment_method?: (IPaymentMethodReadReusableResponse|null); 178 | 179 | /** Amount that can be captured */ 180 | amount_capturable?: (number|null); 181 | 182 | /** Amount that was collected */ 183 | amount_received?: (number|null); 184 | 185 | /** The amount of the application fee (if any) for the resulting payment */ 186 | application_fee_amount?: (number|null); 187 | 188 | /** Populated when status is canceled, this is the time at which the PaymentIntent was canceled. */ 189 | canceled_at?: (number|null); 190 | 191 | /** Controls when the funds will be captured from the customer's account */ 192 | capture_method?: (Method|null); 193 | 194 | /** The client secret of this PaymentIntent. Used for client-side retrieval using a publishable key. */ 195 | client_secret?: (string|null); 196 | 197 | /** The confirmation method */ 198 | confirmation_method?: (Method|null); 199 | 200 | /** The customer of this payment intent */ 201 | customer?: (string|null); 202 | 203 | /** A string that identifies this intent as part of a group. */ 204 | transfer_group?: (string|null); 205 | } 206 | 207 | /** Properties of a PaymentMethod. */ 208 | export interface IPaymentMethodReadReusableResponse { 209 | /** Unique identifier for the Payment Method object */ 210 | id?: string | null; 211 | 212 | /** Time at which the Payment Method object was created. Measured in seconds since the Unix epoch */ 213 | created?: number | null; 214 | 215 | /** Customer ID */ 216 | customer?: string | null; 217 | 218 | /** Whether this charge was made in live mode or not */ 219 | livemode?: boolean | null; 220 | 221 | /** Meta data in JSON format */ 222 | metadata?: {[k: string]: string} | null; 223 | 224 | /** PaymentMethod type */ 225 | type?: string | null; 226 | 227 | /** Card representation of payment method */ 228 | card?: ICardPaymentMethodReadReusableResponse | null; 229 | } 230 | 231 | /** Properties of a CardPaymentMethod. */ 232 | interface ICardPaymentMethodReadReusableResponse { 233 | /** Masked card data */ 234 | masked_pan?: string | null; 235 | 236 | /** The card expiration date */ 237 | expiration_date?: string | null; 238 | 239 | /** Brand of credit card tender, determined by BIN table lookup */ 240 | card_brand?: CreditCardBrand | null; 241 | 242 | /** Entry method of payment */ 243 | card_entry_method?: CardEntryMethod | null; 244 | } 245 | 246 | /** Properties of an ErrorResponse. */ 247 | export interface IErrorResponse { 248 | /** The type of error returned. */ 249 | type?: string | null; 250 | 251 | /** ID of failed charge */ 252 | charge?: string | null; 253 | 254 | /** For some errors that could be handled programmatically, a short string indicating the error code reported. (https://stripe.com/docs/error-codes) */ 255 | code?: string | null; 256 | 257 | /** For card errors resulting from a card issuer decline, a short string indicating the card issuer’s reason for the decline if they provide one. (https://stripe.com/docs/declines#issuer-declines) */ 258 | decline_code?: string | null; 259 | 260 | /** A URL to more information about the error code reported. */ 261 | doc_url?: string | null; 262 | 263 | /** A human-readable message providing more details about the error. For card errors, these messages can be shown to your users. */ 264 | message?: string | null; 265 | 266 | /** If the error is parameter-specific, the parameter related to the error. For example, you can use this to display a message near the correct form field. */ 267 | param?: string | null; 268 | 269 | /** Source used for the error */ 270 | source?: ISource | null; 271 | 272 | /** Payment intent used for the error */ 273 | payment_intent?: IPaymentIntent | null; 274 | } 275 | /** Properties of an Owner. */ 276 | export interface IOwner { 277 | /** Owner address */ 278 | address?: string | null; 279 | 280 | /** Owner email */ 281 | email?: string | null; 282 | 283 | /** Owner name */ 284 | name?: string | null; 285 | 286 | /** Owner phone */ 287 | phone?: string | null; 288 | 289 | /** Owner verified_address */ 290 | verified_address?: string | null; 291 | 292 | /** Owner verified_email */ 293 | verified_email?: string | null; 294 | 295 | /** Owner verified_name */ 296 | verified_name?: string | null; 297 | 298 | /** Owner verified_phone */ 299 | verified_phone?: string | null; 300 | } 301 | /** Properties of a PaymentMethodDetails. */ 302 | export interface IPaymentMethodDetails { 303 | /** Payment Method type (e.g. "card_present") */ 304 | type?: string | null; 305 | 306 | /** PaymentMethodDetails card_present */ 307 | card_present?: ICardPresent | null; 308 | 309 | /** PaymentMethodDetails interac_present */ 310 | interac_present?: ICardPresent | null; 311 | 312 | /** PaymentMethodDetails wechat_pay */ 313 | wechat_pay?: IWechatPay | null; 314 | 315 | /** PaymentMethodDetails affirm */ 316 | affirm?: IAffirm | null; 317 | } 318 | /** Properties of a Refund. */ 319 | interface IRefund { 320 | /** Refund id */ 321 | id?: string | null; 322 | 323 | /** Refund amount */ 324 | amount?: number | null; 325 | 326 | /** Refund charge */ 327 | charge?: string | null; 328 | 329 | /** Time at which the Refund object was created. Measured in seconds since the Unix epoch */ 330 | created?: number | null; 331 | 332 | /** Three-letter ISO currency code, in lowercase. Must be a supported currency */ 333 | currency?: string | null; 334 | 335 | /** Meta data in JSON format */ 336 | metadata?: {[k: string]: string} | null; 337 | 338 | /** Reason for refund */ 339 | reason?: string | null; 340 | 341 | /** Status of refund */ 342 | status?: string | null; 343 | 344 | /** Actual details of the payment method */ 345 | payment_method_details?: IPaymentMethodDetails | null; 346 | 347 | /** If the refund failed, the reason for refund failure if known. */ 348 | failure_reason?: string | null; 349 | } 350 | /** Properties of a Refunds. */ 351 | interface IRefunds { 352 | /** Refunds data */ 353 | data?: IRefund[] | null; 354 | 355 | /** Refunds has_more */ 356 | has_more?: boolean | null; 357 | 358 | /** Refunds total_count */ 359 | total_count?: number | null; 360 | } 361 | /** Properties of a Charge. */ 362 | interface ICharge { 363 | /** ID for charge */ 364 | id?: string | null; 365 | 366 | /** Amount that is associated with the charge */ 367 | amount?: number | null; 368 | 369 | /** Amount that is associated with a refund of the charge */ 370 | amount_refunded?: number | null; 371 | 372 | /** Whether this charge has been captured */ 373 | captured?: boolean | null; 374 | 375 | /** Whether this charge has been refunded */ 376 | refunded?: boolean | null; 377 | 378 | /** Time at which the Charge object was created. Measured in seconds since the Unix epoch */ 379 | created?: number | null; 380 | 381 | /** Three-letter ISO currency code, in lowercase. Must be a supported currency. */ 382 | currency?: string | null; 383 | 384 | /** An arbitrary string attached to the object. Often useful for displaying to users. */ 385 | description?: string | null; 386 | 387 | /** An arbitrary string to be displayed on your customer's credit card statement. */ 388 | statement_descriptor?: string | null; 389 | 390 | /** Email address that the receipt for the resulting payment will be sent to. */ 391 | receipt_email?: string | null; 392 | 393 | /** Failure code if the charge was declined */ 394 | failure_code?: string | null; 395 | 396 | /** Message associated with the failure code */ 397 | failure_message?: string | null; 398 | 399 | /** Whether this charge was made in live mode or not */ 400 | livemode?: boolean | null; 401 | 402 | /** Meta data in JSON format */ 403 | metadata?: {[k: string]: string} | null; 404 | 405 | /** Source associated with the charge */ 406 | source?: ISource | null; 407 | 408 | /** Payment intent ID associated with the charge */ 409 | payment_intent?: string | null; 410 | 411 | /** Status of the charge */ 412 | status?: string | null; 413 | 414 | /** Payment method ID */ 415 | payment_method?: string | null; 416 | 417 | /** Actual details of the payment method */ 418 | payment_method_details?: IPaymentMethodDetails | null; 419 | 420 | /** Whether the charge was paid */ 421 | paid?: boolean | null; 422 | 423 | /** Receipt URL */ 424 | receipt_url?: string | null; 425 | 426 | /** Refunds associated with charge */ 427 | refunds?: IRefunds | null; 428 | } 429 | /** Properties of a Charges. */ 430 | interface ICharges { 431 | /** Charges data */ 432 | data?: ICharge[] | null; 433 | 434 | /** Charges has_more */ 435 | has_more?: boolean | null; 436 | 437 | /** Charges total_count */ 438 | total_count?: number | null; 439 | } 440 | /** Properties of a CardPresent. */ 441 | interface ICardPresent { 442 | /** The last four digits of the card. */ 443 | last4?: string | null; 444 | 445 | /** Card brand */ 446 | brand?: string | null; 447 | 448 | /** Customer's signature if signed */ 449 | evidence_customer_signature?: string | null; 450 | 451 | /** Method used by POS to read the card */ 452 | read_method?: string | null; 453 | 454 | /** The EMV authorization response payload */ 455 | emv_auth_data?: string | null; 456 | 457 | /** The EMV authorization response code */ 458 | authorization_response_code?: string | null; 459 | 460 | /** AID */ 461 | dedicated_file_name?: string | null; 462 | 463 | /** AID name */ 464 | application_preferred_name?: string | null; 465 | 466 | /** TVR */ 467 | terminal_verification_results?: string | null; 468 | 469 | /** TSI */ 470 | transaction_status_information?: string | null; 471 | 472 | /** CVM type */ 473 | cvm_type?: string | null; 474 | 475 | /** CardPresent reader */ 476 | reader?: string | null; 477 | 478 | /** CardPresent fingerprint */ 479 | fingerprint?: string | null; 480 | 481 | /** CardPresent authorization_code */ 482 | authorization_code?: string | null; 483 | 484 | /** CardPresent location */ 485 | location?: string | null; 486 | } 487 | 488 | interface IWechatPay { 489 | 490 | /** WechatPay reader */ 491 | reader?: string | null; 492 | 493 | /** WechatPay location */ 494 | location?: string | null; 495 | 496 | /** WeChat Pay transactionId */ 497 | transactionId?: string | null; 498 | } 499 | 500 | interface IAffirm { 501 | 502 | /** Affirm reader */ 503 | reader?: string | null; 504 | 505 | /** Affirm location */ 506 | location?: string | null; 507 | 508 | /** Affirm transactionId */ 509 | transactionId?: string | null; 510 | } 511 | 512 | /** Properties of a Source. */ 513 | export interface ISource { 514 | /** Unique identifier for the source card object. */ 515 | id?: string | null; 516 | 517 | /** Source type (e.g. "card_present") */ 518 | type?: string | null; 519 | 520 | /** Card payment method */ 521 | card_present?: ICardPresent | null; 522 | 523 | /** Interac version of card present */ 524 | interac_present?: ICardPresent | null; 525 | 526 | /** Meta data in JSON format */ 527 | metadata?: {[k: string]: string} | null; 528 | 529 | /** Owner data */ 530 | owner?: IOwner | null; 531 | } 532 | export interface IPaymentIntent { 533 | /** Unique identifier for the Payment Intent object */ 534 | id?: string | null; 535 | 536 | /** Time at which the Payment Intent object was created. Measured in seconds since the Unix epoch */ 537 | created?: number | null; 538 | 539 | /** Status of this PaymentIntent */ 540 | status?: string | null; 541 | 542 | /** Amount intended to be collected by this Payment Intent */ 543 | amount?: number | null; 544 | 545 | /** Three-letter ISO currency code, in lowercase. Must be a supported currency. */ 546 | currency?: string | null; 547 | 548 | /** Card present payment source field map */ 549 | source?: ISource | null; 550 | 551 | /** An arbitrary string to be displayed on your customer's credit card statement. */ 552 | statement_descriptor?: string | null; 553 | 554 | /** An arbitrary string attached to the object. Often useful for displaying to users. */ 555 | description?: string | null; 556 | 557 | /** Email address that the receipt for the resulting payment will be sent to. */ 558 | receipt_email?: string | null; 559 | 560 | /** Whether this charge was made in live mode or not */ 561 | livemode?: boolean | null; 562 | 563 | /** Last payment error on a charge (if retrieved) */ 564 | last_payment_error?: IErrorResponse | null; 565 | 566 | /** Meta data in JSON format */ 567 | metadata?: {[k: string]: string} | null; 568 | 569 | /** Charges associated with the payment intent */ 570 | charges?: ICharges | null; 571 | 572 | /** ID for payment method */ 573 | payment_method?: string | null; 574 | 575 | /** PaymentMethod types supported on the payment intent */ 576 | payment_method_types?: (string[]|null); 577 | } 578 | 579 | export interface ISetupIntent { 580 | /** Unique identifier for the object. */ 581 | id?: (string|null); 582 | 583 | /** The client secret of this SetupIntent. Used for client-side retrieval using a publishable key. */ 584 | client_secret?: (string|null); 585 | 586 | /** ID of the Customer this SetupIntent belongs to, if one exists. */ 587 | customer?: (string|null); 588 | 589 | /** An arbitrary string attached to the object. Often useful for displaying to users. */ 590 | description?: (string|null); 591 | 592 | /** The error encountered in the previous SetupIntent confirmation. */ 593 | last_setup_error?: ILastSetupError | null; 594 | 595 | /** Meta data in JSON format */ 596 | metadata?: ({ [k: string]: string }|null); 597 | 598 | /** If present, this property tells you what actions you need to take in order for your customer to continue payment setup. */ 599 | next_action?: INextAction | null; 600 | 601 | /** ID of the payment method used with this SetupIntent. */ 602 | payment_method?: (string|null); 603 | 604 | /** The list of payment method types (e.g. card) that this SetupIntent is allowed to set up. */ 605 | payment_method_types?: (string[]|null); 606 | 607 | /** Status of this SetupIntent, one of requires_payment_method, requires_confirmation, requires_action, processing, canceled, or succeeded. */ 608 | status?: (string|null); 609 | 610 | /** Indicates how the payment method is intended to be used in the future. */ 611 | usage?: (string|null); 612 | 613 | /** Time at which the object was created. Measured in seconds since the Unix epoch. */ 614 | created?: (number|null); 615 | 616 | /** The most recent SetupAttempt for this SetupIntent. */ 617 | latest_attempt?: (ISetupAttempt|null); 618 | 619 | /** Has the value true if the object exists in live mode or the value false if the object exists in test mode. */ 620 | livemode?: (boolean|null); 621 | 622 | /** ID of the multi use Mandate generated by the SetupIntent. */ 623 | mandate?: (string|null); 624 | 625 | /** ID of the single_use Mandate generated by the SetupIntent. */ 626 | single_use_mandate?: (string|null); 627 | 628 | /** ID of the Connect application that created the SetupIntent. */ 629 | application?: (string|null); 630 | 631 | /** The account (if any) for which the setup is intended. */ 632 | on_behalf_of?: (string|null); 633 | 634 | /** Payment-method-specific configuration for this SetupIntent. */ 635 | payment_method_options?: (IPaymentMethodOptions|null); 636 | } 637 | 638 | /** Properties of a SetupAttempt. */ 639 | export interface ISetupAttempt { 640 | 641 | /** Unique identifier for the object. */ 642 | id?: (string|null); 643 | 644 | /** String representing the object’s type: "setup_attempt" */ 645 | object?: (string|null); 646 | 647 | /** ID of the Connect application that created the SetupIntent. */ 648 | application?: (string|null); 649 | 650 | /** Time at which the object was created. Measured in seconds since the Unix epoch. */ 651 | created?: (number|null); 652 | 653 | /** ID of the Customer this SetupIntent belongs to, if one exists. */ 654 | customer?: (string|null); 655 | 656 | /** Has the value true if the object exists in live mode or the value false if the object exists in test mode. */ 657 | livemode?: (boolean|null); 658 | 659 | /** The account (if any) for which the setup is intended. */ 660 | on_behalf_of?: (string|null); 661 | 662 | /** ID of the payment method used with this SetupAttempt. */ 663 | payment_method?: (string|null); 664 | 665 | /** Details about the payment method at the time of SetupIntent confirmation. */ 666 | payment_method_details?: (IPaymentMethodDetails|null); 667 | 668 | /** The error encountered during this attempt to confirm the SetupIntent, if any. */ 669 | setup_error?: (ISetupError|null); 670 | 671 | /** ID of the SetupIntent that this attempt belongs to. */ 672 | setup_intent?: (string|null); 673 | 674 | /** Status of this SetupAttempt, one of requires_confirmation, requires_action, processing, succeeded, failed, or abandoned. */ 675 | status?: (string|null); 676 | 677 | /** The value of usage on the SetupIntent at the time of this confirmation, one of off_session or on_session. */ 678 | usage?: (string|null); 679 | } 680 | 681 | /** Properties of a SetupError. */ 682 | export interface ISetupError { 683 | 684 | /** For some errors that could be handled programmatically, a short string indicating the error code reported. */ 685 | code?: (string|null); 686 | 687 | /** For card errors resulting from a card issuer decline, a short string indicating the card issuer’s reason for the decline if they provide one. */ 688 | decline_code?: (string|null); 689 | 690 | /** A URL to more information about the error code reported. */ 691 | doc_url?: (string|null); 692 | 693 | /** A human-readable message providing more details about the error. For card errors, these messages can be shown to your users. */ 694 | message?: (string|null); 695 | 696 | /** If the error is parameter-specific, the parameter related to the error. For example, you can use this to display a message near the correct form field. */ 697 | param?: (string|null); 698 | 699 | /** The PaymentMethod object for errors returned on a request involving a PaymentMethod. */ 700 | payment_method?: (IPaymentMethod|null); 701 | 702 | /** If the error is specific to the type of payment method, the payment method type that had a problem. This field is only populated for invoice-related errors. */ 703 | payment_method_type?: (string|null); 704 | 705 | /** The type of error returned. One of api_connection_error, api_error, authentication_error, card_error, idempotency_error, invalid_request_error, or rate_limit_error */ 706 | type?: (string|null); 707 | } 708 | 709 | /** Properties of an ActivateTerminalRequest. */ 710 | export interface IActivateTerminalRequest { 711 | /** An activation token obtained from Stripe that can be used to activate the reader */ 712 | pos_activation_token?: string | null; 713 | 714 | /** The fingerprint for the POS authenticating to rabbit */ 715 | pos_device_id?: string | null; 716 | 717 | /** The terminal hardware information */ 718 | pos_hardware_info?: any | null; 719 | 720 | /** The terminal software information */ 721 | pos_software_info?: any | null; 722 | 723 | /** Provide RPC error if reader is currently in use */ 724 | fail_if_in_use?: boolean | null; 725 | 726 | /** The logical identity of terminal (i.e. lane number) authenticating to rabbit. */ 727 | terminal_id?: string | null; 728 | 729 | /** ActivateTerminalRequest terminal_ip */ 730 | terminal_ip?: string | null; 731 | 732 | /** The store name associated with the POS */ 733 | store_name?: string | null; 734 | 735 | /** The store address associated with the POS */ 736 | store_address?: any | null; 737 | } 738 | 739 | /** Properties of a SetReaderDisplayRequest. */ 740 | export interface ISetReaderDisplayRequest { 741 | /** SetReaderDisplayRequest type */ 742 | type?: string | null; 743 | 744 | /** SetReaderDisplayRequest cart */ 745 | cart?: ICart | null; 746 | } 747 | 748 | interface ICart { 749 | /** All line items in the basket */ 750 | line_items?: ILineItem[] | null; 751 | 752 | /** Modifiers that have been applied to the basket. */ 753 | modifiers?: IModifier[] | null; 754 | 755 | /** Any discounts that have been added to the basket. */ 756 | discounts?: IDiscount[] | null; 757 | 758 | /** Tenders that have been charged/refunded */ 759 | tenders?: ITender[] | null; 760 | 761 | /** Total amount of tax */ 762 | tax?: number | null; 763 | 764 | /** Total balance of cart due */ 765 | total?: number | null; 766 | 767 | /** The currency of the basket (i.e. USD or AUD). */ 768 | currency?: string | null; 769 | } 770 | 771 | /** Properties of a LineItem. */ 772 | interface ILineItem { 773 | /** LineItem quantity */ 774 | quantity?: number | null; 775 | 776 | /** A detailed description of the item. */ 777 | description?: string | null; 778 | 779 | /** This is equal to extended_price - discount + modifiers */ 780 | amount?: number | null; 781 | 782 | /** The discounts that have been applied to this line item. */ 783 | discounts?: IDiscount[] | null; 784 | 785 | /** The modifiers that have been applied to this line item. */ 786 | modifiers?: IModifier[] | null; 787 | } 788 | 789 | interface IModifier { 790 | /** A detailed description of discount. */ 791 | description?: string | null; 792 | 793 | /** Amount in cents of the modification. */ 794 | amount?: number | null; 795 | } 796 | /** Properties of a Discount. */ 797 | interface IDiscount { 798 | /** A detailed description of discount. */ 799 | description?: string | null; 800 | 801 | /** The amount and mechanism of the discount */ 802 | amount?: number | null; 803 | } 804 | /** Properties of a Tender. */ 805 | interface ITender { 806 | /** A detailed description of tender. */ 807 | description?: string | null; 808 | 809 | /** Amount in cents of the tender. */ 810 | amount?: number | null; 811 | } 812 | 813 | interface ILastSetupError { 814 | 815 | /** For some errors that could be handled programmatically, a short string indicating the error code reported. */ 816 | code?: (string|null); 817 | 818 | /** For card errors resulting from a card issuer decline, a short string indicating the card issuer’s reason for the decline if they provide one. */ 819 | decline_code?: (string|null); 820 | 821 | /** A URL to more information about the error code reported. */ 822 | doc_url?: (string|null); 823 | 824 | /** A human-readable message providing more details about the error. For card errors, these messages can be shown to users. */ 825 | message?: (string|null); 826 | 827 | /** If the error is parameter-specific, the parameter related to the error. For example, you can use this to display a message near the correct form field. */ 828 | param?: (string|null); 829 | 830 | /** The PaymentMethod object for errors returned on a request involving a PaymentMethod. */ 831 | payment_method?: (IPaymentMethod|null); 832 | 833 | /** One of: api_connection_error, api_error, authentication_error, card_error, idempotency_error, invalid_request_error, or rate_limit_error */ 834 | type?: (string|null); 835 | } 836 | 837 | interface INextAction { 838 | 839 | /** Contains instructions for authenticating by redirecting your customer to another page or application. */ 840 | redirect_to_url?: (IRedirectToUrl|null); 841 | 842 | /** Type of the next action to perform, one of redirect_to_url or use_stripe_sdk. */ 843 | type?: (string|null); 844 | 845 | /** When confirming a SetupIntent with Stripe.js, Stripe.js depends on the contents of this dictionary to invoke authentication flows. */ 846 | use_stripe_sdk?: ({ [k: string]: string }|null); 847 | } 848 | 849 | interface IRedirectToUrl { 850 | 851 | /** If the customer does not exit their browser while authenticating, they will be redirected to this specified URL after completion. */ 852 | return_url?: (string|null); 853 | 854 | /** The URL you must redirect your customer to in order to authenticate. */ 855 | url?: (string|null); 856 | } 857 | interface IPaymentMethodOptions { 858 | 859 | /** PaymentMethodOptions card */ 860 | card?: (ICardOptions|null); 861 | } 862 | 863 | interface ICardOptions { 864 | 865 | /** CardOptions request_three_d_secure */ 866 | request_three_d_secure?: (Request3dSecureType|null); 867 | } 868 | 869 | type Request3dSecureType = "automatic"| "any"; 870 | 871 | /** Method enum. */ 872 | type Method = 873 | "automatic"| "manual"; 874 | 875 | export type ITextToSpeechStatus = 'off' | 'headphones' | 'speakers'; 876 | 877 | export interface IAccessibilitySettings { 878 | textToSpeechStatus: ITextToSpeechStatus; 879 | } 880 | 881 | export interface IReaderSettings { 882 | accessibilitySettings: IAccessibilitySettings | IErrorResponse; 883 | } 884 | 885 | export interface IAccessibilityParameters { 886 | enableTextToSpeechSpeakers: boolean; 887 | } 888 | 889 | export interface ISetReaderSettingsRequest { 890 | accessibility_parameters?: null | IAccessibilityParameters; 891 | } 892 | -------------------------------------------------------------------------------- /types/terminal.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import Stripe from 'stripe'; 3 | 4 | import { 5 | IActivateTerminalRequest, 6 | IErrorResponse, 7 | IPaymentMethod as SdkIPaymentMethod, 8 | IPaymentMethodReadReusableResponse, 9 | IRefundChargeRequest, 10 | ISetReaderDisplayRequest, 11 | ITipConfiguration, 12 | IRefund, 13 | IPaymentIntentExpandedMethod, 14 | IReaderSettings, 15 | ISetReaderSettingsRequest, 16 | IAccessibilitySettings, 17 | IAccessibilityParameters, 18 | ITextToSpeechStatus, 19 | } from './proto'; 20 | 21 | export { 22 | IActivateTerminalRequest, 23 | IErrorResponse, 24 | IPaymentMethodReadReusableResponse, 25 | IPaymentMethod, 26 | IRefundChargeRequest, 27 | ISetReaderDisplayRequest, 28 | ITipConfiguration, 29 | IRefund, 30 | IReaderSettings, 31 | ISetReaderSettingsRequest, 32 | IAccessibilitySettings, 33 | IAccessibilityParameters, 34 | ITextToSpeechStatus, 35 | }; 36 | 37 | export enum PaymentStatus { 38 | NOT_READY = 'not_ready', 39 | READY = 'ready', 40 | WAITING_FOR_INPUT = 'waiting_for_input', 41 | PROCESSING = 'processing', 42 | } 43 | 44 | export enum ConnectionStatus { 45 | CONNECTING = 'connecting', 46 | CONNECTED = 'connected', 47 | NOT_CONNECTED = 'not_connected', 48 | } 49 | 50 | export enum OutputLogLevel { 51 | NONE = 'none', 52 | VERBOSE = 'verbose', 53 | } 54 | 55 | export enum AllowRedisplay { 56 | ALWAYS = 'always', 57 | LIMITED = 'limited', 58 | UNSPECIFIED = 'unspecified', 59 | } 60 | 61 | export declare type ConnectionToken = string; 62 | export declare type FetchConnectionTokenFn = () => Promise; 63 | 64 | export declare type ISetReaderDisplayResponse = Record; 65 | export declare type ICancelResponse = Record; 66 | export declare type IClearCachedCredentialsResponse = Record; 67 | export declare type IClearReaderDisplayResponse = Record; 68 | export declare type ICollectRefundPaymentMethodResponse = Record; 69 | export declare type IDisconnectResponse = Record; 70 | 71 | interface IPaymentMethod extends SdkIPaymentMethod { 72 | payment_intent?: IPaymentIntentExpandedMethod | null; 73 | } 74 | 75 | export interface StatusEvent { 76 | status: T; 77 | } 78 | export interface DisconnectEvent { 79 | error?: ExposedError; 80 | } 81 | export declare type ConnectionStatusEvent = StatusEvent; 82 | export declare type PaymentStatusEvent = StatusEvent; 83 | export declare type EventHandler = (event: T) => void; 84 | export interface TerminalCallbacks { 85 | onFetchConnectionToken: FetchConnectionTokenFn; 86 | onUnexpectedReaderDisconnect?: EventHandler; 87 | onConnectionStatusChange?: EventHandler; 88 | onPaymentStatusChange?: EventHandler; 89 | } 90 | export interface ReaderBehaviors { 91 | allowCustomerCancel?: boolean; 92 | } 93 | export interface TerminalOptions { 94 | logLevel?: OutputLogLevel; 95 | simulatorBaseUrl?: string; 96 | readerBehavior?: ReaderBehaviors; 97 | } 98 | export declare type TerminalProps = TerminalOptions & TerminalCallbacks; 99 | 100 | export declare type PaymentIntentClientSecret = string; 101 | 102 | export declare type DeviceType = Stripe.Terminal.Reader.DeviceType; 103 | 104 | export declare type Reader = Stripe.Terminal.Reader; 105 | 106 | export declare type IPaymentIntent = Stripe.PaymentIntent; 107 | export declare type ISetupIntent = Stripe.SetupIntent; 108 | 109 | export interface ISdkManagedPaymentIntent extends IPaymentIntent { 110 | sdk_payment_details: IPaymentMethod; 111 | } 112 | export type SdkManagedPaymentIntent = ISdkManagedPaymentIntent; 113 | 114 | export interface ICollectConfig { 115 | // Bypass tipping selection if it would have otherwise been shown. 116 | // For more information, see the official Stripe docs: [On Reader Tipping](https://stripe.com/docs/terminal/features/collecting-tips/on-reader) 117 | skip_tipping?: boolean | null; 118 | tipping?: ITippingConfig | null; 119 | // set to true to return the expanded payment_intent. 120 | update_payment_intent?: boolean | null; 121 | 122 | // the ID of the payment intent to return back. 123 | payment_intent_id?: string | null; 124 | 125 | // Optional notice to display on the payment collection screen to inform the customer of a surcharge. 126 | surcharge_notice?: string | null; 127 | 128 | // Request ability to offer dynamic currency conversion (DCC) if the card is eligible. 129 | request_dynamic_currency_conversion?: boolean | null; 130 | 131 | // Required if `setup_future_usage` is set; otherwise, it defaults to `unspecified`. 132 | // An enum value indicating whether future checkout flows can show this payment method to its customer. 133 | allow_redisplay?: AllowRedisplay | null; 134 | 135 | // Collect and process the payment as a Mail Order/Telephone Order payment. Contact Stripe support to enable this feature on your account. 136 | // For more information, see the official Stripe docs: [Mail Order Telephone Order transactions](https://support.stripe.com/questions/mail-order-telephone-order-(moto)-transactions-when-to-categorize-transactions-as-moto) 137 | moto?: boolean | null; 138 | } 139 | 140 | // Contains per-transaction configuration information relevant to collecting tips 141 | export interface ITippingConfig { 142 | // Calculate percentage-based tips based on this amount. 143 | // For more information, see the official Stripe docs: [On Reader Tipping](https://stripe.com/docs/terminal/features/collecting-tips/on-reader) 144 | eligible_amount?: number | null; 145 | } 146 | 147 | // Contains configuration information relevant to processing/confirming a payment method. 148 | export interface IProcessConfig { 149 | // Surcharge amount to be applied to the payment. 150 | amount_surcharge?: number | null; 151 | 152 | // The URL to redirect your customer back to after they authenticate or cancel their payment on the payment method’s app or site. 153 | // If you’d prefer to redirect to a mobile application, you can alternatively supply an application URI scheme. 154 | // This parameter is only used for redirect-based payment methods. 155 | return_url?: string | null; 156 | } 157 | 158 | // Contains configuration information relevant to collecting a setup intent. 159 | export interface ISetupIntentConfig { 160 | // Whether to show a cancel button in transaction UI on Stripe smart readers. 161 | enable_customer_cancellation?: boolean | null; 162 | 163 | // Save the payment method using the Mail Order/Telephone Order feature. Contact Stripe support to enable this feature on your account. 164 | // For more information, see the official Stripe docs: [Mail Order Telephone Order transactions](https://support.stripe.com/questions/mail-order-telephone-order-(moto)-transactions-when-to-categorize-transactions-as-moto) 165 | moto?: boolean | null; 166 | } 167 | 168 | export declare type ConnectOptions = Pick< 169 | IActivateTerminalRequest, 170 | 'fail_if_in_use' 171 | >; 172 | export declare type RefundOptions = Pick< 173 | IRefundChargeRequest, 174 | 'reverse_transfer' | 'refund_application_fee' 175 | >; 176 | 177 | export declare type ErrorResponse = { 178 | error: ExposedError; 179 | }; 180 | export declare type ExposedError = { 181 | type?: string; 182 | request_id?: string; 183 | code?: string; 184 | message: string; 185 | decline_code?: string; 186 | payment_intent?: IPaymentIntent; 187 | failure_reason?: string; 188 | failure_balance_transaction?: string; 189 | }; 190 | 191 | export enum SimulatedCollectInputsResultType { 192 | SUCCEEDED = 'succeeded', 193 | TIMEOUT = 'timeout', 194 | } 195 | 196 | export interface ISimulatedCollectInputsResult { 197 | resultType: SimulatedCollectInputsResultType; 198 | } 199 | 200 | export enum SimulatedCollectInputsSkipBehavior { 201 | NONE = 'none', 202 | ALL = 'all', 203 | } 204 | 205 | export interface ISimulatedCollectInputsResultSucceeded 206 | extends ISimulatedCollectInputsResult { 207 | skipBehavior: SimulatedCollectInputsSkipBehavior; 208 | } 209 | 210 | export interface ISimulatedCollectInputsResultTimeout 211 | extends ISimulatedCollectInputsResult {} 212 | 213 | export interface SimulatorConfiguration { 214 | paymentMethodType?: 'interac_present' | null; 215 | testPaymentMethod?: string | null; 216 | testCardNumber?: string | null; 217 | tipAmount?: number | null; 218 | collectInputsResult?: ISimulatedCollectInputsResult | null; 219 | } 220 | 221 | export interface DiscoveryMethodConfiguration { 222 | device_type?: string; 223 | method?: string; 224 | simulated?: boolean; 225 | } 226 | export interface InternetMethodConfiguration 227 | extends DiscoveryMethodConfiguration { 228 | method?: 'internet'; 229 | location?: string; 230 | } 231 | export declare type DiscoveryConfig = InternetMethodConfiguration; 232 | export declare type DiscoverResult = { 233 | discoveredReaders: Array; 234 | }; 235 | 236 | export type Address = Stripe.Address; 237 | 238 | export type Location = Stripe.Terminal.Location; 239 | 240 | // Contains information about the inputs to collect from the reader 241 | export interface ICollectInputsParameters { 242 | inputs: Array; 243 | } 244 | 245 | export enum FormType { 246 | SELECTION = 'selection', 247 | SIGNATURE = 'signature', 248 | PHONE = 'phone', 249 | EMAIL = 'email', 250 | NUMERIC = 'numeric', 251 | TEXT = 'text', 252 | } 253 | 254 | // Represents a single input form 255 | export interface IInput { 256 | // Set the type of the form 257 | formType: FormType; 258 | 259 | // Set whether this form is required 260 | required?: boolean | null; 261 | 262 | // Set the title of the form 263 | title: string; 264 | 265 | // Set the description of the form 266 | description?: string | null; 267 | 268 | // Set the toggles to display on the form 269 | toggles?: IToggle[] | null; 270 | 271 | // Modify the skip button text 272 | skipButtonText?: string | null; 273 | } 274 | 275 | // Represents the toggle state 276 | export enum ToggleValue { 277 | // Toggle is checked or on 278 | ENABLED = 'enabled', 279 | // Toggle is unchecked or off 280 | DISABLED = 'disabled', 281 | } 282 | 283 | // Contains information for a collect inputs toggle 284 | export interface IToggle { 285 | // Set the main, larger style text. 286 | title?: string | null; 287 | // Set the secondary, smaller style text. 288 | description?: string | null; 289 | // Set the initial value to be set for the toggle. 290 | defaultValue: ToggleValue; 291 | } 292 | 293 | // Represents the style of a selection form button 294 | export enum SelectionButtonStyle { 295 | // Button will use a highlighted, accent color 296 | PRIMARY = 'primary', 297 | // Button will use a subdued, secondary color 298 | SECONDARY = 'secondary', 299 | } 300 | 301 | // Contains information for a selection form button 302 | export interface ISelectionButton { 303 | // Set the style of a selection button 304 | style: SelectionButtonStyle; 305 | // Set the button text 306 | text: string; 307 | // Set the button id 308 | id: string; 309 | } 310 | 311 | // Contains information about a selection form to display on the reader 312 | export interface SelectionInput extends IInput { 313 | // Set the button choices to display on the form 314 | selectionButtons: ISelectionButton[]; 315 | } 316 | 317 | // Contains information about a signature form to display on the reader 318 | export interface SignatureInput extends IInput { 319 | // Modify the submit button text 320 | submitButtonText?: string | null; 321 | } 322 | 323 | // Contains information about a phone form to display on the reader 324 | export interface PhoneInput extends IInput { 325 | // Modify the submit button text 326 | submitButtonText?: string | null; 327 | } 328 | 329 | // Contains information about an email form to display on the reader 330 | export interface EmailInput extends IInput { 331 | // Modify the submit button text 332 | submitButtonText?: string | null; 333 | } 334 | 335 | // Contains information about a text form to display on the reader 336 | export interface TextInput extends IInput { 337 | // Modify the submit button text 338 | submitButtonText?: string | null; 339 | } 340 | 341 | // Contains information about a numeric form to display on the reader 342 | export interface NumericInput extends IInput { 343 | // Modify the submit button text 344 | submitButtonText?: string | null; 345 | } 346 | 347 | // Contains data collected for a toggle 348 | export enum ToggleResult { 349 | // Toggle is unchecked or off 350 | DISABLED = 'disabled', 351 | // Toggle is checked or on 352 | ENABLED = 'enabled', 353 | // Input form is skipped, no value 354 | SKIPPED = 'skipped', 355 | } 356 | 357 | // Contains the common fields for all input result types 358 | export interface ICollectInputsResult { 359 | // the type of the form 360 | formType: FormType; 361 | 362 | // if true, the skip button was pressed to skip the form. 363 | skipped: boolean; 364 | 365 | // array of toggles and selected value. Values are `ToggleResult.SKIPPED` if form was skipped. 366 | toggles: ToggleResult[]; 367 | } 368 | 369 | // Contains data collected from a selection form 370 | export interface SelectionResult extends ICollectInputsResult { 371 | // selected button. Null if the form was skipped. 372 | selection?: string | null; 373 | // selected button ID. Null if the form was skipped. 374 | selectionId?: string | null; 375 | } 376 | 377 | // Contains data collected from a signature form 378 | export interface SignatureResult extends ICollectInputsResult { 379 | // signature in svg format. Null if the form was skipped. 380 | signatureSvg?: string | null; 381 | } 382 | 383 | // Contains data collected from a phone form 384 | export interface PhoneResult extends ICollectInputsResult { 385 | // the submitted phone number in E.164 format. Null if the form was skipped. 386 | phone?: string | null; 387 | } 388 | 389 | // Contains data collected from an email form 390 | export interface EmailResult extends ICollectInputsResult { 391 | // the submitted email. Null if the form was skipped. 392 | email?: string | null; 393 | } 394 | 395 | // Contains data collected from a text form 396 | export interface TextResult extends ICollectInputsResult { 397 | // the submitted text. Null if the form was skipped. 398 | text?: string | null; 399 | } 400 | 401 | // Contains data collected from an email form 402 | export interface NumericResult extends ICollectInputsResult { 403 | // the submitted number as a string. Null if the form was skipped. 404 | numericString?: string | null; 405 | } 406 | 407 | export class Terminal { 408 | /** 409 | * Returns the current connection status of the PIN pad. 410 | */ 411 | getConnectionStatus(): ConnectionStatus; 412 | /** 413 | * Returns the current transaction status. 414 | */ 415 | getPaymentStatus(): PaymentStatus; 416 | /** 417 | * Returns a promise that resolves with discovered readers that can be connected to. 418 | */ 419 | discoverReaders( 420 | config?: DiscoveryConfig 421 | ): Promise; 422 | /** 423 | * Returns a promise that resolves only when the SDK has connected to a Reader. 424 | */ 425 | connectReader( 426 | reader: Reader, 427 | connectOptions?: ConnectOptions 428 | ): Promise< 429 | | ErrorResponse 430 | | { 431 | reader: Reader; 432 | } 433 | >; 434 | /** 435 | * Returns the current connected reader. 436 | */ 437 | getConnectedReader(): Reader; 438 | /** 439 | * Disconnects from any connected Readers and triggers reconnecting based on 440 | * the options in the passed in config. 441 | */ 442 | disconnectReader(): Promise; 443 | /** 444 | * Clears the cached connection token or rabbit sessions 445 | */ 446 | clearCachedCredentials(): Promise< 447 | IClearCachedCredentialsResponse | ErrorResponse 448 | >; 449 | /** 450 | * Ends the Checkout Flow. This brings the UX back to the splash screen. 451 | */ 452 | clearReaderDisplay(): Promise; 453 | /** 454 | * Updates the PIN Pad UI with information on the basket the user is buying 455 | * @param request Request object containing information on the basket 456 | */ 457 | setReaderDisplay( 458 | request: ISetReaderDisplayRequest 459 | ): Promise; 460 | /** 461 | * Display forms and collect information from customers. Available for BBPOS WisePOS E and Stripe S700. 462 | * @param collectInputsParameters Parameters to configure forms 463 | */ 464 | collectInputs( 465 | collectInputsParameters: ICollectInputsParameters 466 | ): Promise>; 467 | /** 468 | * Cancels an in-flight request made by collectInputs 469 | */ 470 | cancelCollectInputs(): Promise; 471 | /** 472 | * Requests the Terminal object to collect a card source from the reader that 473 | * can be charged. 474 | * @param request Request object containing the payment intent secret of the intent to attach the 475 | * source to. 476 | */ 477 | collectPaymentMethod( 478 | request: PaymentIntentClientSecret, 479 | options?: { 480 | tip_configuration?: ITipConfiguration; 481 | config_override?: ICollectConfig; 482 | } 483 | ): Promise< 484 | | ErrorResponse 485 | | { 486 | paymentIntent: ISdkManagedPaymentIntent; 487 | } 488 | >; 489 | cancelCollectPaymentMethod(): Promise; 490 | /** 491 | * Confirms the payment intent which causes the charging of the user card. 492 | * @param request Object containing the payment intent to confirm. 493 | */ 494 | processPayment( 495 | request: ISdkManagedPaymentIntent, 496 | options?: { 497 | config_override?: IProcessConfig; 498 | } 499 | ): Promise< 500 | | ErrorResponse 501 | | { 502 | paymentIntent: IPaymentIntent; 503 | } 504 | >; 505 | cancelProcessPayment(): Promise; 506 | readReusableCard(options?: { 507 | customer?: string; 508 | }): Promise< 509 | | ErrorResponse 510 | | { 511 | payment_method: IPaymentMethodReadReusableResponse; 512 | } 513 | >; 514 | 515 | /** 516 | * Requests the Terminal object to collect a card source from the reader that 517 | * can be saved via a SetupIntent. 518 | * @param clientSecret Request object containing the setup intent secret of the intent to attach The 519 | * @param customerConsentCollectedOrAllowRedisplay field indicating whether this payment method can be shown again to its customer in a checkout flow. 520 | * @param config an optional object containing collection configuration. 521 | */ 522 | collectSetupIntentPaymentMethod( 523 | clientSecret: string, 524 | customerConsentCollectedOrAllowRedisplay: boolean | AllowRedisplay, 525 | config: ISetupIntentConfig | null 526 | ): Promise; 527 | 528 | /** 529 | * Cancels an in-flight request made by collectSetupIntentPaymentMethod to collect a payment method for future use 530 | */ 531 | cancelCollectSetupIntentPaymentMethod(): Promise< 532 | ErrorResponse | ICancelResponse 533 | >; 534 | 535 | /** 536 | * Confirms the setup intent which causes the card to be saved for future use. 537 | * @param setupIntent The SetupIntent object to confirm; use the value returned from collectSetupIntentPaymentMethod 538 | */ 539 | confirmSetupIntent( 540 | setupIntent: ISetupIntent 541 | ): Promise; 542 | cancelConfirmSetupIntent(): Promise; 543 | 544 | collectRefundPaymentMethod( 545 | charge_id: string, 546 | amount: number, 547 | currency: string, 548 | options?: RefundOptions 549 | ): Promise; 550 | cancelCollectRefundPaymentMethod(): Promise; 551 | 552 | processRefund(): Promise< 553 | | ErrorResponse 554 | | ErrorResponse 555 | | { 556 | refund: IRefund; 557 | } 558 | >; 559 | cancelProcessRefund(): Promise; 560 | 561 | cancelReadReusableCard(): Promise; 562 | setSimulatorConfiguration(config: any): void; 563 | getSimulatorConfiguration(): SimulatorConfiguration; 564 | overrideBaseURL(url: string): void; 565 | 566 | /** 567 | * Changes settings on the connected reader. 568 | * 569 | * @param request The request with the values to set on the reader. 570 | */ 571 | setReaderSettings( 572 | request: ISetReaderSettingsRequest 573 | ): Promise; 574 | 575 | /** 576 | * Retrieves current settings from the connected reader. 577 | */ 578 | getReaderSettings(): Promise; 579 | } 580 | --------------------------------------------------------------------------------