iap-apple 2.0.5 โ 3.0.1
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/README.md +127 -117
- package/dist/index.d.mts +146 -0
- package/dist/index.d.ts +146 -0
- package/dist/index.js +267 -0
- package/dist/index.mjs +235 -0
- package/package.json +61 -53
- package/CHANGELOG.md +0 -75
- package/constants/index.d.ts +0 -2
- package/constants/index.js +0 -18
- package/constants/internal/index.d.ts +0 -4
- package/constants/internal/index.js +0 -19
- package/constants/shared/index.d.ts +0 -14
- package/constants/shared/index.js +0 -31
- package/index.d.ts +0 -3
- package/index.js +0 -19
- package/lib/internal/index.d.ts +0 -10
- package/lib/internal/index.js +0 -185
- package/lib/shared/index.d.ts +0 -35
- package/lib/shared/index.js +0 -216
- package/types/index.d.ts +0 -2
- package/types/index.js +0 -18
- package/types/internal/index.d.ts +0 -18
- package/types/internal/index.js +0 -2
- package/types/shared/index.d.ts +0 -52
- package/types/shared/index.js +0 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
| Statements | Branches | Functions | Lines |
|
|
2
2
|
| --------------------------- | ----------------------- | ------------------------- | ----------------- |
|
|
3
|
-
|  |  |  |  |
|
|
4
4
|
|
|
5
5
|
# iap-apple
|
|
6
6
|
|
|
@@ -8,173 +8,183 @@
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Integration of Apple's **validation service** for App Store Receipts, written in TypeScript, available for Node.js environments.
|
|
12
12
|
|
|
13
|
-
A
|
|
13
|
+
A Node.js module for in-app purchase (in-app billing) and subscription validation for Apple.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Requirements
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
This package is meant to be used server side to validate receipts from the App Store by talking to Apples servers.
|
|
17
|
+
- **Node.js 22+** (uses native `fetch`, zero runtime dependencies)
|
|
19
18
|
|
|
20
|
-
##
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Server-side validation of [App Store Receipts](https://developer.apple.com/documentation/appstorereceipts) by communicating with Apple's verifyReceipt endpoints.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### pnpm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add iap-apple
|
|
29
|
+
```
|
|
21
30
|
|
|
22
31
|
### npm
|
|
23
32
|
|
|
24
|
-
```
|
|
33
|
+
```bash
|
|
34
|
+
npm install iap-apple
|
|
35
|
+
```
|
|
25
36
|
|
|
26
37
|
### yarn
|
|
27
38
|
|
|
28
|
-
```
|
|
39
|
+
```bash
|
|
40
|
+
yarn add iap-apple
|
|
41
|
+
```
|
|
29
42
|
|
|
30
|
-
## API
|
|
43
|
+
## API Documentation
|
|
31
44
|
|
|
32
|
-
### verify
|
|
45
|
+
### verify
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
Requires **appSharedSecret** to be passed as part of the configuration.
|
|
36
|
-
See example for more details.
|
|
47
|
+
Validates a receipt against Apple's verifyReceipt endpoint. Attempts production first, falls back to sandbox if needed.
|
|
37
48
|
|
|
38
49
|
```typescript
|
|
39
|
-
|
|
40
50
|
import { verify, IAPAppleError, IVerifyReceiptResponseBody } from 'iap-apple';
|
|
41
51
|
|
|
42
52
|
async function verifyAppleReceipt(receipt: string) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
*/
|
|
65
|
-
logger: console,
|
|
66
|
-
});
|
|
67
|
-
console.log('verifyReceiptResponse', verifyReceiptResponse);
|
|
68
|
-
} catch(error) {
|
|
69
|
-
const iapAppleError = error as IAPAppleError;
|
|
70
|
-
const rejectionMessage: string = error.rejectionMessage;
|
|
71
|
-
const errorData: IVerifyReceiptResponseBody | null = error.data;
|
|
72
|
-
console.error('Error happened', rejectionMessage);
|
|
73
|
-
console.error('Details', errorData);
|
|
74
|
-
}
|
|
53
|
+
try {
|
|
54
|
+
const verifyReceiptResponse = await verify(receipt, {
|
|
55
|
+
// Required: Your app's shared secret (hexadecimal string)
|
|
56
|
+
// https://help.apple.com/app-store-connect/#/devf341c0f01
|
|
57
|
+
appSharedSecret: 'your-shared-secret',
|
|
58
|
+
|
|
59
|
+
// Optional: Exclude old transactions (default: false)
|
|
60
|
+
appleExcludeOldTransactions: false,
|
|
61
|
+
|
|
62
|
+
// Optional: Force sandbox-only validation (default: false)
|
|
63
|
+
test: false,
|
|
64
|
+
|
|
65
|
+
// Optional: Logger for debugging (default: null)
|
|
66
|
+
logger: console,
|
|
67
|
+
});
|
|
68
|
+
console.log('verifyReceiptResponse', verifyReceiptResponse);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
const iapAppleError = error as IAPAppleError;
|
|
71
|
+
console.error('Error:', iapAppleError.rejectionMessage);
|
|
72
|
+
console.error('Details:', iapAppleError.data);
|
|
73
|
+
}
|
|
75
74
|
}
|
|
76
75
|
```
|
|
77
76
|
|
|
78
|
-
### isVerifiedReceipt
|
|
77
|
+
### isVerifiedReceipt
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
Requires the output of `verify` to be passed.
|
|
82
|
-
See example for more details.
|
|
79
|
+
Checks if the response from `verify` indicates a successful validation.
|
|
83
80
|
|
|
84
81
|
```typescript
|
|
85
|
-
|
|
86
82
|
import { verify, isVerifiedReceipt, IIAPAppleConfig } from 'iap-apple';
|
|
87
83
|
|
|
88
|
-
async function
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const iapAppleError = error as IAPAppleError;
|
|
94
|
-
const rejectionMessage: string = error.rejectionMessage;
|
|
95
|
-
const errorData: IVerifyReceiptResponseBody | null = error.data;
|
|
96
|
-
console.error('Error happened', rejectionMessage);
|
|
97
|
-
console.error('Details', errorData);
|
|
84
|
+
async function checkReceipt(receipt: string, config: IIAPAppleConfig) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await verify(receipt, config);
|
|
87
|
+
if (isVerifiedReceipt(response)) {
|
|
88
|
+
console.log('Receipt is valid');
|
|
98
89
|
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Validation failed:', (error as IAPAppleError).rejectionMessage);
|
|
92
|
+
}
|
|
99
93
|
}
|
|
100
94
|
```
|
|
101
95
|
|
|
102
|
-
### getPurchasedItems
|
|
96
|
+
### getPurchasedItems
|
|
103
97
|
|
|
104
|
-
|
|
105
|
-
sort by their purchase date descending.
|
|
106
|
-
Usually what we are interested in is the first item of the purchase.
|
|
107
|
-
Requires the output of `verify` to be passed.
|
|
108
|
-
See example for more details.
|
|
98
|
+
Extracts purchased items from the validated receipt, sorted by purchase date (newest first), deduplicated by `original_transaction_id`.
|
|
109
99
|
|
|
110
100
|
```typescript
|
|
111
|
-
|
|
112
101
|
import { verify, getPurchasedItems, IIAPAppleConfig } from 'iap-apple';
|
|
113
102
|
|
|
114
|
-
async function
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
console.error('Error happened', rejectionMessage);
|
|
124
|
-
console.error('Details', errorData);
|
|
125
|
-
}
|
|
103
|
+
async function getLatestPurchase(receipt: string, config: IIAPAppleConfig) {
|
|
104
|
+
try {
|
|
105
|
+
const response = await verify(receipt, config);
|
|
106
|
+
const purchasedItems = getPurchasedItems(response);
|
|
107
|
+
const latestPurchase = purchasedItems[0];
|
|
108
|
+
console.log('Latest purchase:', latestPurchase);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error('Error:', (error as IAPAppleError).rejectionMessage);
|
|
111
|
+
}
|
|
126
112
|
}
|
|
127
113
|
```
|
|
128
114
|
|
|
129
|
-
### isPurchasedItemCanceled
|
|
115
|
+
### isPurchasedItemCanceled
|
|
130
116
|
|
|
131
|
-
|
|
132
|
-
Requires the output of `getPurchasedItems` to be passed.
|
|
133
|
-
See example for more details.
|
|
117
|
+
Checks if a purchased item has been canceled.
|
|
134
118
|
|
|
135
119
|
```typescript
|
|
136
|
-
|
|
137
120
|
import { verify, getPurchasedItems, isPurchasedItemCanceled, IIAPAppleConfig } from 'iap-apple';
|
|
138
121
|
|
|
139
|
-
async function
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const iapAppleError = error as IAPAppleError;
|
|
147
|
-
const rejectionMessage: string = error.rejectionMessage;
|
|
148
|
-
const errorData: IVerifyReceiptResponseBody | null = error.data;
|
|
149
|
-
console.error('Error happened', rejectionMessage);
|
|
150
|
-
console.error('Details', errorData);
|
|
122
|
+
async function checkCancellation(receipt: string, config: IIAPAppleConfig) {
|
|
123
|
+
try {
|
|
124
|
+
const response = await verify(receipt, config);
|
|
125
|
+
const purchasedItems = getPurchasedItems(response);
|
|
126
|
+
const latestPurchase = purchasedItems[0];
|
|
127
|
+
if (isPurchasedItemCanceled(latestPurchase)) {
|
|
128
|
+
console.log('Purchase was canceled');
|
|
151
129
|
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('Error:', (error as IAPAppleError).rejectionMessage);
|
|
132
|
+
}
|
|
152
133
|
}
|
|
153
134
|
```
|
|
154
135
|
|
|
136
|
+
### isPurchasedItemExpired
|
|
155
137
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
API used to check if a purchased item is expired.
|
|
159
|
-
Requires the output of `getPurchasedItems` to be passed.
|
|
160
|
-
See example for more details.
|
|
138
|
+
Checks if a purchased item has expired (canceled or past expiration date).
|
|
161
139
|
|
|
162
140
|
```typescript
|
|
163
|
-
|
|
164
141
|
import { verify, getPurchasedItems, isPurchasedItemExpired, IIAPAppleConfig } from 'iap-apple';
|
|
165
142
|
|
|
166
|
-
async function
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const iapAppleError = error as IAPAppleError;
|
|
174
|
-
const rejectionMessage: string = error.rejectionMessage;
|
|
175
|
-
const errorData: IVerifyReceiptResponseBody | null = error.data;
|
|
176
|
-
console.error('Error happened', rejectionMessage);
|
|
177
|
-
console.error('Details', errorData);
|
|
143
|
+
async function checkExpiration(receipt: string, config: IIAPAppleConfig) {
|
|
144
|
+
try {
|
|
145
|
+
const response = await verify(receipt, config);
|
|
146
|
+
const purchasedItems = getPurchasedItems(response);
|
|
147
|
+
const latestPurchase = purchasedItems[0];
|
|
148
|
+
if (isPurchasedItemExpired(latestPurchase)) {
|
|
149
|
+
console.log('Purchase has expired');
|
|
178
150
|
}
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error('Error:', (error as IAPAppleError).rejectionMessage);
|
|
153
|
+
}
|
|
179
154
|
}
|
|
180
|
-
```
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Types
|
|
158
|
+
|
|
159
|
+
### PurchasedItem
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
interface PurchasedItem {
|
|
163
|
+
bundleId: string;
|
|
164
|
+
appItemId: string;
|
|
165
|
+
originalTransactionId?: string;
|
|
166
|
+
transactionId: string;
|
|
167
|
+
productId: string;
|
|
168
|
+
originalPurchaseDateMS?: number;
|
|
169
|
+
expirationDateMS?: number;
|
|
170
|
+
purchaseDateMS: number;
|
|
171
|
+
isTrialPeriod: boolean;
|
|
172
|
+
cancellationDateMS?: number;
|
|
173
|
+
quantity: number;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### IIAPAppleConfig
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
interface IIAPAppleConfig {
|
|
181
|
+
appSharedSecret: string;
|
|
182
|
+
appleExcludeOldTransactions?: boolean;
|
|
183
|
+
test?: boolean;
|
|
184
|
+
logger?: ILogger | null;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
ISC
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
declare enum RECEIPT_STATUS_ENUM {
|
|
2
|
+
SUCCESS = 0,
|
|
3
|
+
VALID_NO_PURCHASE = 2,
|
|
4
|
+
CANNOT_READ_JSON = 21000,
|
|
5
|
+
DATA_MALFORMED = 21002,
|
|
6
|
+
RECEIPT_NOT_AUTHENTICATED = 21003,
|
|
7
|
+
SHARED_SECRET_DOESNT_MATCH = 21004,
|
|
8
|
+
SERVER_NOT_AVAILABLE = 21005,
|
|
9
|
+
SUBSCRIPTION_EXPIRED = 21006,
|
|
10
|
+
TEST_ENV_RECEIPT_DETECTED = 21007,
|
|
11
|
+
PRODUCTION_ENV_RECEIPT_DETECTED = 21008,
|
|
12
|
+
INTERNAL_DATA_ACCESS_ERROR = 21009,
|
|
13
|
+
USER_ACCOUNT_DELETED = 21010
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface IPendingRenewalInfo {
|
|
17
|
+
auto_renew_product_id: string;
|
|
18
|
+
auto_renew_status: '0' | '1';
|
|
19
|
+
original_transaction_id: string;
|
|
20
|
+
product_id: string;
|
|
21
|
+
expiration_intent?: '1' | '2' | '3' | '4' | '5';
|
|
22
|
+
grace_period_expires_date_ms?: string;
|
|
23
|
+
is_in_billing_retry_period?: '0' | '1';
|
|
24
|
+
offer_code_ref_name?: string;
|
|
25
|
+
price_consent_status?: '0' | '1';
|
|
26
|
+
promotional_offer_id?: string;
|
|
27
|
+
}
|
|
28
|
+
interface IReceiptInAppItem {
|
|
29
|
+
quantity: string;
|
|
30
|
+
product_id: string;
|
|
31
|
+
transaction_id: string;
|
|
32
|
+
original_transaction_id: string;
|
|
33
|
+
purchase_date: string;
|
|
34
|
+
purchase_date_ms: string;
|
|
35
|
+
original_purchase_date: string;
|
|
36
|
+
original_purchase_date_ms: string;
|
|
37
|
+
expires_date?: string;
|
|
38
|
+
expires_date_ms?: string;
|
|
39
|
+
expiration_intent?: '1' | '2' | '3' | '4' | '5';
|
|
40
|
+
is_trial_period: string;
|
|
41
|
+
cancellation_date?: string;
|
|
42
|
+
cancellation_date_ms?: string;
|
|
43
|
+
cancellation_reason?: '0' | '1';
|
|
44
|
+
app_item_id: string;
|
|
45
|
+
web_order_line_item_id?: string;
|
|
46
|
+
is_in_intro_offer_period?: string;
|
|
47
|
+
promotional_offer_id?: string;
|
|
48
|
+
offer_code_ref_name?: string;
|
|
49
|
+
in_app_ownership_type?: 'FAMILY_SHARED' | 'PURCHASED';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface ILogger {
|
|
53
|
+
log: (message: string) => void;
|
|
54
|
+
warn: (message: string) => void;
|
|
55
|
+
error: (message: string) => void;
|
|
56
|
+
}
|
|
57
|
+
interface IIAPAppleConfig {
|
|
58
|
+
appleExcludeOldTransactions?: boolean;
|
|
59
|
+
appSharedSecret: string;
|
|
60
|
+
test?: boolean | undefined;
|
|
61
|
+
logger?: ILogger | null;
|
|
62
|
+
}
|
|
63
|
+
interface PurchasedItem {
|
|
64
|
+
bundleId: string;
|
|
65
|
+
appItemId: string;
|
|
66
|
+
originalTransactionId?: string;
|
|
67
|
+
transactionId: string;
|
|
68
|
+
productId: string;
|
|
69
|
+
originalPurchaseDateMS?: number;
|
|
70
|
+
expirationDateMS?: number;
|
|
71
|
+
purchaseDateMS: number;
|
|
72
|
+
isTrialPeriod: boolean;
|
|
73
|
+
cancellationDateMS?: number;
|
|
74
|
+
quantity: number;
|
|
75
|
+
}
|
|
76
|
+
interface IAPAppleError {
|
|
77
|
+
rejectionMessage: string;
|
|
78
|
+
data?: IVerifyReceiptResponseBody | null;
|
|
79
|
+
}
|
|
80
|
+
interface IVerifyReceiptResponseBody {
|
|
81
|
+
status: RECEIPT_STATUS_ENUM;
|
|
82
|
+
environment: 'Sandbox' | 'Production';
|
|
83
|
+
receipt: IReceipt;
|
|
84
|
+
latest_receipt: string;
|
|
85
|
+
latest_receipt_info: IReceiptInAppItem[];
|
|
86
|
+
'is-retryable'?: boolean;
|
|
87
|
+
pending_renewal_info?: IPendingRenewalInfo[];
|
|
88
|
+
}
|
|
89
|
+
interface IReceipt {
|
|
90
|
+
bundle_id: string;
|
|
91
|
+
application_version: string;
|
|
92
|
+
in_app: IReceiptInAppItem[];
|
|
93
|
+
latest_receipt_info: IReceiptInAppItem[];
|
|
94
|
+
original_application_version: string;
|
|
95
|
+
receipt_creation_date_ms: string;
|
|
96
|
+
expiration_date_ms: string;
|
|
97
|
+
original_purchase_date: string;
|
|
98
|
+
app_item_id: string;
|
|
99
|
+
version_external_identifier: string;
|
|
100
|
+
expires_date_ms?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validates an Apple App Store receipt against Apple's verifyReceipt endpoint.
|
|
105
|
+
* Attempts production endpoint first, falls back to sandbox if needed.
|
|
106
|
+
*
|
|
107
|
+
* @param receipt - Base64-encoded receipt data from the App Store
|
|
108
|
+
* @param config - Configuration including shared secret and optional settings
|
|
109
|
+
* @returns Validated receipt response from Apple
|
|
110
|
+
* @throws {IAPAppleError} When validation fails or receipt is invalid
|
|
111
|
+
*/
|
|
112
|
+
declare function verify(receipt: string, config: IIAPAppleConfig): Promise<IVerifyReceiptResponseBody>;
|
|
113
|
+
/**
|
|
114
|
+
* Checks whether the receipt validation was successful.
|
|
115
|
+
*
|
|
116
|
+
* @param verifyReceiptResponse - Response from Apple's verifyReceipt endpoint
|
|
117
|
+
* @returns True if the receipt status indicates success
|
|
118
|
+
*/
|
|
119
|
+
declare const isVerifiedReceipt: (verifyReceiptResponse: IVerifyReceiptResponseBody | null) => boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Determines if a purchased item has expired (cancelled or past expiration date).
|
|
122
|
+
*
|
|
123
|
+
* @param purchasedItem - The purchased item to check
|
|
124
|
+
* @returns True if the item has been cancelled or its expiration date has passed
|
|
125
|
+
* @throws {Error} If purchasedItem is invalid or missing transactionId
|
|
126
|
+
*/
|
|
127
|
+
declare const isPurchasedItemExpired: (purchasedItem: PurchasedItem | null) => boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Checks if a purchased item has been cancelled.
|
|
130
|
+
*
|
|
131
|
+
* @param purchasedItem - The purchased item to check
|
|
132
|
+
* @returns True if the item has a cancellation date
|
|
133
|
+
* @throws {Error} If purchasedItem is invalid or missing transactionId
|
|
134
|
+
*/
|
|
135
|
+
declare const isPurchasedItemCanceled: (purchasedItem: PurchasedItem) => boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Extracts purchased items from a validated receipt response.
|
|
138
|
+
* Combines in_app and latest_receipt_info, deduplicates by original_transaction_id,
|
|
139
|
+
* and returns items sorted by purchase date (newest first).
|
|
140
|
+
*
|
|
141
|
+
* @param verifyReceiptResponse - Response from Apple's verifyReceipt endpoint
|
|
142
|
+
* @returns Array of purchased items, deduplicated and sorted by purchase date descending
|
|
143
|
+
*/
|
|
144
|
+
declare const getPurchasedItems: (verifyReceiptResponse: IVerifyReceiptResponseBody | null) => PurchasedItem[];
|
|
145
|
+
|
|
146
|
+
export { type IAPAppleError, type IIAPAppleConfig, type ILogger, type IPendingRenewalInfo, type IReceiptInAppItem, type IVerifyReceiptResponseBody, type PurchasedItem, RECEIPT_STATUS_ENUM, getPurchasedItems, isPurchasedItemCanceled, isPurchasedItemExpired, isVerifiedReceipt, verify };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
declare enum RECEIPT_STATUS_ENUM {
|
|
2
|
+
SUCCESS = 0,
|
|
3
|
+
VALID_NO_PURCHASE = 2,
|
|
4
|
+
CANNOT_READ_JSON = 21000,
|
|
5
|
+
DATA_MALFORMED = 21002,
|
|
6
|
+
RECEIPT_NOT_AUTHENTICATED = 21003,
|
|
7
|
+
SHARED_SECRET_DOESNT_MATCH = 21004,
|
|
8
|
+
SERVER_NOT_AVAILABLE = 21005,
|
|
9
|
+
SUBSCRIPTION_EXPIRED = 21006,
|
|
10
|
+
TEST_ENV_RECEIPT_DETECTED = 21007,
|
|
11
|
+
PRODUCTION_ENV_RECEIPT_DETECTED = 21008,
|
|
12
|
+
INTERNAL_DATA_ACCESS_ERROR = 21009,
|
|
13
|
+
USER_ACCOUNT_DELETED = 21010
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface IPendingRenewalInfo {
|
|
17
|
+
auto_renew_product_id: string;
|
|
18
|
+
auto_renew_status: '0' | '1';
|
|
19
|
+
original_transaction_id: string;
|
|
20
|
+
product_id: string;
|
|
21
|
+
expiration_intent?: '1' | '2' | '3' | '4' | '5';
|
|
22
|
+
grace_period_expires_date_ms?: string;
|
|
23
|
+
is_in_billing_retry_period?: '0' | '1';
|
|
24
|
+
offer_code_ref_name?: string;
|
|
25
|
+
price_consent_status?: '0' | '1';
|
|
26
|
+
promotional_offer_id?: string;
|
|
27
|
+
}
|
|
28
|
+
interface IReceiptInAppItem {
|
|
29
|
+
quantity: string;
|
|
30
|
+
product_id: string;
|
|
31
|
+
transaction_id: string;
|
|
32
|
+
original_transaction_id: string;
|
|
33
|
+
purchase_date: string;
|
|
34
|
+
purchase_date_ms: string;
|
|
35
|
+
original_purchase_date: string;
|
|
36
|
+
original_purchase_date_ms: string;
|
|
37
|
+
expires_date?: string;
|
|
38
|
+
expires_date_ms?: string;
|
|
39
|
+
expiration_intent?: '1' | '2' | '3' | '4' | '5';
|
|
40
|
+
is_trial_period: string;
|
|
41
|
+
cancellation_date?: string;
|
|
42
|
+
cancellation_date_ms?: string;
|
|
43
|
+
cancellation_reason?: '0' | '1';
|
|
44
|
+
app_item_id: string;
|
|
45
|
+
web_order_line_item_id?: string;
|
|
46
|
+
is_in_intro_offer_period?: string;
|
|
47
|
+
promotional_offer_id?: string;
|
|
48
|
+
offer_code_ref_name?: string;
|
|
49
|
+
in_app_ownership_type?: 'FAMILY_SHARED' | 'PURCHASED';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface ILogger {
|
|
53
|
+
log: (message: string) => void;
|
|
54
|
+
warn: (message: string) => void;
|
|
55
|
+
error: (message: string) => void;
|
|
56
|
+
}
|
|
57
|
+
interface IIAPAppleConfig {
|
|
58
|
+
appleExcludeOldTransactions?: boolean;
|
|
59
|
+
appSharedSecret: string;
|
|
60
|
+
test?: boolean | undefined;
|
|
61
|
+
logger?: ILogger | null;
|
|
62
|
+
}
|
|
63
|
+
interface PurchasedItem {
|
|
64
|
+
bundleId: string;
|
|
65
|
+
appItemId: string;
|
|
66
|
+
originalTransactionId?: string;
|
|
67
|
+
transactionId: string;
|
|
68
|
+
productId: string;
|
|
69
|
+
originalPurchaseDateMS?: number;
|
|
70
|
+
expirationDateMS?: number;
|
|
71
|
+
purchaseDateMS: number;
|
|
72
|
+
isTrialPeriod: boolean;
|
|
73
|
+
cancellationDateMS?: number;
|
|
74
|
+
quantity: number;
|
|
75
|
+
}
|
|
76
|
+
interface IAPAppleError {
|
|
77
|
+
rejectionMessage: string;
|
|
78
|
+
data?: IVerifyReceiptResponseBody | null;
|
|
79
|
+
}
|
|
80
|
+
interface IVerifyReceiptResponseBody {
|
|
81
|
+
status: RECEIPT_STATUS_ENUM;
|
|
82
|
+
environment: 'Sandbox' | 'Production';
|
|
83
|
+
receipt: IReceipt;
|
|
84
|
+
latest_receipt: string;
|
|
85
|
+
latest_receipt_info: IReceiptInAppItem[];
|
|
86
|
+
'is-retryable'?: boolean;
|
|
87
|
+
pending_renewal_info?: IPendingRenewalInfo[];
|
|
88
|
+
}
|
|
89
|
+
interface IReceipt {
|
|
90
|
+
bundle_id: string;
|
|
91
|
+
application_version: string;
|
|
92
|
+
in_app: IReceiptInAppItem[];
|
|
93
|
+
latest_receipt_info: IReceiptInAppItem[];
|
|
94
|
+
original_application_version: string;
|
|
95
|
+
receipt_creation_date_ms: string;
|
|
96
|
+
expiration_date_ms: string;
|
|
97
|
+
original_purchase_date: string;
|
|
98
|
+
app_item_id: string;
|
|
99
|
+
version_external_identifier: string;
|
|
100
|
+
expires_date_ms?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Validates an Apple App Store receipt against Apple's verifyReceipt endpoint.
|
|
105
|
+
* Attempts production endpoint first, falls back to sandbox if needed.
|
|
106
|
+
*
|
|
107
|
+
* @param receipt - Base64-encoded receipt data from the App Store
|
|
108
|
+
* @param config - Configuration including shared secret and optional settings
|
|
109
|
+
* @returns Validated receipt response from Apple
|
|
110
|
+
* @throws {IAPAppleError} When validation fails or receipt is invalid
|
|
111
|
+
*/
|
|
112
|
+
declare function verify(receipt: string, config: IIAPAppleConfig): Promise<IVerifyReceiptResponseBody>;
|
|
113
|
+
/**
|
|
114
|
+
* Checks whether the receipt validation was successful.
|
|
115
|
+
*
|
|
116
|
+
* @param verifyReceiptResponse - Response from Apple's verifyReceipt endpoint
|
|
117
|
+
* @returns True if the receipt status indicates success
|
|
118
|
+
*/
|
|
119
|
+
declare const isVerifiedReceipt: (verifyReceiptResponse: IVerifyReceiptResponseBody | null) => boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Determines if a purchased item has expired (cancelled or past expiration date).
|
|
122
|
+
*
|
|
123
|
+
* @param purchasedItem - The purchased item to check
|
|
124
|
+
* @returns True if the item has been cancelled or its expiration date has passed
|
|
125
|
+
* @throws {Error} If purchasedItem is invalid or missing transactionId
|
|
126
|
+
*/
|
|
127
|
+
declare const isPurchasedItemExpired: (purchasedItem: PurchasedItem | null) => boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Checks if a purchased item has been cancelled.
|
|
130
|
+
*
|
|
131
|
+
* @param purchasedItem - The purchased item to check
|
|
132
|
+
* @returns True if the item has a cancellation date
|
|
133
|
+
* @throws {Error} If purchasedItem is invalid or missing transactionId
|
|
134
|
+
*/
|
|
135
|
+
declare const isPurchasedItemCanceled: (purchasedItem: PurchasedItem) => boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Extracts purchased items from a validated receipt response.
|
|
138
|
+
* Combines in_app and latest_receipt_info, deduplicates by original_transaction_id,
|
|
139
|
+
* and returns items sorted by purchase date (newest first).
|
|
140
|
+
*
|
|
141
|
+
* @param verifyReceiptResponse - Response from Apple's verifyReceipt endpoint
|
|
142
|
+
* @returns Array of purchased items, deduplicated and sorted by purchase date descending
|
|
143
|
+
*/
|
|
144
|
+
declare const getPurchasedItems: (verifyReceiptResponse: IVerifyReceiptResponseBody | null) => PurchasedItem[];
|
|
145
|
+
|
|
146
|
+
export { type IAPAppleError, type IIAPAppleConfig, type ILogger, type IPendingRenewalInfo, type IReceiptInAppItem, type IVerifyReceiptResponseBody, type PurchasedItem, RECEIPT_STATUS_ENUM, getPurchasedItems, isPurchasedItemCanceled, isPurchasedItemExpired, isVerifiedReceipt, verify };
|