@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 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
- | `checkout.create({ productId, quantity?, customerEmail?, metadata?, couponCode?, returnUrl?, customFields? })` | `checkout:write` |
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 `licenseDurationDays`.
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.updated`, `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. The three trial and upcoming events are accepted by the API but the backend does not send them yet.
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
 
@@ -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.6.0";
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.6.0';
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 instanceof ArrayBuffer)
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) {
@@ -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?: boolean;
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. Only orders.get and orders.cancel fill it in. */
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: 'EUR' | 'USD' | 'PLN';
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' | 'subscription.upcoming', SubscriptionEventData> | Envelope<'subscription.renewed', SubscriptionEventData & {
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;
@@ -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.6.0";
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.6.0';
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 instanceof ArrayBuffer)
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) {
@@ -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?: boolean;
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. Only orders.get and orders.cancel fill it in. */
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: 'EUR' | 'USD' | 'PLN';
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' | 'subscription.upcoming', SubscriptionEventData> | Envelope<'subscription.renewed', SubscriptionEventData & {
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.6.0",
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",