@chipmobilesdk/rn-payment 0.4.0 → 0.5.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 +482 -334
- package/README.md +925 -897
- package/package.json +52 -54
- package/skills/sdk-rn-payment/SKILL.md +175 -174
- package/src/adapter/createStoreProvider.ts +116 -118
- package/src/adapter/iap-adapter.ts +627 -660
- package/src/adapter/port.ts +209 -215
- package/src/config/types.ts +298 -310
- package/src/config/validate.ts +224 -232
- package/src/core/mutex.ts +25 -128
- package/src/core/retry.ts +95 -133
- package/src/core/timers.ts +272 -267
- package/src/diagnostics/errors.ts +124 -117
- package/src/diagnostics/events.ts +282 -266
- package/src/diagnostics/messageKeys.ts +93 -95
- package/src/engine/engine.ts +921 -999
- package/src/engine/finalize.ts +343 -346
- package/src/engine/foreground.ts +29 -0
- package/src/engine/products.ts +259 -259
- package/src/engine/purchase.ts +589 -614
- package/src/engine/subscriptions.ts +146 -157
- package/src/entitlements/aggregate.ts +261 -242
- package/src/entitlements/mapping.ts +67 -67
- package/src/entitlements/policy.ts +121 -129
- package/src/index.ts +5 -9
- package/src/persistence/mmkv-store.ts +158 -158
- package/src/persistence/snapshot.ts +220 -247
- package/src/react/PaymentProvider.tsx +90 -79
- package/src/react/hooks.ts +236 -274
- package/src/testing/conformance.ts +169 -0
- package/src/testing/fakeStore.ts +360 -393
- package/src/testing/index.ts +19 -10
|
@@ -1,117 +1,124 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Normalized public errors.
|
|
3
|
-
*
|
|
4
|
-
* Error codes are **public API**: renaming one is a breaking change (FR-078,
|
|
5
|
-
* LIB-008). They are the vocabulary an app branches on, so they must outlive any
|
|
6
|
-
* internal refactor and must never leak a store's own code.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
|
|
33
|
-
'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
| '
|
|
50
|
-
| '
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Normalized public errors.
|
|
3
|
+
*
|
|
4
|
+
* Error codes are **public API**: renaming one is a breaking change (FR-078,
|
|
5
|
+
* LIB-008). They are the vocabulary an app branches on, so they must outlive any
|
|
6
|
+
* internal refactor and must never leak a store's own code.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { REDACTED, SdkError, createRedactor } from '@chipmobilesdk/rn-core';
|
|
10
|
+
|
|
11
|
+
const identifiers = createRedactor();
|
|
12
|
+
|
|
13
|
+
export const PAYMENT_ERROR_CODES = [
|
|
14
|
+
'PAYMENT_NOT_CONFIGURED',
|
|
15
|
+
'PAYMENT_INVALID_CATALOG',
|
|
16
|
+
'PAYMENT_NOT_READY',
|
|
17
|
+
'PAYMENT_DISABLED',
|
|
18
|
+
'PAYMENT_UNAVAILABLE',
|
|
19
|
+
'PAYMENT_UNSUPPORTED_PLATFORM',
|
|
20
|
+
'PAYMENT_ENVIRONMENT_BLOCKED',
|
|
21
|
+
'PAYMENT_PRODUCTION_CONFIG_IN_NON_PRODUCTION_BUILD',
|
|
22
|
+
'PAYMENT_PURCHASE_IN_PROGRESS',
|
|
23
|
+
'PAYMENT_USER_CANCELLED',
|
|
24
|
+
'PAYMENT_PENDING',
|
|
25
|
+
'PAYMENT_ALREADY_OWNED',
|
|
26
|
+
'PAYMENT_INELIGIBLE',
|
|
27
|
+
'PAYMENT_UNKNOWN_PRODUCT',
|
|
28
|
+
'PAYMENT_PRODUCT_UNAVAILABLE_IN_REGION',
|
|
29
|
+
'PAYMENT_TIMEOUT',
|
|
30
|
+
'PAYMENT_NETWORK_ERROR',
|
|
31
|
+
'PAYMENT_STORE_ERROR',
|
|
32
|
+
'PAYMENT_FINALIZE_FAILED',
|
|
33
|
+
'PAYMENT_VALIDATION_REJECTED',
|
|
34
|
+
'PAYMENT_VALIDATION_UNAVAILABLE',
|
|
35
|
+
'PAYMENT_STORAGE_UNAVAILABLE',
|
|
36
|
+
/** `consume` on a transaction that is not a consumable, added in 0.3.2. */
|
|
37
|
+
'PAYMENT_NOT_CONSUMABLE',
|
|
38
|
+
/**
|
|
39
|
+
* A timeout, backoff or interval outside its bounds, added in 0.5.0. These
|
|
40
|
+
* used to be reported as `PAYMENT_INVALID_CATALOG`, which is about products.
|
|
41
|
+
*/
|
|
42
|
+
'PAYMENT_INVALID_CONFIG',
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
45
|
+
export type PaymentErrorCode = (typeof PAYMENT_ERROR_CODES)[number];
|
|
46
|
+
|
|
47
|
+
/** Which operation produced an error. Part of the public error shape (FR-078). */
|
|
48
|
+
export type PaymentOperation =
|
|
49
|
+
| 'configure'
|
|
50
|
+
| 'initialize'
|
|
51
|
+
| 'getProducts'
|
|
52
|
+
| 'purchase'
|
|
53
|
+
| 'finalize'
|
|
54
|
+
| 'consume'
|
|
55
|
+
| 'sync'
|
|
56
|
+
| 'restore'
|
|
57
|
+
| 'changePlan'
|
|
58
|
+
| 'validate'
|
|
59
|
+
| 'persist';
|
|
60
|
+
|
|
61
|
+
/** The package's error; an `SdkError` (`@chipmobilesdk/rn-core`) with `pkg: 'rn-payment'`. */
|
|
62
|
+
export class PaymentError extends SdkError<PaymentErrorCode> {
|
|
63
|
+
readonly operation: PaymentOperation;
|
|
64
|
+
/** Redacted where appropriate — never a raw receipt, token, or store object (FR-074). */
|
|
65
|
+
readonly cause?: string;
|
|
66
|
+
|
|
67
|
+
constructor(init: {
|
|
68
|
+
code: PaymentErrorCode;
|
|
69
|
+
message: string;
|
|
70
|
+
operation: PaymentOperation;
|
|
71
|
+
retryable?: boolean;
|
|
72
|
+
cause?: string;
|
|
73
|
+
}) {
|
|
74
|
+
super('rn-payment', init.code, {
|
|
75
|
+
message: init.message,
|
|
76
|
+
retryable: init.retryable ?? false,
|
|
77
|
+
redactedCause: init.cause,
|
|
78
|
+
});
|
|
79
|
+
this.name = 'PaymentError';
|
|
80
|
+
this.operation = init.operation;
|
|
81
|
+
this.cause = init.cause;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A configuration problem the app can act on.
|
|
87
|
+
*
|
|
88
|
+
* Separate from `PaymentError` because configuration faults are developer-facing
|
|
89
|
+
* and must never be shown to an end user — the message-key map keeps that
|
|
90
|
+
* separation explicit (FR-085).
|
|
91
|
+
*/
|
|
92
|
+
export class PaymentConfigError extends PaymentError {
|
|
93
|
+
/** The offending catalog entries or entitlement keys, named (FR-011). */
|
|
94
|
+
readonly offenders: string[];
|
|
95
|
+
|
|
96
|
+
constructor(init: {
|
|
97
|
+
code: PaymentErrorCode;
|
|
98
|
+
message: string;
|
|
99
|
+
operation: PaymentOperation;
|
|
100
|
+
offenders?: string[];
|
|
101
|
+
}) {
|
|
102
|
+
super({ ...init, retryable: false });
|
|
103
|
+
this.name = 'PaymentConfigError';
|
|
104
|
+
this.offenders = init.offenders ?? [];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Strips anything that must never reach a log or event.
|
|
110
|
+
*
|
|
111
|
+
* Applied at the boundary rather than trusted to call sites: a single forgotten
|
|
112
|
+
* interpolation is how receipts end up in logs (NFR-006).
|
|
113
|
+
*
|
|
114
|
+
* Identifier-only: what survives is what code defined, never what data carried.
|
|
115
|
+
* A `PaymentError` keeps its code and an `Error` its class name; every message
|
|
116
|
+
* and every string is dropped, because a store or consumer message can embed a
|
|
117
|
+
* purchase token or an account id and nothing here can tell which.
|
|
118
|
+
*/
|
|
119
|
+
export function redact(value: unknown): string {
|
|
120
|
+
// An SDK error reduces to its code and any other Error to its class name
|
|
121
|
+
// (rn-core's identifier-only redactor). Strings never survive here, not even
|
|
122
|
+
// a leading constant: a store message is free text from a payments SDK.
|
|
123
|
+
return value instanceof Error ? identifiers.text(value) : REDACTED;
|
|
124
|
+
}
|