@payvia-sdk/sdk 1.2.0 → 1.3.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/README.md +18 -0
- package/package.json +17 -3
- package/payvia.d.ts +313 -0
- package/payvia.js +172 -37
package/README.md
CHANGED
|
@@ -26,6 +26,24 @@ Copy `payvia.js` into your extension folder.
|
|
|
26
26
|
npm install @payvia-sdk/sdk
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## TypeScript Support
|
|
30
|
+
|
|
31
|
+
The SDK ships with built-in TypeScript declarations - no `@types/*` package needed:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import PayVia from '@payvia-sdk/sdk';
|
|
35
|
+
import type { PayViaUser, Tier } from '@payvia-sdk/sdk';
|
|
36
|
+
|
|
37
|
+
const payvia = PayVia(process.env.PAYVIA_API_KEY!);
|
|
38
|
+
|
|
39
|
+
const user: PayViaUser = await payvia.getUser();
|
|
40
|
+
if (user.tier && user.tier.level >= 1) {
|
|
41
|
+
// Pro or above
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
All methods, options, and return types have full IntelliSense support.
|
|
46
|
+
|
|
29
47
|
## Basic Usage
|
|
30
48
|
|
|
31
49
|
### 1. Add to manifest.json
|
package/package.json
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payvia-sdk/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A lightweight JavaScript SDK for connecting your Chrome Extension / SaaS app to PayVia, for accepting PayPal and Tranzila payments and managing subscriptions, license validation, tier-based feature gating, trial management and monthly / yearly / lifetime plans",
|
|
5
5
|
"main": "payvia.js",
|
|
6
|
+
"types": "payvia.d.ts",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"exports": {
|
|
8
|
-
".":
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./payvia.d.ts",
|
|
11
|
+
"import": "./payvia.js",
|
|
12
|
+
"default": "./payvia.js"
|
|
13
|
+
}
|
|
9
14
|
},
|
|
10
15
|
"files": [
|
|
11
16
|
"payvia.js",
|
|
17
|
+
"payvia.d.ts",
|
|
12
18
|
"README.md"
|
|
13
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build:types": "tsc",
|
|
22
|
+
"prepublishOnly": "npm run build:types"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.6.0"
|
|
26
|
+
},
|
|
14
27
|
"keywords": [
|
|
15
28
|
"paypal",
|
|
16
29
|
"payments",
|
|
17
30
|
"chrome-extension",
|
|
18
31
|
"saas",
|
|
19
32
|
"subscriptions",
|
|
20
|
-
"monetization"
|
|
33
|
+
"monetization",
|
|
34
|
+
"typescript"
|
|
21
35
|
],
|
|
22
36
|
"author": "PayVia",
|
|
23
37
|
"license": "MIT",
|
package/payvia.d.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
export default PayVia;
|
|
2
|
+
export type Tier = {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
/**
|
|
6
|
+
* - 0=Free, 1=Pro, 2=Super
|
|
7
|
+
*/
|
|
8
|
+
level: number;
|
|
9
|
+
features: string[];
|
|
10
|
+
};
|
|
11
|
+
export type Identity = {
|
|
12
|
+
/**
|
|
13
|
+
* - Unique user identifier (email or random pv_* ID)
|
|
14
|
+
*/
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* - User email (if known)
|
|
18
|
+
*/
|
|
19
|
+
email: string | null;
|
|
20
|
+
/**
|
|
21
|
+
* - How the identity was obtained
|
|
22
|
+
*/
|
|
23
|
+
source: "google" | "random";
|
|
24
|
+
};
|
|
25
|
+
export type PayViaUser = {
|
|
26
|
+
id: string;
|
|
27
|
+
email: string | null;
|
|
28
|
+
identitySource: "google" | "random";
|
|
29
|
+
/**
|
|
30
|
+
* - True if status is ACTIVE or TRIAL
|
|
31
|
+
*/
|
|
32
|
+
paid: boolean;
|
|
33
|
+
status: "ACTIVE" | "TRIAL" | "INACTIVE";
|
|
34
|
+
tier: Tier | null;
|
|
35
|
+
/**
|
|
36
|
+
* - Shortcut to tier.features
|
|
37
|
+
*/
|
|
38
|
+
features: string[];
|
|
39
|
+
planIds: string[];
|
|
40
|
+
isTrial: boolean;
|
|
41
|
+
trialExpiresAt?: Date | null;
|
|
42
|
+
daysRemaining?: number | null;
|
|
43
|
+
canceledAt?: Date | null;
|
|
44
|
+
currentPeriodEnd?: Date | null;
|
|
45
|
+
isCanceled?: boolean;
|
|
46
|
+
cancelGraceActive?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* - True if data came from cache
|
|
49
|
+
*/
|
|
50
|
+
fromCache: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* - Unix timestamp in ms
|
|
53
|
+
*/
|
|
54
|
+
checkedAt?: number | null;
|
|
55
|
+
/**
|
|
56
|
+
* - Cache TTL in ms
|
|
57
|
+
*/
|
|
58
|
+
ttl?: number | null;
|
|
59
|
+
/**
|
|
60
|
+
* - HMAC anti-tamper signature
|
|
61
|
+
*/
|
|
62
|
+
signature?: string | null;
|
|
63
|
+
/**
|
|
64
|
+
* - Set only when a network error occurred and no valid cache existed
|
|
65
|
+
*/
|
|
66
|
+
error?: string;
|
|
67
|
+
};
|
|
68
|
+
export type TrialStartResult = {
|
|
69
|
+
subscriptionId: string;
|
|
70
|
+
status: string;
|
|
71
|
+
planId: string;
|
|
72
|
+
planName: string;
|
|
73
|
+
trialExpiresAt: Date;
|
|
74
|
+
daysRemaining: number;
|
|
75
|
+
};
|
|
76
|
+
export type TrialStatus = {
|
|
77
|
+
status: string;
|
|
78
|
+
trialExpiresAt: Date | null;
|
|
79
|
+
daysRemaining: number | null;
|
|
80
|
+
canConvert: boolean;
|
|
81
|
+
planIds: string[];
|
|
82
|
+
};
|
|
83
|
+
export type Plan = {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
price?: number;
|
|
88
|
+
currency?: string;
|
|
89
|
+
interval?: string;
|
|
90
|
+
tierId?: string;
|
|
91
|
+
};
|
|
92
|
+
export type OpenPaymentPageOptions = {
|
|
93
|
+
/**
|
|
94
|
+
* - Checkout mode (default: 'pricing')
|
|
95
|
+
*/
|
|
96
|
+
mode?: "pricing" | "hosted" | "direct";
|
|
97
|
+
/**
|
|
98
|
+
* - Required for 'hosted' and 'direct' modes
|
|
99
|
+
*/
|
|
100
|
+
planId?: string;
|
|
101
|
+
/**
|
|
102
|
+
* - Customer email (optional; PayPal collects it for anonymous users)
|
|
103
|
+
*/
|
|
104
|
+
email?: string;
|
|
105
|
+
/**
|
|
106
|
+
* - Redirect URL after successful payment ('direct' mode only)
|
|
107
|
+
*/
|
|
108
|
+
successUrl?: string;
|
|
109
|
+
/**
|
|
110
|
+
* - Redirect URL if user cancels ('direct' mode only)
|
|
111
|
+
*/
|
|
112
|
+
cancelUrl?: string;
|
|
113
|
+
};
|
|
114
|
+
export type OpenPaymentPageResult = {
|
|
115
|
+
/**
|
|
116
|
+
* - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
|
|
117
|
+
*/
|
|
118
|
+
mode?: string | null;
|
|
119
|
+
pricingUrl?: string;
|
|
120
|
+
checkoutUrl?: string;
|
|
121
|
+
sessionId?: string;
|
|
122
|
+
/**
|
|
123
|
+
* - 'PayPal' | 'Tranzila'
|
|
124
|
+
*/
|
|
125
|
+
provider?: string;
|
|
126
|
+
};
|
|
127
|
+
export type CancelSubscriptionOptions = {
|
|
128
|
+
/**
|
|
129
|
+
* - Specific plan to cancel
|
|
130
|
+
*/
|
|
131
|
+
planId?: string;
|
|
132
|
+
/**
|
|
133
|
+
* - Cancellation reason
|
|
134
|
+
*/
|
|
135
|
+
reason?: string;
|
|
136
|
+
};
|
|
137
|
+
export type CancelSubscriptionResult = {
|
|
138
|
+
success: boolean;
|
|
139
|
+
message: string;
|
|
140
|
+
canceledPlanId?: string;
|
|
141
|
+
};
|
|
142
|
+
export type ResetLicenseResult = {
|
|
143
|
+
message: string;
|
|
144
|
+
};
|
|
145
|
+
export type OnPaidCallback = (user: PayViaUser) => void;
|
|
146
|
+
export type PayViaInstance = {
|
|
147
|
+
getUser: (options?: {
|
|
148
|
+
forceRefresh?: boolean;
|
|
149
|
+
}) => Promise<PayViaUser>;
|
|
150
|
+
refresh: () => Promise<PayViaUser>;
|
|
151
|
+
refreshLicenseCache: () => Promise<void>;
|
|
152
|
+
hasFeature: (featureName: string) => Promise<boolean>;
|
|
153
|
+
hasTierLevel: (requiredLevel: number) => Promise<boolean>;
|
|
154
|
+
getTier: () => Promise<Tier | null>;
|
|
155
|
+
startTrial: () => Promise<TrialStartResult | null>;
|
|
156
|
+
getTrialStatus: () => Promise<TrialStatus>;
|
|
157
|
+
isFirstRun: () => Promise<boolean>;
|
|
158
|
+
markFirstRunDone: () => Promise<void>;
|
|
159
|
+
needsEmailForPayment: () => Promise<boolean>;
|
|
160
|
+
getIdentity: () => Promise<Identity>;
|
|
161
|
+
openPaymentPage: (options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>;
|
|
162
|
+
onPaid: (callback: OnPaidCallback) => (() => void);
|
|
163
|
+
getPlans: () => Promise<Plan[]>;
|
|
164
|
+
resetLicense: () => Promise<ResetLicenseResult>;
|
|
165
|
+
cancelSubscription: (options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* PayVia SDK for Chrome Extensions
|
|
169
|
+
*
|
|
170
|
+
* ספריית JavaScript שהסולק מטמיע בתוסף הכרום שלו
|
|
171
|
+
* מאפשרת בדיקת רישיון, פתיחת חלון תשלום, וניהול מנויים
|
|
172
|
+
*
|
|
173
|
+
* Usage:
|
|
174
|
+
* ```javascript
|
|
175
|
+
* import PayVia from './payvia.js';
|
|
176
|
+
*
|
|
177
|
+
* const payvia = PayVia('YOUR_API_KEY');
|
|
178
|
+
*
|
|
179
|
+
* // Check if user paid
|
|
180
|
+
* const user = await payvia.getUser();
|
|
181
|
+
* if (user.paid) {
|
|
182
|
+
* // Enable premium features
|
|
183
|
+
* }
|
|
184
|
+
*
|
|
185
|
+
* // Open payment page
|
|
186
|
+
* payvia.openPaymentPage();
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
/**
|
|
190
|
+
* @typedef {Object} Tier
|
|
191
|
+
* @property {string} id
|
|
192
|
+
* @property {string} name
|
|
193
|
+
* @property {number} level - 0=Free, 1=Pro, 2=Super
|
|
194
|
+
* @property {string[]} features
|
|
195
|
+
*/
|
|
196
|
+
/**
|
|
197
|
+
* @typedef {Object} Identity
|
|
198
|
+
* @property {string} id - Unique user identifier (email or random pv_* ID)
|
|
199
|
+
* @property {string | null} email - User email (if known)
|
|
200
|
+
* @property {'google' | 'random'} source - How the identity was obtained
|
|
201
|
+
*/
|
|
202
|
+
/**
|
|
203
|
+
* @typedef {Object} PayViaUser
|
|
204
|
+
* @property {string} id
|
|
205
|
+
* @property {string | null} email
|
|
206
|
+
* @property {'google' | 'random'} identitySource
|
|
207
|
+
* @property {boolean} paid - True if status is ACTIVE or TRIAL
|
|
208
|
+
* @property {'ACTIVE' | 'TRIAL' | 'INACTIVE'} status
|
|
209
|
+
* @property {Tier | null} tier
|
|
210
|
+
* @property {string[]} features - Shortcut to tier.features
|
|
211
|
+
* @property {string[]} planIds
|
|
212
|
+
* @property {boolean} isTrial
|
|
213
|
+
* @property {Date | null} [trialExpiresAt]
|
|
214
|
+
* @property {number | null} [daysRemaining]
|
|
215
|
+
* @property {Date | null} [canceledAt]
|
|
216
|
+
* @property {Date | null} [currentPeriodEnd]
|
|
217
|
+
* @property {boolean} [isCanceled]
|
|
218
|
+
* @property {boolean} [cancelGraceActive]
|
|
219
|
+
* @property {boolean} fromCache - True if data came from cache
|
|
220
|
+
* @property {number | null} [checkedAt] - Unix timestamp in ms
|
|
221
|
+
* @property {number | null} [ttl] - Cache TTL in ms
|
|
222
|
+
* @property {string | null} [signature] - HMAC anti-tamper signature
|
|
223
|
+
* @property {string} [error] - Set only when a network error occurred and no valid cache existed
|
|
224
|
+
*/
|
|
225
|
+
/**
|
|
226
|
+
* @typedef {Object} TrialStartResult
|
|
227
|
+
* @property {string} subscriptionId
|
|
228
|
+
* @property {string} status
|
|
229
|
+
* @property {string} planId
|
|
230
|
+
* @property {string} planName
|
|
231
|
+
* @property {Date} trialExpiresAt
|
|
232
|
+
* @property {number} daysRemaining
|
|
233
|
+
*/
|
|
234
|
+
/**
|
|
235
|
+
* @typedef {Object} TrialStatus
|
|
236
|
+
* @property {string} status
|
|
237
|
+
* @property {Date | null} trialExpiresAt
|
|
238
|
+
* @property {number | null} daysRemaining
|
|
239
|
+
* @property {boolean} canConvert
|
|
240
|
+
* @property {string[]} planIds
|
|
241
|
+
*/
|
|
242
|
+
/**
|
|
243
|
+
* @typedef {Object} Plan
|
|
244
|
+
* @property {string} id
|
|
245
|
+
* @property {string} name
|
|
246
|
+
* @property {string} [description]
|
|
247
|
+
* @property {number} [price]
|
|
248
|
+
* @property {string} [currency]
|
|
249
|
+
* @property {string} [interval]
|
|
250
|
+
* @property {string} [tierId]
|
|
251
|
+
*/
|
|
252
|
+
/**
|
|
253
|
+
* @typedef {Object} OpenPaymentPageOptions
|
|
254
|
+
* @property {'pricing' | 'hosted' | 'direct'} [mode] - Checkout mode (default: 'pricing')
|
|
255
|
+
* @property {string} [planId] - Required for 'hosted' and 'direct' modes
|
|
256
|
+
* @property {string} [email] - Customer email (optional; PayPal collects it for anonymous users)
|
|
257
|
+
* @property {string} [successUrl] - Redirect URL after successful payment ('direct' mode only)
|
|
258
|
+
* @property {string} [cancelUrl] - Redirect URL if user cancels ('direct' mode only)
|
|
259
|
+
*/
|
|
260
|
+
/**
|
|
261
|
+
* @typedef {Object} OpenPaymentPageResult
|
|
262
|
+
* @property {string | null} [mode] - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
|
|
263
|
+
* @property {string} [pricingUrl]
|
|
264
|
+
* @property {string} [checkoutUrl]
|
|
265
|
+
* @property {string} [sessionId]
|
|
266
|
+
* @property {string} [provider] - 'PayPal' | 'Tranzila'
|
|
267
|
+
*/
|
|
268
|
+
/**
|
|
269
|
+
* @typedef {Object} CancelSubscriptionOptions
|
|
270
|
+
* @property {string} [planId] - Specific plan to cancel
|
|
271
|
+
* @property {string} [reason] - Cancellation reason
|
|
272
|
+
*/
|
|
273
|
+
/**
|
|
274
|
+
* @typedef {Object} CancelSubscriptionResult
|
|
275
|
+
* @property {boolean} success
|
|
276
|
+
* @property {string} message
|
|
277
|
+
* @property {string} [canceledPlanId]
|
|
278
|
+
*/
|
|
279
|
+
/**
|
|
280
|
+
* @typedef {Object} ResetLicenseResult
|
|
281
|
+
* @property {string} message
|
|
282
|
+
*/
|
|
283
|
+
/**
|
|
284
|
+
* @callback OnPaidCallback
|
|
285
|
+
* @param {PayViaUser} user
|
|
286
|
+
* @returns {void}
|
|
287
|
+
*/
|
|
288
|
+
/**
|
|
289
|
+
* @typedef {Object} PayViaInstance
|
|
290
|
+
* @property {(options?: { forceRefresh?: boolean }) => Promise<PayViaUser>} getUser
|
|
291
|
+
* @property {() => Promise<PayViaUser>} refresh
|
|
292
|
+
* @property {() => Promise<void>} refreshLicenseCache
|
|
293
|
+
* @property {(featureName: string) => Promise<boolean>} hasFeature
|
|
294
|
+
* @property {(requiredLevel: number) => Promise<boolean>} hasTierLevel
|
|
295
|
+
* @property {() => Promise<Tier | null>} getTier
|
|
296
|
+
* @property {() => Promise<TrialStartResult | null>} startTrial
|
|
297
|
+
* @property {() => Promise<TrialStatus>} getTrialStatus
|
|
298
|
+
* @property {() => Promise<boolean>} isFirstRun
|
|
299
|
+
* @property {() => Promise<void>} markFirstRunDone
|
|
300
|
+
* @property {() => Promise<boolean>} needsEmailForPayment
|
|
301
|
+
* @property {() => Promise<Identity>} getIdentity
|
|
302
|
+
* @property {(options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>} openPaymentPage
|
|
303
|
+
* @property {(callback: OnPaidCallback) => (() => void)} onPaid
|
|
304
|
+
* @property {() => Promise<Plan[]>} getPlans
|
|
305
|
+
* @property {() => Promise<ResetLicenseResult>} resetLicense
|
|
306
|
+
* @property {(options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>} cancelSubscription
|
|
307
|
+
*/
|
|
308
|
+
/**
|
|
309
|
+
* Create a PayVia SDK instance.
|
|
310
|
+
* @param {string} apiKey - API key from the PayVia dashboard
|
|
311
|
+
* @returns {PayViaInstance} PayVia SDK instance
|
|
312
|
+
*/
|
|
313
|
+
declare function PayVia(apiKey: string): PayViaInstance;
|
package/payvia.js
CHANGED
|
@@ -1,26 +1,166 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PayVia SDK for Chrome Extensions
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* ספריית JavaScript שהסולק מטמיע בתוסף הכרום שלו
|
|
5
5
|
* מאפשרת בדיקת רישיון, פתיחת חלון תשלום, וניהול מנויים
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* ```javascript
|
|
9
9
|
* import PayVia from './payvia.js';
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* const payvia = PayVia('YOUR_API_KEY');
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* // Check if user paid
|
|
14
14
|
* const user = await payvia.getUser();
|
|
15
15
|
* if (user.paid) {
|
|
16
16
|
* // Enable premium features
|
|
17
17
|
* }
|
|
18
|
-
*
|
|
18
|
+
*
|
|
19
19
|
* // Open payment page
|
|
20
20
|
* payvia.openPaymentPage();
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
+
// ============ Type Definitions (JSDoc) ============
|
|
25
|
+
// These @typedef blocks power the generated TypeScript declarations (payvia.d.ts).
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} Tier
|
|
29
|
+
* @property {string} id
|
|
30
|
+
* @property {string} name
|
|
31
|
+
* @property {number} level - 0=Free, 1=Pro, 2=Super
|
|
32
|
+
* @property {string[]} features
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {Object} Identity
|
|
37
|
+
* @property {string} id - Unique user identifier (email or random pv_* ID)
|
|
38
|
+
* @property {string | null} email - User email (if known)
|
|
39
|
+
* @property {'google' | 'random'} source - How the identity was obtained
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {Object} PayViaUser
|
|
44
|
+
* @property {string} id
|
|
45
|
+
* @property {string | null} email
|
|
46
|
+
* @property {'google' | 'random'} identitySource
|
|
47
|
+
* @property {boolean} paid - True if status is ACTIVE or TRIAL
|
|
48
|
+
* @property {'ACTIVE' | 'TRIAL' | 'INACTIVE'} status
|
|
49
|
+
* @property {Tier | null} tier
|
|
50
|
+
* @property {string[]} features - Shortcut to tier.features
|
|
51
|
+
* @property {string[]} planIds
|
|
52
|
+
* @property {boolean} isTrial
|
|
53
|
+
* @property {Date | null} [trialExpiresAt]
|
|
54
|
+
* @property {number | null} [daysRemaining]
|
|
55
|
+
* @property {Date | null} [canceledAt]
|
|
56
|
+
* @property {Date | null} [currentPeriodEnd]
|
|
57
|
+
* @property {boolean} [isCanceled]
|
|
58
|
+
* @property {boolean} [cancelGraceActive]
|
|
59
|
+
* @property {boolean} fromCache - True if data came from cache
|
|
60
|
+
* @property {number | null} [checkedAt] - Unix timestamp in ms
|
|
61
|
+
* @property {number | null} [ttl] - Cache TTL in ms
|
|
62
|
+
* @property {string | null} [signature] - HMAC anti-tamper signature
|
|
63
|
+
* @property {string} [error] - Set only when a network error occurred and no valid cache existed
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @typedef {Object} TrialStartResult
|
|
68
|
+
* @property {string} subscriptionId
|
|
69
|
+
* @property {string} status
|
|
70
|
+
* @property {string} planId
|
|
71
|
+
* @property {string} planName
|
|
72
|
+
* @property {Date} trialExpiresAt
|
|
73
|
+
* @property {number} daysRemaining
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @typedef {Object} TrialStatus
|
|
78
|
+
* @property {string} status
|
|
79
|
+
* @property {Date | null} trialExpiresAt
|
|
80
|
+
* @property {number | null} daysRemaining
|
|
81
|
+
* @property {boolean} canConvert
|
|
82
|
+
* @property {string[]} planIds
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @typedef {Object} Plan
|
|
87
|
+
* @property {string} id
|
|
88
|
+
* @property {string} name
|
|
89
|
+
* @property {string} [description]
|
|
90
|
+
* @property {number} [price]
|
|
91
|
+
* @property {string} [currency]
|
|
92
|
+
* @property {string} [interval]
|
|
93
|
+
* @property {string} [tierId]
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {Object} OpenPaymentPageOptions
|
|
98
|
+
* @property {'pricing' | 'hosted' | 'direct'} [mode] - Checkout mode (default: 'pricing')
|
|
99
|
+
* @property {string} [planId] - Required for 'hosted' and 'direct' modes
|
|
100
|
+
* @property {string} [email] - Customer email (optional; PayPal collects it for anonymous users)
|
|
101
|
+
* @property {string} [successUrl] - Redirect URL after successful payment ('direct' mode only)
|
|
102
|
+
* @property {string} [cancelUrl] - Redirect URL if user cancels ('direct' mode only)
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @typedef {Object} OpenPaymentPageResult
|
|
107
|
+
* @property {string | null} [mode] - 'pricing' | 'hosted' for those modes; null/'iframe'/'redirect' for 'direct' mode (reflects PayVia backend response shape)
|
|
108
|
+
* @property {string} [pricingUrl]
|
|
109
|
+
* @property {string} [checkoutUrl]
|
|
110
|
+
* @property {string} [sessionId]
|
|
111
|
+
* @property {string} [provider] - 'PayPal' | 'Tranzila'
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @typedef {Object} CancelSubscriptionOptions
|
|
116
|
+
* @property {string} [planId] - Specific plan to cancel
|
|
117
|
+
* @property {string} [reason] - Cancellation reason
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @typedef {Object} CancelSubscriptionResult
|
|
122
|
+
* @property {boolean} success
|
|
123
|
+
* @property {string} message
|
|
124
|
+
* @property {string} [canceledPlanId]
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @typedef {Object} ResetLicenseResult
|
|
129
|
+
* @property {string} message
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @callback OnPaidCallback
|
|
134
|
+
* @param {PayViaUser} user
|
|
135
|
+
* @returns {void}
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @typedef {Object} PayViaInstance
|
|
140
|
+
* @property {(options?: { forceRefresh?: boolean }) => Promise<PayViaUser>} getUser
|
|
141
|
+
* @property {() => Promise<PayViaUser>} refresh
|
|
142
|
+
* @property {() => Promise<void>} refreshLicenseCache
|
|
143
|
+
* @property {(featureName: string) => Promise<boolean>} hasFeature
|
|
144
|
+
* @property {(requiredLevel: number) => Promise<boolean>} hasTierLevel
|
|
145
|
+
* @property {() => Promise<Tier | null>} getTier
|
|
146
|
+
* @property {() => Promise<TrialStartResult | null>} startTrial
|
|
147
|
+
* @property {() => Promise<TrialStatus>} getTrialStatus
|
|
148
|
+
* @property {() => Promise<boolean>} isFirstRun
|
|
149
|
+
* @property {() => Promise<void>} markFirstRunDone
|
|
150
|
+
* @property {() => Promise<boolean>} needsEmailForPayment
|
|
151
|
+
* @property {() => Promise<Identity>} getIdentity
|
|
152
|
+
* @property {(options?: OpenPaymentPageOptions) => Promise<OpenPaymentPageResult>} openPaymentPage
|
|
153
|
+
* @property {(callback: OnPaidCallback) => (() => void)} onPaid
|
|
154
|
+
* @property {() => Promise<Plan[]>} getPlans
|
|
155
|
+
* @property {() => Promise<ResetLicenseResult>} resetLicense
|
|
156
|
+
* @property {(options?: CancelSubscriptionOptions) => Promise<CancelSubscriptionResult>} cancelSubscription
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Create a PayVia SDK instance.
|
|
161
|
+
* @param {string} apiKey - API key from the PayVia dashboard
|
|
162
|
+
* @returns {PayViaInstance} PayVia SDK instance
|
|
163
|
+
*/
|
|
24
164
|
function PayVia(apiKey) {
|
|
25
165
|
if (!apiKey) {
|
|
26
166
|
throw new Error('PayVia: API key is required');
|
|
@@ -32,8 +172,11 @@ function PayVia(apiKey) {
|
|
|
32
172
|
const DEFAULT_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
33
173
|
const GRACE_PERIOD_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
34
174
|
|
|
35
|
-
|
|
175
|
+
/** @type {PayViaInstance} */
|
|
176
|
+
const instance = /** @type {PayViaInstance} */ ({});
|
|
177
|
+
/** @type {PayViaUser | null} */
|
|
36
178
|
let cachedUser = null;
|
|
179
|
+
/** @type {Promise<PayViaUser> | null} */
|
|
37
180
|
let userPromise = null;
|
|
38
181
|
|
|
39
182
|
// ============ License Cache Storage ============
|
|
@@ -233,10 +376,9 @@ function PayVia(apiKey) {
|
|
|
233
376
|
}
|
|
234
377
|
|
|
235
378
|
/**
|
|
236
|
-
* Get user's payment status
|
|
379
|
+
* Get user's payment status.
|
|
237
380
|
* Uses cache first, then server. Falls back to cache during network errors.
|
|
238
|
-
* @param {
|
|
239
|
-
* @param {boolean} options.forceRefresh - Force fetch from server
|
|
381
|
+
* @param {{ forceRefresh?: boolean }} [options]
|
|
240
382
|
* @returns {Promise<PayViaUser>} User object with payment status
|
|
241
383
|
*/
|
|
242
384
|
instance.getUser = async function (options = {}) {
|
|
@@ -395,8 +537,8 @@ function PayVia(apiKey) {
|
|
|
395
537
|
};
|
|
396
538
|
|
|
397
539
|
/**
|
|
398
|
-
* Get the user's current tier info
|
|
399
|
-
* @returns {Promise<
|
|
540
|
+
* Get the user's current tier info.
|
|
541
|
+
* @returns {Promise<Tier | null>}
|
|
400
542
|
*/
|
|
401
543
|
instance.getTier = async function () {
|
|
402
544
|
const user = await instance.getUser();
|
|
@@ -404,10 +546,10 @@ function PayVia(apiKey) {
|
|
|
404
546
|
};
|
|
405
547
|
|
|
406
548
|
/**
|
|
407
|
-
* Start a trial for the current user
|
|
408
|
-
* Call this when user first installs/uses the extension
|
|
409
|
-
* Idempotent: if user already has a trial/active subscription, returns existing info
|
|
410
|
-
* @returns {Promise<
|
|
549
|
+
* Start a trial for the current user.
|
|
550
|
+
* Call this when user first installs/uses the extension.
|
|
551
|
+
* Idempotent: if user already has a trial/active subscription, returns existing info.
|
|
552
|
+
* @returns {Promise<TrialStartResult | null>}
|
|
411
553
|
*/
|
|
412
554
|
instance.startTrial = async function () {
|
|
413
555
|
try {
|
|
@@ -438,8 +580,8 @@ function PayVia(apiKey) {
|
|
|
438
580
|
};
|
|
439
581
|
|
|
440
582
|
/**
|
|
441
|
-
* Get trial status for the current user
|
|
442
|
-
* @returns {Promise<
|
|
583
|
+
* Get trial status for the current user.
|
|
584
|
+
* @returns {Promise<TrialStatus>}
|
|
443
585
|
*/
|
|
444
586
|
instance.getTrialStatus = async function () {
|
|
445
587
|
try {
|
|
@@ -486,6 +628,7 @@ function PayVia(apiKey) {
|
|
|
486
628
|
|
|
487
629
|
/**
|
|
488
630
|
* Mark first run as complete
|
|
631
|
+
* @returns {Promise<void>}
|
|
489
632
|
*/
|
|
490
633
|
instance.markFirstRunDone = async function () {
|
|
491
634
|
return new Promise((resolve) => {
|
|
@@ -508,24 +651,17 @@ function PayVia(apiKey) {
|
|
|
508
651
|
};
|
|
509
652
|
|
|
510
653
|
/**
|
|
511
|
-
* Get the current user identity info
|
|
512
|
-
* @returns {Promise<
|
|
654
|
+
* Get the current user identity info.
|
|
655
|
+
* @returns {Promise<Identity>}
|
|
513
656
|
*/
|
|
514
657
|
instance.getIdentity = async function () {
|
|
515
658
|
return getUserIdentity();
|
|
516
659
|
};
|
|
517
660
|
|
|
518
661
|
/**
|
|
519
|
-
* Open payment page for the user
|
|
520
|
-
* @param {
|
|
521
|
-
* @
|
|
522
|
-
* @param {string} options.email - Customer email
|
|
523
|
-
* @param {'pricing'|'hosted'|'direct'} options.mode - Checkout mode:
|
|
524
|
-
* - 'pricing': Shows all plans for user to choose (default, most secure)
|
|
525
|
-
* - 'hosted': Goes directly to checkout for specific plan
|
|
526
|
-
* - 'direct': Bypasses PayVia, goes straight to PayPal
|
|
527
|
-
* @param {string} options.successUrl - URL to redirect after successful payment (direct mode only)
|
|
528
|
-
* @param {string} options.cancelUrl - URL to redirect if user cancels (direct mode only)
|
|
662
|
+
* Open payment page for the user.
|
|
663
|
+
* @param {OpenPaymentPageOptions} [options] - Payment options
|
|
664
|
+
* @returns {Promise<OpenPaymentPageResult>}
|
|
529
665
|
*/
|
|
530
666
|
instance.openPaymentPage = async function (options = {}) {
|
|
531
667
|
const identity = await getUserIdentity();
|
|
@@ -619,8 +755,9 @@ function PayVia(apiKey) {
|
|
|
619
755
|
};
|
|
620
756
|
|
|
621
757
|
/**
|
|
622
|
-
* Listen for payment status changes
|
|
623
|
-
* @param {
|
|
758
|
+
* Listen for payment status changes (polls every 5 seconds).
|
|
759
|
+
* @param {OnPaidCallback} callback - Called when payment status changes
|
|
760
|
+
* @returns {() => void} Unsubscribe function - call to stop listening
|
|
624
761
|
*/
|
|
625
762
|
instance.onPaid = function (callback) {
|
|
626
763
|
// Poll for status changes every 5 seconds when tab is visible
|
|
@@ -661,7 +798,7 @@ function PayVia(apiKey) {
|
|
|
661
798
|
/**
|
|
662
799
|
* Reset the user's license (delete all subscriptions).
|
|
663
800
|
* This is for demo/testing purposes only.
|
|
664
|
-
* @returns {Promise<
|
|
801
|
+
* @returns {Promise<ResetLicenseResult>}
|
|
665
802
|
*/
|
|
666
803
|
instance.resetLicense = async function () {
|
|
667
804
|
const identity = await getUserIdentity();
|
|
@@ -674,11 +811,9 @@ function PayVia(apiKey) {
|
|
|
674
811
|
};
|
|
675
812
|
|
|
676
813
|
/**
|
|
677
|
-
* Cancel a subscription for the current user
|
|
678
|
-
* @param {
|
|
679
|
-
* @
|
|
680
|
-
* @param {string} options.reason - Cancellation reason (optional)
|
|
681
|
-
* @returns {Promise<{success: boolean, message: string, canceledPlanId: string}>}
|
|
814
|
+
* Cancel a subscription for the current user.
|
|
815
|
+
* @param {CancelSubscriptionOptions} [options]
|
|
816
|
+
* @returns {Promise<CancelSubscriptionResult>}
|
|
682
817
|
*/
|
|
683
818
|
instance.cancelSubscription = async function (options = {}) {
|
|
684
819
|
const identity = await getUserIdentity();
|