@tapayadot/accept-react-native 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/README.md +82 -2
- package/android/build.gradle +29 -2
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/AcceptSdkReactNativeModule.kt +58 -0
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/NfcBridge.kt +35 -0
- package/android/src/nfc/java/com/tapaya/acceptsdkreactnative/PlatformNfcBridge.kt +215 -0
- package/android/src/nfcDisabled/java/com/tapaya/acceptsdkreactnative/PlatformNfcBridge.kt +38 -0
- package/build/Accept.d.ts +7 -1
- package/build/Accept.d.ts.map +1 -1
- package/build/Accept.js +84 -0
- package/build/Accept.js.map +1 -1
- package/build/Accept.types.d.ts +59 -0
- package/build/Accept.types.d.ts.map +1 -1
- package/build/Accept.types.js.map +1 -1
- package/build/AcceptPluginPackages.d.ts +7 -0
- package/build/AcceptPluginPackages.d.ts.map +1 -0
- package/build/AcceptPluginPackages.js +11 -0
- package/build/AcceptPluginPackages.js.map +1 -0
- package/build/AcceptSdkReactNativeModule.d.ts +23 -1
- package/build/AcceptSdkReactNativeModule.d.ts.map +1 -1
- package/build/AcceptSdkReactNativeModule.js.map +1 -1
- package/build/TagSessionError.d.ts +13 -0
- package/build/TagSessionError.d.ts.map +1 -0
- package/build/TagSessionError.js +53 -0
- package/build/TagSessionError.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/package.json +12 -1
- package/plugin/withAcceptSdk.js +28 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { rethrowAsAcceptError } from "./AcceptError";
|
|
2
|
+
/** A checked failure from opening or operating an NFC tag session. */
|
|
3
|
+
export class TagSessionError extends Error {
|
|
4
|
+
code = "TagSessionException";
|
|
5
|
+
reason;
|
|
6
|
+
authLost;
|
|
7
|
+
vendorCode;
|
|
8
|
+
constructor(reason, message, authLost = false, vendorCode = null) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "TagSessionError";
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
this.authLost = authLost;
|
|
13
|
+
this.vendorCode = vendorCode;
|
|
14
|
+
}
|
|
15
|
+
static is(error) {
|
|
16
|
+
return error instanceof TagSessionError;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function extractPayload(message) {
|
|
20
|
+
const start = message.indexOf("{");
|
|
21
|
+
const end = message.lastIndexOf("}");
|
|
22
|
+
if (start === -1 || end <= start)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(message.slice(start, end + 1));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function toTagSessionError(error) {
|
|
32
|
+
const code = error?.code;
|
|
33
|
+
const message = error?.message;
|
|
34
|
+
if (code !== "TagSessionException" || typeof message !== "string")
|
|
35
|
+
return null;
|
|
36
|
+
const payload = extractPayload(message);
|
|
37
|
+
if (payload?.code !== code || typeof payload.reason !== "string")
|
|
38
|
+
return null;
|
|
39
|
+
return new TagSessionError(payload.reason, payload.message, payload.authLost, payload.vendorCode);
|
|
40
|
+
}
|
|
41
|
+
/** Converts NFC and core-SDK native rejections while preserving unrelated Expo errors. */
|
|
42
|
+
export async function mapNfcErrors(call) {
|
|
43
|
+
try {
|
|
44
|
+
return await call();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const tagError = toTagSessionError(error);
|
|
48
|
+
if (tagError)
|
|
49
|
+
throw tagError;
|
|
50
|
+
rethrowAsAcceptError(error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=TagSessionError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TagSessionError.js","sourceRoot":"","sources":["../src/TagSessionError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAUrD,sEAAsE;AACtE,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,GAAG,qBAA8B,CAAC;IACtC,MAAM,CAAiB;IACvB,QAAQ,CAAU;IAClB,UAAU,CAAgB;IAEnC,YACE,MAAsB,EACtB,OAAe,EACf,QAAQ,GAAG,KAAK,EAChB,aAA4B,IAAI;QAEhC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,EAAE,CAAC,KAAc;QACtB,OAAO,KAAK,YAAY,eAAe,CAAC;IAC1C,CAAC;CACF;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,MAAM,IAAI,GAAI,KAAkC,EAAE,IAAI,CAAC;IACvD,MAAM,OAAO,GAAI,KAAqC,EAAE,OAAO,CAAC;IAChE,IAAI,IAAI,KAAK,qBAAqB,IAAI,OAAO,OAAO,KAAK,QAAQ;QAC/D,OAAO,IAAI,CAAC;IACd,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,OAAO,EAAE,IAAI,KAAK,IAAI,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC9E,OAAO,IAAI,eAAe,CACxB,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,UAAU,CACnB,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAsB;IAC1D,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,QAAQ;YAAE,MAAM,QAAQ,CAAC;QAC7B,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC","sourcesContent":["import type { TagErrorReason } from \"./Accept.types\";\nimport { rethrowAsAcceptError } from \"./AcceptError\";\n\ntype SerializedTagSessionError = {\n code: \"TagSessionException\";\n message: string;\n reason: TagErrorReason;\n authLost: boolean;\n vendorCode: number | null;\n};\n\n/** A checked failure from opening or operating an NFC tag session. */\nexport class TagSessionError extends Error {\n readonly code = \"TagSessionException\" as const;\n readonly reason: TagErrorReason;\n readonly authLost: boolean;\n readonly vendorCode: number | null;\n\n constructor(\n reason: TagErrorReason,\n message: string,\n authLost = false,\n vendorCode: number | null = null,\n ) {\n super(message);\n this.name = \"TagSessionError\";\n this.reason = reason;\n this.authLost = authLost;\n this.vendorCode = vendorCode;\n }\n\n static is(error: unknown): error is TagSessionError {\n return error instanceof TagSessionError;\n }\n}\n\nfunction extractPayload(message: string): SerializedTagSessionError | null {\n const start = message.indexOf(\"{\");\n const end = message.lastIndexOf(\"}\");\n if (start === -1 || end <= start) return null;\n try {\n return JSON.parse(message.slice(start, end + 1));\n } catch {\n return null;\n }\n}\n\nfunction toTagSessionError(error: unknown): TagSessionError | null {\n const code = (error as { code?: string } | null)?.code;\n const message = (error as { message?: string } | null)?.message;\n if (code !== \"TagSessionException\" || typeof message !== \"string\")\n return null;\n const payload = extractPayload(message);\n if (payload?.code !== code || typeof payload.reason !== \"string\") return null;\n return new TagSessionError(\n payload.reason,\n payload.message,\n payload.authLost,\n payload.vendorCode,\n );\n}\n\n/** Converts NFC and core-SDK native rejections while preserving unrelated Expo errors. */\nexport async function mapNfcErrors<T>(call: () => Promise<T>): Promise<T> {\n try {\n return await call();\n } catch (error) {\n const tagError = toTagSessionError(error);\n if (tagError) throw tagError;\n rethrowAsAcceptError(error);\n }\n}\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -7,5 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { Accept, Accept as default } from "./Accept";
|
|
9
9
|
export { AcceptError } from "./AcceptError";
|
|
10
|
+
export { AcceptPluginPackages } from "./AcceptPluginPackages";
|
|
11
|
+
export { TagSessionError } from "./TagSessionError";
|
|
10
12
|
export * from "./Accept.types";
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,cAAc,gBAAgB,CAAC"}
|
package/build/index.js
CHANGED
|
@@ -7,5 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { Accept, Accept as default } from "./Accept";
|
|
9
9
|
export { AcceptError } from "./AcceptError";
|
|
10
|
+
export { AcceptPluginPackages } from "./AcceptPluginPackages";
|
|
11
|
+
export { TagSessionError } from "./TagSessionError";
|
|
10
12
|
export * from "./Accept.types";
|
|
11
13
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,cAAc,gBAAgB,CAAC","sourcesContent":["/**\n * Accept SDK for React Native / Expo — Android.\n *\n * A thin wrapper over the Accept SDK for Android (`com.tapaya:accept`), which in turn drives the\n * Accept plugin app installed on the terminal. The surfaces here mirror the Android SDK 1:1, so its\n * reference documentation applies unchanged: https://docs.tapaya.com\n */\n\nexport { Accept, Accept as default } from \"./Accept\";\nexport { AcceptError } from \"./AcceptError\";\nexport * from \"./Accept.types\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,cAAc,gBAAgB,CAAC","sourcesContent":["/**\n * Accept SDK for React Native / Expo — Android.\n *\n * A thin wrapper over the Accept SDK for Android (`com.tapaya:accept`), which in turn drives the\n * Accept plugin app installed on the terminal. The surfaces here mirror the Android SDK 1:1, so its\n * reference documentation applies unchanged: https://docs.tapaya.com\n */\n\nexport { Accept, Accept as default } from \"./Accept\";\nexport { AcceptError } from \"./AcceptError\";\nexport { AcceptPluginPackages } from \"./AcceptPluginPackages\";\nexport { TagSessionError } from \"./TagSessionError\";\nexport * from \"./Accept.types\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tapayadot/accept-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Accept SDK for React Native/Expo (Android)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -67,6 +67,17 @@
|
|
|
67
67
|
"android": "npm run --workspace accept-react-native-example android",
|
|
68
68
|
"open:android": "open -a \"Android Studio\" example/android"
|
|
69
69
|
},
|
|
70
|
+
"jest": {
|
|
71
|
+
"testEnvironment": "node",
|
|
72
|
+
"transform": {
|
|
73
|
+
"^.+\\.[jt]sx?$": [
|
|
74
|
+
"babel-jest",
|
|
75
|
+
{
|
|
76
|
+
"configFile": "./node_modules/expo-module-scripts/babel.config.base.js"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
},
|
|
70
81
|
"expo": {
|
|
71
82
|
"plugins": [
|
|
72
83
|
"./app.plugin.js"
|
package/plugin/withAcceptSdk.js
CHANGED
|
@@ -3,6 +3,8 @@ const { withGradleProperties } = require("expo/config-plugins");
|
|
|
3
3
|
const MIN_SDK_VERSION = 30;
|
|
4
4
|
const MIN_SDK_PROPERTY = "android.minSdkVersion";
|
|
5
5
|
const SELF_INSTALL_PROPERTY = "tapaya.accept.selfInstall";
|
|
6
|
+
const NFC_PROPERTY = "tapaya.accept.nfc";
|
|
7
|
+
const NFC_SUNMI_PROPERTY = "tapaya.accept.nfcSunmi";
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Sets `key` in the host app's gradle.properties, replacing any value already there.
|
|
@@ -34,14 +36,18 @@ function setProperty(properties, key, value) {
|
|
|
34
36
|
* runtime dependency here, so requiring it would fail in a consumer's project.
|
|
35
37
|
*
|
|
36
38
|
* @param {object} config the Expo config being modified.
|
|
37
|
-
* @param {{ selfInstall?: boolean }} [options] plugin options
|
|
39
|
+
* @param {{ selfInstall?: boolean, nfc?: boolean | { sunmi?: boolean } }} [options] plugin options
|
|
40
|
+
* from the `plugins` array.
|
|
38
41
|
* @param {boolean} [options.selfInstall] opt in to installing the plugin app without a store.
|
|
39
42
|
* Pulls in `com.tapaya:accept-installer`, which carries `REQUEST_INSTALL_PACKAGES` — see the
|
|
40
43
|
* README. Off by default, because that permission merges into the host app's manifest and Play
|
|
41
44
|
* requires every app declaring it to justify it on its listing.
|
|
45
|
+
* @param {boolean | { sunmi?: boolean }} [options.nfc] opt in to NFC tag sessions. `true` adds the
|
|
46
|
+
* Android NFC backend. `{ sunmi: true }` adds both it and the Sunmi PayLib backend. Off by
|
|
47
|
+
* default so apps that do not use tag sessions ship neither artifact nor their permissions.
|
|
42
48
|
*/
|
|
43
49
|
module.exports = function withAcceptSdk(config, options = {}) {
|
|
44
|
-
const { selfInstall = false } = options ?? {};
|
|
50
|
+
const { selfInstall = false, nfc = false } = options ?? {};
|
|
45
51
|
|
|
46
52
|
if (typeof selfInstall !== "boolean") {
|
|
47
53
|
throw new Error(
|
|
@@ -50,6 +56,24 @@ module.exports = function withAcceptSdk(config, options = {}) {
|
|
|
50
56
|
);
|
|
51
57
|
}
|
|
52
58
|
|
|
59
|
+
const nfcIsObject =
|
|
60
|
+
typeof nfc === "object" && nfc !== null && !Array.isArray(nfc);
|
|
61
|
+
if (typeof nfc !== "boolean" && !nfcIsObject) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`@tapayadot/accept-react-native: the \`nfc\` plugin option must be a boolean or ` +
|
|
64
|
+
`an object like { sunmi: true }, received ${JSON.stringify(nfc)}.`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const sunmi = nfcIsObject ? (nfc.sunmi ?? false) : false;
|
|
69
|
+
if (typeof sunmi !== "boolean") {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`@tapayadot/accept-react-native: the \`nfc.sunmi\` plugin option must be a boolean, ` +
|
|
72
|
+
`received ${JSON.stringify(sunmi)}.`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
const nfcEnabled = nfc === true || nfcIsObject;
|
|
76
|
+
|
|
53
77
|
return withGradleProperties(config, (config) => {
|
|
54
78
|
const properties = config.modResults;
|
|
55
79
|
|
|
@@ -69,6 +93,8 @@ module.exports = function withAcceptSdk(config, options = {}) {
|
|
|
69
93
|
// once and then turned it off keeps the stale `true` forever if the `false` case writes
|
|
70
94
|
// nothing, and the next build still ships REQUEST_INSTALL_PACKAGES with no trace of why.
|
|
71
95
|
setProperty(properties, SELF_INSTALL_PROPERTY, String(selfInstall));
|
|
96
|
+
setProperty(properties, NFC_PROPERTY, String(nfcEnabled));
|
|
97
|
+
setProperty(properties, NFC_SUNMI_PROPERTY, String(sunmi));
|
|
72
98
|
|
|
73
99
|
return config;
|
|
74
100
|
});
|