├── .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 | [](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 |
--------------------------------------------------------------------------------