@skalpgg/sdk 1.6.0 → 1.8.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 +16 -5
- package/dist/cjs/index.d.ts +10 -3
- package/dist/cjs/index.js +16 -6
- package/dist/cjs/types.d.ts +93 -10
- package/dist/esm/index.d.ts +10 -3
- package/dist/esm/index.js +16 -6
- package/dist/esm/types.d.ts +93 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,8 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
|
|
|
41
41
|
|
|
42
42
|
| Method | Scope |
|
|
43
43
|
| --- | --- |
|
|
44
|
-
| `
|
|
44
|
+
| `me()` | none |
|
|
45
|
+
| `checkout.create({ productId, quantity?, customerEmail?, metadata?, couponCode?, returnUrl?, customFields?, player? })` | `checkout:write` |
|
|
45
46
|
| `checkout.get(id)` | `checkout:read` |
|
|
46
47
|
| `orders.list({ status?, productId?, email?, identifier?, createdAfter?, createdBefore?, updatedSince?, limit?, offset? })` | `orders:read` |
|
|
47
48
|
| `orders.get(id)` | `orders:read` |
|
|
@@ -63,7 +64,7 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
|
|
|
63
64
|
| `groups.list()` / `groups.get(id)` | `products:read` |
|
|
64
65
|
| `groups.create({ title, productIds, ... })` / `groups.update(id, { ... })` / `groups.delete(id)` | `products:write` |
|
|
65
66
|
| `coupons.list()` / `coupons.get(id)` | `coupons:read` |
|
|
66
|
-
| `coupons.create({ code, discountType?, discountPercent?, discountAmount?, validFrom?, validTo?, maxUses?, ... })` / `coupons.update(id, { ... })` / `coupons.delete(id)` | `coupons:write` |
|
|
67
|
+
| `coupons.create({ code, discountType?, discountPercent?, discountAmount?, validFrom?, validTo?, maxUses?, subscriptionDuration?, subscriptionMonths?, ... })` / `coupons.update(id, { ... })` / `coupons.delete(id)` | `coupons:write` |
|
|
67
68
|
| `customers.list({ search?, limit?, offset? })` / `customers.get(id)` | `customers:read` |
|
|
68
69
|
| `customers.create({ email, name?, note? })` / `customers.update(id, { name?, note? })` / `customers.delete(id)` | `customers:write` |
|
|
69
70
|
| `feedback.list({ productId?, rating?, limit?, offset? })` / `feedback.get(id)` | `feedback:read` |
|
|
@@ -86,6 +87,8 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
|
|
|
86
87
|
| `licenses.resetDevices({ key, hardwareId? })` | `licenses:write` |
|
|
87
88
|
| `licenses.verify({ licenseKey, serverIp, serverKey, serverPort? })` | none |
|
|
88
89
|
| `licenses.heartbeat({ licenseKey, serverIp })` | none |
|
|
90
|
+
| `webhooks.list()` | `webhooks:read` |
|
|
91
|
+
| `webhooks.create({ url, events, productIds? })` / `webhooks.delete(id)` | `webhooks:write` |
|
|
89
92
|
| `webhooks.constructEvent(rawBody, headers)` | none |
|
|
90
93
|
| `webhooks.verify(rawBody, headers)` | none |
|
|
91
94
|
|
|
@@ -107,7 +110,7 @@ const { added, skipped, stock } = await skalp.products.addSerials(product.id, {
|
|
|
107
110
|
await skalp.products.submit(product.id)
|
|
108
111
|
```
|
|
109
112
|
|
|
110
|
-
A product starts as a `DRAFT`. `submit` sends it to review, and the review sets `ACTIVE` or `REJECTED`; read the product to see which. `update` accepts only `DRAFT` and `ARCHIVED` as a `status`, and `archive` takes a product off sale without deleting anything. Pass `null` to `update` to clear `comparePrice`, `storeCategoryId`, `dynamicUrl` or `
|
|
113
|
+
A product starts as a `DRAFT`. `submit` sends it to review, and the review sets `ACTIVE` or `REJECTED`; read the product to see which. `update` accepts only `DRAFT` and `ARCHIVED` as a `status`, and `archive` takes a product off sale without deleting anything. Pass `null` to `update` to clear `comparePrice`, `storeCategoryId`, `dynamicUrl`, `licenseDurationDays` or `trialPrice`. `trialPrice` is what the buyer pays for the trial of a recurring product in a digital store, in the store currency before VAT, and `null` makes the trial free.
|
|
111
114
|
|
|
112
115
|
`price` is in your store currency, and buyers in Poland, the euro area, the US and Brazil pay it converted at the day's rate. To charge a round local price instead, pass `prices: [{ currency: 'PLN', price: 79 }]`: up to three currencies other than the store one, from 5 to 999999 each, not on coin packs. The list replaces the old one, and `[]` removes them.
|
|
113
116
|
|
|
@@ -135,7 +138,9 @@ const { replacements } = await skalp.orders.replace(order.id, { reason: 'Key doe
|
|
|
135
138
|
|
|
136
139
|
`updatedSince` lists oldest change first, so you can page through it and keep the last `updatedAt` as your cursor; without it, newest orders come first. Amounts are in major units (`19.5`).
|
|
137
140
|
|
|
138
|
-
Coupons take `validFrom`, `validTo` as an ISO string or a `Date`; `coupons.update` accepts `null` to clear `validTo`, `maxUses`, `minPurchaseAmount` and `description`.
|
|
141
|
+
Coupons take `validFrom`, `validTo` as an ISO string or a `Date`; `coupons.update` accepts `null` to clear `validTo`, `maxUses`, `minPurchaseAmount`, `subscriptionMonths` and `description`. On a subscription, `subscriptionDuration` sets how long the discount lasts: `ONCE` (the default), `REPEATING` for `subscriptionMonths` (1 to 36) or `FOREVER`.
|
|
142
|
+
|
|
143
|
+
`me()` returns the store and the key you are using, with its scopes. `checkout.create` takes `player`, a `name` and game `ids` such as `steamid64` or `mc_name`, when your server already knows who gets the order. Orders carry `serviceFee`, the buyer fee included in `amount`, and customers carry `spent`, one total per currency.
|
|
139
144
|
|
|
140
145
|
## Support and access rules
|
|
141
146
|
|
|
@@ -180,9 +185,15 @@ export async function POST(request: Request) {
|
|
|
180
185
|
}
|
|
181
186
|
```
|
|
182
187
|
|
|
188
|
+
`webhooks.create` returns the endpoint's signing `secret` once, so store it then. `events` takes event names or `'*'` for all of them.
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
const { id, secret } = await skalp.webhooks.create({ url: 'https://example.com/skalp', events: ['order.paid', 'subscription.renewed'] })
|
|
192
|
+
```
|
|
193
|
+
|
|
183
194
|
A webhook with the default events receives every purchase as both `order.paid` and its legacy name `purchase.completed`. Handle `order.paid` and deduplicate on `data.idempotencyKey`.
|
|
184
195
|
|
|
185
|
-
`order.created`, `order.updated`, `order.canceled`, `order.replaced`, `query.created`, `query.replied`, `feedback.received` and the subscription events `subscription.
|
|
196
|
+
`order.created`, `order.updated`, `order.canceled`, `order.replaced`, `query.created`, `query.replied`, `feedback.received` and the subscription events `subscription.trial_started`, `subscription.trial_ended` and `subscription.upcoming` are not in the default list either: subscribe the webhook to them by name, and `event.type` narrows `event.data` to the right payload. `order.created`, `order.updated` and `order.canceled` carry the order as `orders.get` returns it, plus `previousStatus`; `order.replaced` adds `reason` and the new keys in `replacements[].key`. Every one of them, like `query.created`, `query.replied` and `feedback.received`, carries a `data.idempotencyKey` that stays the same on every retry of the same event, so deduplicate on it. `subscription.trial_started` follows `subscription.created` when a subscription starts with a trial, free or paid, `subscription.trial_ended` comes when the trial is over, and `subscription.upcoming` comes before a renewal is charged.
|
|
186
197
|
|
|
187
198
|
`product.created`, `product.updated` and `product.stock` are not in the default list: subscribe the webhook to them by name. `product.stock` carries `stock`, `previousStock` and `change` whenever the number of available keys changes.
|
|
188
199
|
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams } from './types.js';
|
|
1
|
+
import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, CreateWebhookParams, CreatedWebhookEndpoint, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Me, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams, WebhookEndpoint } from './types.js';
|
|
2
2
|
export type * from './types.js';
|
|
3
|
-
export declare const VERSION = "1.
|
|
3
|
+
export declare const VERSION = "1.8.0";
|
|
4
4
|
export interface SkalpOptions {
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
webhookSecret?: string;
|
|
@@ -31,8 +31,9 @@ export declare class SkalpSignatureError extends Error {
|
|
|
31
31
|
export declare class Skalp {
|
|
32
32
|
#private;
|
|
33
33
|
constructor(options?: string | SkalpOptions);
|
|
34
|
+
readonly me: () => Promise<Me>;
|
|
34
35
|
readonly checkout: {
|
|
35
|
-
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
36
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
36
37
|
get: (id: string) => Promise<CheckoutSessionStatus>;
|
|
37
38
|
};
|
|
38
39
|
readonly orders: {
|
|
@@ -129,6 +130,12 @@ export declare class Skalp {
|
|
|
129
130
|
}>;
|
|
130
131
|
};
|
|
131
132
|
readonly webhooks: {
|
|
133
|
+
list: () => Promise<WebhookEndpoint[]>;
|
|
134
|
+
create: ({ url, events, productIds }: CreateWebhookParams) => Promise<CreatedWebhookEndpoint>;
|
|
135
|
+
delete: (id: string) => Promise<{
|
|
136
|
+
id: string;
|
|
137
|
+
deleted: true;
|
|
138
|
+
}>;
|
|
132
139
|
verify: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<boolean>;
|
|
133
140
|
constructEvent: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<SkalpEvent>;
|
|
134
141
|
};
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Skalp = exports.SkalpSignatureError = exports.SkalpConnectionError = exports.SkalpError = exports.VERSION = void 0;
|
|
4
|
-
exports.VERSION = '1.
|
|
4
|
+
exports.VERSION = '1.8.0';
|
|
5
5
|
const SIGNATURE_HEADER = 'skalp-signature';
|
|
6
6
|
const SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
7
7
|
const PRODUCT_PAGE = 100;
|
|
@@ -60,6 +60,7 @@ const PRODUCT_FIELDS = [
|
|
|
60
60
|
'fulfillmentType',
|
|
61
61
|
'billingInterval',
|
|
62
62
|
'trialPeriodDays',
|
|
63
|
+
'trialPrice',
|
|
63
64
|
'dynamicUrl',
|
|
64
65
|
'licenseDeviceLimit',
|
|
65
66
|
'licenseDurationDays',
|
|
@@ -81,6 +82,9 @@ const PRODUCT_FIELDS = [
|
|
|
81
82
|
'volumeDiscounts',
|
|
82
83
|
'upsells',
|
|
83
84
|
'prices',
|
|
85
|
+
'poolsEnabled',
|
|
86
|
+
'upgradeFrom',
|
|
87
|
+
'includes',
|
|
84
88
|
];
|
|
85
89
|
const COUPON_FIELDS = [
|
|
86
90
|
'discountType',
|
|
@@ -92,6 +96,8 @@ const COUPON_FIELDS = [
|
|
|
92
96
|
'maxUses',
|
|
93
97
|
'minPurchaseAmount',
|
|
94
98
|
'oneTimePerUser',
|
|
99
|
+
'subscriptionDuration',
|
|
100
|
+
'subscriptionMonths',
|
|
95
101
|
];
|
|
96
102
|
const GROUP_FIELDS = ['title', 'productIds', 'description', 'image', 'sortPriority', 'unlisted'];
|
|
97
103
|
function pick(source, keys) {
|
|
@@ -122,9 +128,10 @@ class Skalp {
|
|
|
122
128
|
throw new Error('Skalp: your API key is a secret and must never reach the browser. Call the SDK from server code, or pass dangerouslyAllowBrowser: true if you really know what you are doing.');
|
|
123
129
|
}
|
|
124
130
|
}
|
|
131
|
+
me = () => this.#request('GET', '/v1/me');
|
|
125
132
|
checkout = {
|
|
126
|
-
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
127
|
-
body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields },
|
|
133
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
134
|
+
body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields, player },
|
|
128
135
|
}),
|
|
129
136
|
get: (id) => this.#request('GET', `/v1/checkout/sessions/${segment(id)}`),
|
|
130
137
|
};
|
|
@@ -302,6 +309,9 @@ class Skalp {
|
|
|
302
309
|
}),
|
|
303
310
|
};
|
|
304
311
|
webhooks = {
|
|
312
|
+
list: () => this.#request('GET', '/v1/webhooks'),
|
|
313
|
+
create: ({ url, events, productIds }) => this.#request('POST', '/v1/webhooks', { body: { url, events, productIds } }),
|
|
314
|
+
delete: (id) => this.#request('DELETE', `/v1/webhooks/${segment(id)}`),
|
|
305
315
|
verify: async (payload, signature, secret) => (await this.#checkSignature(payload, signature, secret)) === undefined,
|
|
306
316
|
constructEvent: async (payload, signature, secret) => {
|
|
307
317
|
const failure = await this.#checkSignature(payload, signature, secret);
|
|
@@ -415,10 +425,10 @@ function parseSignature(header) {
|
|
|
415
425
|
function toBytes(payload, encoder) {
|
|
416
426
|
if (typeof payload === 'string')
|
|
417
427
|
return encoder.encode(payload);
|
|
418
|
-
if (payload
|
|
428
|
+
if (ArrayBuffer.isView(payload))
|
|
429
|
+
return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
|
|
430
|
+
if (Object.prototype.toString.call(payload) === '[object ArrayBuffer]')
|
|
419
431
|
return new Uint8Array(payload);
|
|
420
|
-
if (payload instanceof Uint8Array)
|
|
421
|
-
return payload;
|
|
422
432
|
throw new TypeError('Skalp: webhook payload must be the raw request body (string, Buffer or ArrayBuffer). A parsed JSON object cannot be verified, because re-serializing it changes the bytes that were signed.');
|
|
423
433
|
}
|
|
424
434
|
function retryAfterSeconds(res, attempt) {
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -3,12 +3,21 @@ export type FulfillmentType = 'FILE' | 'SERIAL' | 'GAME' | 'SERVICE' | 'DYNAMIC'
|
|
|
3
3
|
export type ProductStatus = 'DRAFT' | 'PENDING_REVIEW' | 'PROCESSING' | 'PROCESSING_FAILED' | 'ACTIVE' | 'REJECTED' | 'ARCHIVED';
|
|
4
4
|
export type ProductType = 'ONE_TIME' | 'RECURRING' | 'COINS';
|
|
5
5
|
export type Game = 'fivem' | 'minecraft' | 'rust';
|
|
6
|
-
export type BillingInterval = 'WEEK' | 'MONTH' | 'YEAR';
|
|
6
|
+
export type BillingInterval = 'WEEK' | 'MONTH' | 'QUARTER' | 'HALF_YEAR' | 'YEAR';
|
|
7
7
|
export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | 'CANCELED';
|
|
8
|
-
export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL';
|
|
8
|
+
export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL' | 'PAYSSION';
|
|
9
9
|
export type DeliveryStatus = 'PENDING' | 'PROCESSING' | 'DELIVERED' | 'FAILED';
|
|
10
10
|
export type SubscriptionStatus = 'ACTIVE' | 'CANCELED' | 'PAST_DUE' | 'UNPAID' | 'INCOMPLETE' | 'INCOMPLETE_EXPIRED' | 'TRIALING' | 'PAUSED';
|
|
11
11
|
export type Metadata = Record<string, string>;
|
|
12
|
+
export type PlayerIdKey = 'fivem' | 'license2' | 'steam' | 'discord' | 'xbl' | 'live' | 'fivemId' | 'mc_uuid' | 'mc_name' | 'steamid64';
|
|
13
|
+
export interface PlayerInput {
|
|
14
|
+
name?: string;
|
|
15
|
+
ids?: Partial<Record<PlayerIdKey, string>>;
|
|
16
|
+
}
|
|
17
|
+
export interface Player {
|
|
18
|
+
name: string | null;
|
|
19
|
+
ids: Partial<Record<PlayerIdKey, string>>;
|
|
20
|
+
}
|
|
12
21
|
export interface CreateCheckoutParams {
|
|
13
22
|
productId: string;
|
|
14
23
|
/** Units to sell, within the product's minQuantity and maxQuantity. Defaults to minQuantity. */
|
|
@@ -19,6 +28,7 @@ export interface CreateCheckoutParams {
|
|
|
19
28
|
returnUrl?: string;
|
|
20
29
|
/** Answers you already have, by field key; the buyer adds the rest on the pay page. */
|
|
21
30
|
customFields?: Record<string, string>;
|
|
31
|
+
player?: PlayerInput;
|
|
22
32
|
}
|
|
23
33
|
export interface CheckoutSession {
|
|
24
34
|
id: string;
|
|
@@ -28,7 +38,7 @@ export interface CheckoutSession {
|
|
|
28
38
|
}
|
|
29
39
|
export interface CheckoutSessionStatus {
|
|
30
40
|
id: string;
|
|
31
|
-
status: 'pending' | 'completed' | 'failed';
|
|
41
|
+
status: 'pending' | 'completed' | 'failed' | 'canceled';
|
|
32
42
|
orderNumber: string;
|
|
33
43
|
amount: number;
|
|
34
44
|
currency: Currency;
|
|
@@ -45,23 +55,24 @@ export interface Order {
|
|
|
45
55
|
vatRate: number | null;
|
|
46
56
|
currency: Currency;
|
|
47
57
|
discountAmount: number;
|
|
58
|
+
serviceFee: number | null;
|
|
48
59
|
couponCode: string | null;
|
|
49
60
|
productId: string;
|
|
50
61
|
productName: string;
|
|
51
62
|
productSlug: string;
|
|
52
63
|
/** Units of productId. */
|
|
53
64
|
quantity: number;
|
|
54
|
-
fulfillmentType: FulfillmentType;
|
|
65
|
+
fulfillmentType: FulfillmentType | null;
|
|
55
66
|
bundleId: string | null;
|
|
56
67
|
buyerEmail: string;
|
|
57
68
|
buyerCountry: string | null;
|
|
58
69
|
paymentProvider: PaymentProvider | null;
|
|
59
70
|
isGift: boolean;
|
|
60
|
-
granted
|
|
71
|
+
granted: boolean;
|
|
61
72
|
deliveryStatus: DeliveryStatus | null;
|
|
62
73
|
serialsCount?: number;
|
|
63
74
|
serialsReplaced?: number;
|
|
64
|
-
/** Delivered and replaced keys by id, never their values.
|
|
75
|
+
/** Delivered and replaced keys by id, never their values. Filled in by orders.get, orders.cancel and orders.redeliver. */
|
|
65
76
|
serials?: Array<OrderSerial>;
|
|
66
77
|
createdAt: string;
|
|
67
78
|
updatedAt: string;
|
|
@@ -199,6 +210,7 @@ export interface Product {
|
|
|
199
210
|
productType: ProductType;
|
|
200
211
|
billingInterval: BillingInterval | null;
|
|
201
212
|
trialPeriodDays: number;
|
|
213
|
+
trialPrice: number | null;
|
|
202
214
|
fulfillmentType: FulfillmentType | null;
|
|
203
215
|
game: Game | null;
|
|
204
216
|
category: string;
|
|
@@ -239,6 +251,9 @@ export interface Product {
|
|
|
239
251
|
volumeDiscounts: Array<VolumeDiscount>;
|
|
240
252
|
/** Products offered on this product's checkout page. */
|
|
241
253
|
upsells: Array<ProductUpsell>;
|
|
254
|
+
poolsEnabled: boolean | null;
|
|
255
|
+
upgradeFrom: Array<string>;
|
|
256
|
+
includes: Array<string>;
|
|
242
257
|
stock: number | null;
|
|
243
258
|
sale: ProductSale | null;
|
|
244
259
|
salesCount: number;
|
|
@@ -281,6 +296,7 @@ interface ProductFields {
|
|
|
281
296
|
fulfillmentType?: FulfillmentType;
|
|
282
297
|
billingInterval?: BillingInterval;
|
|
283
298
|
trialPeriodDays?: number;
|
|
299
|
+
trialPrice?: number | null;
|
|
284
300
|
dynamicUrl?: string | null;
|
|
285
301
|
licenseDeviceLimit?: number;
|
|
286
302
|
licenseDurationDays?: number | null;
|
|
@@ -311,6 +327,9 @@ interface ProductFields {
|
|
|
311
327
|
upsells?: Array<ProductUpsellInput> | null;
|
|
312
328
|
/** Up to 3 currencies other than the store currency, not for coin packs; the list replaces the old one, [] or null removes them all. */
|
|
313
329
|
prices?: Array<ProductPrice> | null;
|
|
330
|
+
poolsEnabled?: boolean;
|
|
331
|
+
upgradeFrom?: Array<string>;
|
|
332
|
+
includes?: Array<string>;
|
|
314
333
|
}
|
|
315
334
|
export interface CreateProductParams extends ProductFields {
|
|
316
335
|
name: string;
|
|
@@ -368,6 +387,39 @@ export interface Deleted {
|
|
|
368
387
|
id: string;
|
|
369
388
|
deleted: true;
|
|
370
389
|
}
|
|
390
|
+
export interface Me {
|
|
391
|
+
store: {
|
|
392
|
+
id: string;
|
|
393
|
+
name: string;
|
|
394
|
+
slug: string;
|
|
395
|
+
currency: Currency;
|
|
396
|
+
url: string;
|
|
397
|
+
};
|
|
398
|
+
key: {
|
|
399
|
+
name: string;
|
|
400
|
+
scopes: Array<string>;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
export type WebhookEventName = SkalpEventType | '*';
|
|
404
|
+
export interface WebhookEndpoint {
|
|
405
|
+
id: string;
|
|
406
|
+
url: string;
|
|
407
|
+
events: Array<WebhookEventName>;
|
|
408
|
+
format: 'skalp' | (string & {});
|
|
409
|
+
isActive: boolean;
|
|
410
|
+
createdAt: string;
|
|
411
|
+
}
|
|
412
|
+
export interface CreateWebhookParams {
|
|
413
|
+
url: string;
|
|
414
|
+
events: Array<WebhookEventName>;
|
|
415
|
+
productIds?: Array<string>;
|
|
416
|
+
}
|
|
417
|
+
export interface CreatedWebhookEndpoint {
|
|
418
|
+
id: string;
|
|
419
|
+
url: string;
|
|
420
|
+
events: Array<WebhookEventName>;
|
|
421
|
+
secret: string;
|
|
422
|
+
}
|
|
371
423
|
export interface StoreCategory {
|
|
372
424
|
id: string;
|
|
373
425
|
name: string;
|
|
@@ -421,6 +473,7 @@ export interface UpdateProductGroupParams {
|
|
|
421
473
|
unlisted?: boolean;
|
|
422
474
|
}
|
|
423
475
|
export type CouponDiscountType = 'PERCENT' | 'FIXED';
|
|
476
|
+
export type CouponDuration = 'ONCE' | 'REPEATING' | 'FOREVER';
|
|
424
477
|
export interface Coupon {
|
|
425
478
|
id: string;
|
|
426
479
|
code: string;
|
|
@@ -430,6 +483,8 @@ export interface Coupon {
|
|
|
430
483
|
discountAmount: number | null;
|
|
431
484
|
productIds: Array<string>;
|
|
432
485
|
disabledWithVolumeDiscounts: boolean;
|
|
486
|
+
subscriptionDuration: CouponDuration;
|
|
487
|
+
subscriptionMonths: number | null;
|
|
433
488
|
validFrom: string;
|
|
434
489
|
validTo: string | null;
|
|
435
490
|
maxUses: number | null;
|
|
@@ -453,6 +508,8 @@ export interface CreateCouponParams {
|
|
|
453
508
|
maxUses?: number;
|
|
454
509
|
minPurchaseAmount?: number;
|
|
455
510
|
oneTimePerUser?: boolean;
|
|
511
|
+
subscriptionDuration?: CouponDuration;
|
|
512
|
+
subscriptionMonths?: number;
|
|
456
513
|
}
|
|
457
514
|
export interface UpdateCouponParams {
|
|
458
515
|
discountType?: CouponDiscountType;
|
|
@@ -467,6 +524,8 @@ export interface UpdateCouponParams {
|
|
|
467
524
|
minPurchaseAmount?: number | null;
|
|
468
525
|
oneTimePerUser?: boolean;
|
|
469
526
|
isActive?: boolean;
|
|
527
|
+
subscriptionDuration?: CouponDuration;
|
|
528
|
+
subscriptionMonths?: number | null;
|
|
470
529
|
}
|
|
471
530
|
export interface Customer {
|
|
472
531
|
id: string;
|
|
@@ -477,6 +536,10 @@ export interface Customer {
|
|
|
477
536
|
ordersCount: number;
|
|
478
537
|
totalSpent: number;
|
|
479
538
|
currency: Currency;
|
|
539
|
+
spent: Array<{
|
|
540
|
+
currency: Currency;
|
|
541
|
+
amount: number;
|
|
542
|
+
}>;
|
|
480
543
|
firstOrderAt: string | null;
|
|
481
544
|
lastOrderAt: string | null;
|
|
482
545
|
createdAt: string;
|
|
@@ -484,6 +547,17 @@ export interface Customer {
|
|
|
484
547
|
}
|
|
485
548
|
export interface CustomerDetails extends Customer {
|
|
486
549
|
recentOrders: Array<Order>;
|
|
550
|
+
recentSubscriptionPayments: Array<SubscriptionPayment>;
|
|
551
|
+
}
|
|
552
|
+
export interface SubscriptionPayment {
|
|
553
|
+
id: string;
|
|
554
|
+
orderNumber: string | null;
|
|
555
|
+
status: 'COMPLETED' | 'REFUNDED';
|
|
556
|
+
amount: number;
|
|
557
|
+
currency: Currency;
|
|
558
|
+
productName: string;
|
|
559
|
+
subscriptionId: string;
|
|
560
|
+
createdAt: string;
|
|
487
561
|
}
|
|
488
562
|
export interface ListCustomersParams {
|
|
489
563
|
search?: string;
|
|
@@ -613,7 +687,7 @@ export interface CreateSubscriptionCheckoutParams {
|
|
|
613
687
|
customerEmail?: string;
|
|
614
688
|
externalRef?: string;
|
|
615
689
|
metadata?: Metadata;
|
|
616
|
-
currency?: 'EUR' | 'USD' | 'PLN';
|
|
690
|
+
currency?: 'EUR' | 'USD' | 'PLN' | 'BRL';
|
|
617
691
|
returnUrl?: string;
|
|
618
692
|
}
|
|
619
693
|
export interface SubscriptionCheckout {
|
|
@@ -690,7 +764,7 @@ export interface Invoice {
|
|
|
690
764
|
}
|
|
691
765
|
export interface CreateUsageChargeParams {
|
|
692
766
|
amount: number;
|
|
693
|
-
currency:
|
|
767
|
+
currency: Currency;
|
|
694
768
|
description: string;
|
|
695
769
|
idempotencyKey: string;
|
|
696
770
|
periodStart: string | Date;
|
|
@@ -822,6 +896,7 @@ export interface OrderPaidData {
|
|
|
822
896
|
customFields: Record<string, string>;
|
|
823
897
|
deliveryType?: string;
|
|
824
898
|
deliveryCommand?: string;
|
|
899
|
+
player?: Player;
|
|
825
900
|
}
|
|
826
901
|
export interface OrderRefundedData {
|
|
827
902
|
orderId: string;
|
|
@@ -837,6 +912,8 @@ export interface OrderRefundedData {
|
|
|
837
912
|
fullRefund: boolean;
|
|
838
913
|
licenses: Array<WebhookLicense>;
|
|
839
914
|
revocations: Array<Revocation>;
|
|
915
|
+
upgradedTo?: string;
|
|
916
|
+
player?: Player;
|
|
840
917
|
}
|
|
841
918
|
export interface Revocation {
|
|
842
919
|
productId: string;
|
|
@@ -889,6 +966,9 @@ export interface SubscriptionEventData {
|
|
|
889
966
|
licenseKey: string | null;
|
|
890
967
|
licenseStatus: string | null;
|
|
891
968
|
licenseExpiresAt: string | null;
|
|
969
|
+
deliveryType?: string;
|
|
970
|
+
deliveryCommand?: string;
|
|
971
|
+
player?: Player;
|
|
892
972
|
}
|
|
893
973
|
export interface ProductEventData {
|
|
894
974
|
productId: string;
|
|
@@ -951,7 +1031,10 @@ export interface FeedbackReceivedData {
|
|
|
951
1031
|
customerName: string | null;
|
|
952
1032
|
createdAt: string;
|
|
953
1033
|
}
|
|
954
|
-
export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.canceled', OrderEventData> | Envelope<'order.replaced', OrderReplacedData> | Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated' | 'subscription.trial_started' | 'subscription.trial_ended'
|
|
1034
|
+
export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.canceled', OrderEventData> | Envelope<'order.replaced', OrderReplacedData> | Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated' | 'subscription.trial_started' | 'subscription.trial_ended', SubscriptionEventData> | Envelope<'subscription.upcoming', SubscriptionEventData & {
|
|
1035
|
+
amountDue: number;
|
|
1036
|
+
nextPaymentAttempt: string | null;
|
|
1037
|
+
}> | Envelope<'subscription.renewed', SubscriptionEventData & {
|
|
955
1038
|
invoiceId: string;
|
|
956
1039
|
amountPaid: number;
|
|
957
1040
|
periodExtendedTo: string;
|
|
@@ -961,7 +1044,7 @@ export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.can
|
|
|
961
1044
|
nextPaymentAttempt: string | null;
|
|
962
1045
|
}> | Envelope<'subscription.canceled', SubscriptionEventData & {
|
|
963
1046
|
endedAt: string | null;
|
|
964
|
-
cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe';
|
|
1047
|
+
cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe' | 'expired';
|
|
965
1048
|
revokeCommand?: string;
|
|
966
1049
|
}> | Envelope<'subscription.refunded', SubscriptionEventData & {
|
|
967
1050
|
invoiceId: string;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams } from './types.js';
|
|
1
|
+
import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, CreateWebhookParams, CreatedWebhookEndpoint, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Me, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams, WebhookEndpoint } from './types.js';
|
|
2
2
|
export type * from './types.js';
|
|
3
|
-
export declare const VERSION = "1.
|
|
3
|
+
export declare const VERSION = "1.8.0";
|
|
4
4
|
export interface SkalpOptions {
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
webhookSecret?: string;
|
|
@@ -31,8 +31,9 @@ export declare class SkalpSignatureError extends Error {
|
|
|
31
31
|
export declare class Skalp {
|
|
32
32
|
#private;
|
|
33
33
|
constructor(options?: string | SkalpOptions);
|
|
34
|
+
readonly me: () => Promise<Me>;
|
|
34
35
|
readonly checkout: {
|
|
35
|
-
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
36
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }: CreateCheckoutParams) => Promise<CheckoutSession>;
|
|
36
37
|
get: (id: string) => Promise<CheckoutSessionStatus>;
|
|
37
38
|
};
|
|
38
39
|
readonly orders: {
|
|
@@ -129,6 +130,12 @@ export declare class Skalp {
|
|
|
129
130
|
}>;
|
|
130
131
|
};
|
|
131
132
|
readonly webhooks: {
|
|
133
|
+
list: () => Promise<WebhookEndpoint[]>;
|
|
134
|
+
create: ({ url, events, productIds }: CreateWebhookParams) => Promise<CreatedWebhookEndpoint>;
|
|
135
|
+
delete: (id: string) => Promise<{
|
|
136
|
+
id: string;
|
|
137
|
+
deleted: true;
|
|
138
|
+
}>;
|
|
132
139
|
verify: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<boolean>;
|
|
133
140
|
constructEvent: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<SkalpEvent>;
|
|
134
141
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const VERSION = '1.
|
|
1
|
+
export const VERSION = '1.8.0';
|
|
2
2
|
const SIGNATURE_HEADER = 'skalp-signature';
|
|
3
3
|
const SIGNATURE_TOLERANCE_SECONDS = 300;
|
|
4
4
|
const PRODUCT_PAGE = 100;
|
|
@@ -54,6 +54,7 @@ const PRODUCT_FIELDS = [
|
|
|
54
54
|
'fulfillmentType',
|
|
55
55
|
'billingInterval',
|
|
56
56
|
'trialPeriodDays',
|
|
57
|
+
'trialPrice',
|
|
57
58
|
'dynamicUrl',
|
|
58
59
|
'licenseDeviceLimit',
|
|
59
60
|
'licenseDurationDays',
|
|
@@ -75,6 +76,9 @@ const PRODUCT_FIELDS = [
|
|
|
75
76
|
'volumeDiscounts',
|
|
76
77
|
'upsells',
|
|
77
78
|
'prices',
|
|
79
|
+
'poolsEnabled',
|
|
80
|
+
'upgradeFrom',
|
|
81
|
+
'includes',
|
|
78
82
|
];
|
|
79
83
|
const COUPON_FIELDS = [
|
|
80
84
|
'discountType',
|
|
@@ -86,6 +90,8 @@ const COUPON_FIELDS = [
|
|
|
86
90
|
'maxUses',
|
|
87
91
|
'minPurchaseAmount',
|
|
88
92
|
'oneTimePerUser',
|
|
93
|
+
'subscriptionDuration',
|
|
94
|
+
'subscriptionMonths',
|
|
89
95
|
];
|
|
90
96
|
const GROUP_FIELDS = ['title', 'productIds', 'description', 'image', 'sortPriority', 'unlisted'];
|
|
91
97
|
function pick(source, keys) {
|
|
@@ -116,9 +122,10 @@ export class Skalp {
|
|
|
116
122
|
throw new Error('Skalp: your API key is a secret and must never reach the browser. Call the SDK from server code, or pass dangerouslyAllowBrowser: true if you really know what you are doing.');
|
|
117
123
|
}
|
|
118
124
|
}
|
|
125
|
+
me = () => this.#request('GET', '/v1/me');
|
|
119
126
|
checkout = {
|
|
120
|
-
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
121
|
-
body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields },
|
|
127
|
+
create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }) => this.#request('POST', '/v1/checkout/sessions', {
|
|
128
|
+
body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields, player },
|
|
122
129
|
}),
|
|
123
130
|
get: (id) => this.#request('GET', `/v1/checkout/sessions/${segment(id)}`),
|
|
124
131
|
};
|
|
@@ -296,6 +303,9 @@ export class Skalp {
|
|
|
296
303
|
}),
|
|
297
304
|
};
|
|
298
305
|
webhooks = {
|
|
306
|
+
list: () => this.#request('GET', '/v1/webhooks'),
|
|
307
|
+
create: ({ url, events, productIds }) => this.#request('POST', '/v1/webhooks', { body: { url, events, productIds } }),
|
|
308
|
+
delete: (id) => this.#request('DELETE', `/v1/webhooks/${segment(id)}`),
|
|
299
309
|
verify: async (payload, signature, secret) => (await this.#checkSignature(payload, signature, secret)) === undefined,
|
|
300
310
|
constructEvent: async (payload, signature, secret) => {
|
|
301
311
|
const failure = await this.#checkSignature(payload, signature, secret);
|
|
@@ -408,10 +418,10 @@ function parseSignature(header) {
|
|
|
408
418
|
function toBytes(payload, encoder) {
|
|
409
419
|
if (typeof payload === 'string')
|
|
410
420
|
return encoder.encode(payload);
|
|
411
|
-
if (payload
|
|
421
|
+
if (ArrayBuffer.isView(payload))
|
|
422
|
+
return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
|
|
423
|
+
if (Object.prototype.toString.call(payload) === '[object ArrayBuffer]')
|
|
412
424
|
return new Uint8Array(payload);
|
|
413
|
-
if (payload instanceof Uint8Array)
|
|
414
|
-
return payload;
|
|
415
425
|
throw new TypeError('Skalp: webhook payload must be the raw request body (string, Buffer or ArrayBuffer). A parsed JSON object cannot be verified, because re-serializing it changes the bytes that were signed.');
|
|
416
426
|
}
|
|
417
427
|
function retryAfterSeconds(res, attempt) {
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -3,12 +3,21 @@ export type FulfillmentType = 'FILE' | 'SERIAL' | 'GAME' | 'SERVICE' | 'DYNAMIC'
|
|
|
3
3
|
export type ProductStatus = 'DRAFT' | 'PENDING_REVIEW' | 'PROCESSING' | 'PROCESSING_FAILED' | 'ACTIVE' | 'REJECTED' | 'ARCHIVED';
|
|
4
4
|
export type ProductType = 'ONE_TIME' | 'RECURRING' | 'COINS';
|
|
5
5
|
export type Game = 'fivem' | 'minecraft' | 'rust';
|
|
6
|
-
export type BillingInterval = 'WEEK' | 'MONTH' | 'YEAR';
|
|
6
|
+
export type BillingInterval = 'WEEK' | 'MONTH' | 'QUARTER' | 'HALF_YEAR' | 'YEAR';
|
|
7
7
|
export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | 'CANCELED';
|
|
8
|
-
export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL';
|
|
8
|
+
export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL' | 'PAYSSION';
|
|
9
9
|
export type DeliveryStatus = 'PENDING' | 'PROCESSING' | 'DELIVERED' | 'FAILED';
|
|
10
10
|
export type SubscriptionStatus = 'ACTIVE' | 'CANCELED' | 'PAST_DUE' | 'UNPAID' | 'INCOMPLETE' | 'INCOMPLETE_EXPIRED' | 'TRIALING' | 'PAUSED';
|
|
11
11
|
export type Metadata = Record<string, string>;
|
|
12
|
+
export type PlayerIdKey = 'fivem' | 'license2' | 'steam' | 'discord' | 'xbl' | 'live' | 'fivemId' | 'mc_uuid' | 'mc_name' | 'steamid64';
|
|
13
|
+
export interface PlayerInput {
|
|
14
|
+
name?: string;
|
|
15
|
+
ids?: Partial<Record<PlayerIdKey, string>>;
|
|
16
|
+
}
|
|
17
|
+
export interface Player {
|
|
18
|
+
name: string | null;
|
|
19
|
+
ids: Partial<Record<PlayerIdKey, string>>;
|
|
20
|
+
}
|
|
12
21
|
export interface CreateCheckoutParams {
|
|
13
22
|
productId: string;
|
|
14
23
|
/** Units to sell, within the product's minQuantity and maxQuantity. Defaults to minQuantity. */
|
|
@@ -19,6 +28,7 @@ export interface CreateCheckoutParams {
|
|
|
19
28
|
returnUrl?: string;
|
|
20
29
|
/** Answers you already have, by field key; the buyer adds the rest on the pay page. */
|
|
21
30
|
customFields?: Record<string, string>;
|
|
31
|
+
player?: PlayerInput;
|
|
22
32
|
}
|
|
23
33
|
export interface CheckoutSession {
|
|
24
34
|
id: string;
|
|
@@ -28,7 +38,7 @@ export interface CheckoutSession {
|
|
|
28
38
|
}
|
|
29
39
|
export interface CheckoutSessionStatus {
|
|
30
40
|
id: string;
|
|
31
|
-
status: 'pending' | 'completed' | 'failed';
|
|
41
|
+
status: 'pending' | 'completed' | 'failed' | 'canceled';
|
|
32
42
|
orderNumber: string;
|
|
33
43
|
amount: number;
|
|
34
44
|
currency: Currency;
|
|
@@ -45,23 +55,24 @@ export interface Order {
|
|
|
45
55
|
vatRate: number | null;
|
|
46
56
|
currency: Currency;
|
|
47
57
|
discountAmount: number;
|
|
58
|
+
serviceFee: number | null;
|
|
48
59
|
couponCode: string | null;
|
|
49
60
|
productId: string;
|
|
50
61
|
productName: string;
|
|
51
62
|
productSlug: string;
|
|
52
63
|
/** Units of productId. */
|
|
53
64
|
quantity: number;
|
|
54
|
-
fulfillmentType: FulfillmentType;
|
|
65
|
+
fulfillmentType: FulfillmentType | null;
|
|
55
66
|
bundleId: string | null;
|
|
56
67
|
buyerEmail: string;
|
|
57
68
|
buyerCountry: string | null;
|
|
58
69
|
paymentProvider: PaymentProvider | null;
|
|
59
70
|
isGift: boolean;
|
|
60
|
-
granted
|
|
71
|
+
granted: boolean;
|
|
61
72
|
deliveryStatus: DeliveryStatus | null;
|
|
62
73
|
serialsCount?: number;
|
|
63
74
|
serialsReplaced?: number;
|
|
64
|
-
/** Delivered and replaced keys by id, never their values.
|
|
75
|
+
/** Delivered and replaced keys by id, never their values. Filled in by orders.get, orders.cancel and orders.redeliver. */
|
|
65
76
|
serials?: Array<OrderSerial>;
|
|
66
77
|
createdAt: string;
|
|
67
78
|
updatedAt: string;
|
|
@@ -199,6 +210,7 @@ export interface Product {
|
|
|
199
210
|
productType: ProductType;
|
|
200
211
|
billingInterval: BillingInterval | null;
|
|
201
212
|
trialPeriodDays: number;
|
|
213
|
+
trialPrice: number | null;
|
|
202
214
|
fulfillmentType: FulfillmentType | null;
|
|
203
215
|
game: Game | null;
|
|
204
216
|
category: string;
|
|
@@ -239,6 +251,9 @@ export interface Product {
|
|
|
239
251
|
volumeDiscounts: Array<VolumeDiscount>;
|
|
240
252
|
/** Products offered on this product's checkout page. */
|
|
241
253
|
upsells: Array<ProductUpsell>;
|
|
254
|
+
poolsEnabled: boolean | null;
|
|
255
|
+
upgradeFrom: Array<string>;
|
|
256
|
+
includes: Array<string>;
|
|
242
257
|
stock: number | null;
|
|
243
258
|
sale: ProductSale | null;
|
|
244
259
|
salesCount: number;
|
|
@@ -281,6 +296,7 @@ interface ProductFields {
|
|
|
281
296
|
fulfillmentType?: FulfillmentType;
|
|
282
297
|
billingInterval?: BillingInterval;
|
|
283
298
|
trialPeriodDays?: number;
|
|
299
|
+
trialPrice?: number | null;
|
|
284
300
|
dynamicUrl?: string | null;
|
|
285
301
|
licenseDeviceLimit?: number;
|
|
286
302
|
licenseDurationDays?: number | null;
|
|
@@ -311,6 +327,9 @@ interface ProductFields {
|
|
|
311
327
|
upsells?: Array<ProductUpsellInput> | null;
|
|
312
328
|
/** Up to 3 currencies other than the store currency, not for coin packs; the list replaces the old one, [] or null removes them all. */
|
|
313
329
|
prices?: Array<ProductPrice> | null;
|
|
330
|
+
poolsEnabled?: boolean;
|
|
331
|
+
upgradeFrom?: Array<string>;
|
|
332
|
+
includes?: Array<string>;
|
|
314
333
|
}
|
|
315
334
|
export interface CreateProductParams extends ProductFields {
|
|
316
335
|
name: string;
|
|
@@ -368,6 +387,39 @@ export interface Deleted {
|
|
|
368
387
|
id: string;
|
|
369
388
|
deleted: true;
|
|
370
389
|
}
|
|
390
|
+
export interface Me {
|
|
391
|
+
store: {
|
|
392
|
+
id: string;
|
|
393
|
+
name: string;
|
|
394
|
+
slug: string;
|
|
395
|
+
currency: Currency;
|
|
396
|
+
url: string;
|
|
397
|
+
};
|
|
398
|
+
key: {
|
|
399
|
+
name: string;
|
|
400
|
+
scopes: Array<string>;
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
export type WebhookEventName = SkalpEventType | '*';
|
|
404
|
+
export interface WebhookEndpoint {
|
|
405
|
+
id: string;
|
|
406
|
+
url: string;
|
|
407
|
+
events: Array<WebhookEventName>;
|
|
408
|
+
format: 'skalp' | (string & {});
|
|
409
|
+
isActive: boolean;
|
|
410
|
+
createdAt: string;
|
|
411
|
+
}
|
|
412
|
+
export interface CreateWebhookParams {
|
|
413
|
+
url: string;
|
|
414
|
+
events: Array<WebhookEventName>;
|
|
415
|
+
productIds?: Array<string>;
|
|
416
|
+
}
|
|
417
|
+
export interface CreatedWebhookEndpoint {
|
|
418
|
+
id: string;
|
|
419
|
+
url: string;
|
|
420
|
+
events: Array<WebhookEventName>;
|
|
421
|
+
secret: string;
|
|
422
|
+
}
|
|
371
423
|
export interface StoreCategory {
|
|
372
424
|
id: string;
|
|
373
425
|
name: string;
|
|
@@ -421,6 +473,7 @@ export interface UpdateProductGroupParams {
|
|
|
421
473
|
unlisted?: boolean;
|
|
422
474
|
}
|
|
423
475
|
export type CouponDiscountType = 'PERCENT' | 'FIXED';
|
|
476
|
+
export type CouponDuration = 'ONCE' | 'REPEATING' | 'FOREVER';
|
|
424
477
|
export interface Coupon {
|
|
425
478
|
id: string;
|
|
426
479
|
code: string;
|
|
@@ -430,6 +483,8 @@ export interface Coupon {
|
|
|
430
483
|
discountAmount: number | null;
|
|
431
484
|
productIds: Array<string>;
|
|
432
485
|
disabledWithVolumeDiscounts: boolean;
|
|
486
|
+
subscriptionDuration: CouponDuration;
|
|
487
|
+
subscriptionMonths: number | null;
|
|
433
488
|
validFrom: string;
|
|
434
489
|
validTo: string | null;
|
|
435
490
|
maxUses: number | null;
|
|
@@ -453,6 +508,8 @@ export interface CreateCouponParams {
|
|
|
453
508
|
maxUses?: number;
|
|
454
509
|
minPurchaseAmount?: number;
|
|
455
510
|
oneTimePerUser?: boolean;
|
|
511
|
+
subscriptionDuration?: CouponDuration;
|
|
512
|
+
subscriptionMonths?: number;
|
|
456
513
|
}
|
|
457
514
|
export interface UpdateCouponParams {
|
|
458
515
|
discountType?: CouponDiscountType;
|
|
@@ -467,6 +524,8 @@ export interface UpdateCouponParams {
|
|
|
467
524
|
minPurchaseAmount?: number | null;
|
|
468
525
|
oneTimePerUser?: boolean;
|
|
469
526
|
isActive?: boolean;
|
|
527
|
+
subscriptionDuration?: CouponDuration;
|
|
528
|
+
subscriptionMonths?: number | null;
|
|
470
529
|
}
|
|
471
530
|
export interface Customer {
|
|
472
531
|
id: string;
|
|
@@ -477,6 +536,10 @@ export interface Customer {
|
|
|
477
536
|
ordersCount: number;
|
|
478
537
|
totalSpent: number;
|
|
479
538
|
currency: Currency;
|
|
539
|
+
spent: Array<{
|
|
540
|
+
currency: Currency;
|
|
541
|
+
amount: number;
|
|
542
|
+
}>;
|
|
480
543
|
firstOrderAt: string | null;
|
|
481
544
|
lastOrderAt: string | null;
|
|
482
545
|
createdAt: string;
|
|
@@ -484,6 +547,17 @@ export interface Customer {
|
|
|
484
547
|
}
|
|
485
548
|
export interface CustomerDetails extends Customer {
|
|
486
549
|
recentOrders: Array<Order>;
|
|
550
|
+
recentSubscriptionPayments: Array<SubscriptionPayment>;
|
|
551
|
+
}
|
|
552
|
+
export interface SubscriptionPayment {
|
|
553
|
+
id: string;
|
|
554
|
+
orderNumber: string | null;
|
|
555
|
+
status: 'COMPLETED' | 'REFUNDED';
|
|
556
|
+
amount: number;
|
|
557
|
+
currency: Currency;
|
|
558
|
+
productName: string;
|
|
559
|
+
subscriptionId: string;
|
|
560
|
+
createdAt: string;
|
|
487
561
|
}
|
|
488
562
|
export interface ListCustomersParams {
|
|
489
563
|
search?: string;
|
|
@@ -613,7 +687,7 @@ export interface CreateSubscriptionCheckoutParams {
|
|
|
613
687
|
customerEmail?: string;
|
|
614
688
|
externalRef?: string;
|
|
615
689
|
metadata?: Metadata;
|
|
616
|
-
currency?: 'EUR' | 'USD' | 'PLN';
|
|
690
|
+
currency?: 'EUR' | 'USD' | 'PLN' | 'BRL';
|
|
617
691
|
returnUrl?: string;
|
|
618
692
|
}
|
|
619
693
|
export interface SubscriptionCheckout {
|
|
@@ -690,7 +764,7 @@ export interface Invoice {
|
|
|
690
764
|
}
|
|
691
765
|
export interface CreateUsageChargeParams {
|
|
692
766
|
amount: number;
|
|
693
|
-
currency:
|
|
767
|
+
currency: Currency;
|
|
694
768
|
description: string;
|
|
695
769
|
idempotencyKey: string;
|
|
696
770
|
periodStart: string | Date;
|
|
@@ -822,6 +896,7 @@ export interface OrderPaidData {
|
|
|
822
896
|
customFields: Record<string, string>;
|
|
823
897
|
deliveryType?: string;
|
|
824
898
|
deliveryCommand?: string;
|
|
899
|
+
player?: Player;
|
|
825
900
|
}
|
|
826
901
|
export interface OrderRefundedData {
|
|
827
902
|
orderId: string;
|
|
@@ -837,6 +912,8 @@ export interface OrderRefundedData {
|
|
|
837
912
|
fullRefund: boolean;
|
|
838
913
|
licenses: Array<WebhookLicense>;
|
|
839
914
|
revocations: Array<Revocation>;
|
|
915
|
+
upgradedTo?: string;
|
|
916
|
+
player?: Player;
|
|
840
917
|
}
|
|
841
918
|
export interface Revocation {
|
|
842
919
|
productId: string;
|
|
@@ -889,6 +966,9 @@ export interface SubscriptionEventData {
|
|
|
889
966
|
licenseKey: string | null;
|
|
890
967
|
licenseStatus: string | null;
|
|
891
968
|
licenseExpiresAt: string | null;
|
|
969
|
+
deliveryType?: string;
|
|
970
|
+
deliveryCommand?: string;
|
|
971
|
+
player?: Player;
|
|
892
972
|
}
|
|
893
973
|
export interface ProductEventData {
|
|
894
974
|
productId: string;
|
|
@@ -951,7 +1031,10 @@ export interface FeedbackReceivedData {
|
|
|
951
1031
|
customerName: string | null;
|
|
952
1032
|
createdAt: string;
|
|
953
1033
|
}
|
|
954
|
-
export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.canceled', OrderEventData> | Envelope<'order.replaced', OrderReplacedData> | Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated' | 'subscription.trial_started' | 'subscription.trial_ended'
|
|
1034
|
+
export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.canceled', OrderEventData> | Envelope<'order.replaced', OrderReplacedData> | Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated' | 'subscription.trial_started' | 'subscription.trial_ended', SubscriptionEventData> | Envelope<'subscription.upcoming', SubscriptionEventData & {
|
|
1035
|
+
amountDue: number;
|
|
1036
|
+
nextPaymentAttempt: string | null;
|
|
1037
|
+
}> | Envelope<'subscription.renewed', SubscriptionEventData & {
|
|
955
1038
|
invoiceId: string;
|
|
956
1039
|
amountPaid: number;
|
|
957
1040
|
periodExtendedTo: string;
|
|
@@ -961,7 +1044,7 @@ export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.can
|
|
|
961
1044
|
nextPaymentAttempt: string | null;
|
|
962
1045
|
}> | Envelope<'subscription.canceled', SubscriptionEventData & {
|
|
963
1046
|
endedAt: string | null;
|
|
964
|
-
cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe';
|
|
1047
|
+
cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe' | 'expired';
|
|
965
1048
|
revokeCommand?: string;
|
|
966
1049
|
}> | Envelope<'subscription.refunded', SubscriptionEventData & {
|
|
967
1050
|
invoiceId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skalpgg/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Official Skalp SDK for Node.js and edge runtimes: checkout, subscriptions, catalog and key stock, webhooks and license verification.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://skalp.gg/docs/sdk",
|