@delopay/sdk 0.34.0 → 0.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -171,6 +171,108 @@ const gateway = await delopay.shops.gateways.connect(merchantId, shop.shop_id, {
171
171
  const gateways = await delopay.shops.gateways.list(merchantId, shop.shop_id);
172
172
  ```
173
173
 
174
+ ### Subscriptions
175
+
176
+ Recurring billing runs through a billing processor connected to the shop (Stripe
177
+ Billing or PayPal). Every subscription call is **profile-scoped** — pass the
178
+ shop's `X-Profile-Id` so the backend can resolve the billing processor (you get
179
+ `IR_04` otherwise):
180
+
181
+ ```typescript
182
+ const opts = { headers: { 'X-Profile-Id': profileId } };
183
+ ```
184
+
185
+ **Browse plans and estimate cost** before creating anything:
186
+
187
+ ```typescript
188
+ // List purchasable plans (or addons) with their prices
189
+ const plans = await delopay.subscriptions.getItems({ item_type: 'plan' }, opts);
190
+ const priceId = plans[0]?.price_id[0]?.price_id;
191
+
192
+ // Preview what the customer will be charged
193
+ const estimate = await delopay.subscriptions.getEstimate({ item_price_id: priceId }, opts);
194
+ console.log(estimate.amount, estimate.currency, estimate.interval); // 1500 'EUR' 'Month'
195
+ ```
196
+
197
+ > **Never send raw card numbers.** The subscription API rejects
198
+ > `payment_method_data.card` with a raw PAN. Cards are collected client-side by
199
+ > the connector's hosted fields (Stripe Elements) so the card never touches your
200
+ > server, keeping raw card data out of your PCI scope. Confirm with a hosted
201
+ > checkout session or a previously-saved token, as shown below.
202
+
203
+ **Recommended: hosted checkout.** Create the subscription server-side, then send
204
+ the buyer to the Delopay hosted checkout with the returned `client_secret`. The
205
+ buyer enters their card in the connector iframe; you never handle the PAN:
206
+
207
+ ```typescript
208
+ const pending = await delopay.subscriptions.create(
209
+ {
210
+ item_price_id: priceId,
211
+ customer_id: 'cus_abc123',
212
+ payment_details: { return_url: 'https://example.com/subscription/complete' },
213
+ },
214
+ opts,
215
+ );
216
+
217
+ // Redirect the buyer to the hosted checkout to enter their card.
218
+ const checkoutUrl =
219
+ `https://checkout.delopay.net/pay/${merchantId}/${pending.id}` +
220
+ `?cs=${encodeURIComponent(pending.client_secret ?? '')}`;
221
+ // → res.redirect(checkoutUrl)
222
+
223
+ // Activation arrives via the subscription/invoice webhooks; never trust the
224
+ // client. Reconcile with subscriptions.retrieve(pending.id, opts).
225
+ ```
226
+
227
+ **Saved payment method (off-session).** If the customer already has a saved,
228
+ tokenized payment method, confirm server-side with the token — still no PAN:
229
+
230
+ ```typescript
231
+ const sub = await delopay.subscriptions.createAndConfirm(
232
+ {
233
+ item_price_id: priceId,
234
+ customer_id: 'cus_abc123',
235
+ payment_details: {
236
+ payment_method: 'card',
237
+ payment_method_id: savedPaymentMethodId, // token, not a card number
238
+ setup_future_usage: 'off_session',
239
+ return_url: 'https://example.com/subscription/complete',
240
+ },
241
+ },
242
+ opts,
243
+ );
244
+
245
+ if (sub.redirect_url) {
246
+ // Some processors (e.g. PayPal) still need buyer approval — redirect there.
247
+ } else {
248
+ console.log(sub.status); // 'active'
249
+ }
250
+ ```
251
+
252
+ You can also split create and confirm — call `subscriptions.confirm(id, …)` with
253
+ the `client_secret` and a `payment_token` once the buyer has a token. Same rule:
254
+ a `payment_token` / `payment_method_id`, never a raw card.
255
+
256
+ **Manage the lifecycle.** Pause, resume, and cancel take optional timing and
257
+ proration controls; called with no body they act immediately:
258
+
259
+ ```typescript
260
+ await delopay.subscriptions.pause(sub.id, { pause_option: 'end_of_term' }, opts);
261
+ await delopay.subscriptions.resume(sub.id, undefined, opts);
262
+ await delopay.subscriptions.cancel(
263
+ sub.id,
264
+ { cancel_option: 'immediately', credit_option_for_current_term_charges: 'prorate' },
265
+ opts,
266
+ );
267
+
268
+ // Retrieve one, or list for the profile
269
+ const current = await delopay.subscriptions.retrieve(sub.id, opts);
270
+ const all = await delopay.subscriptions.list({ limit: 20 }, opts);
271
+ ```
272
+
273
+ Each billing cycle raises an invoice (`sub.invoice`) with its own payment leg
274
+ (`sub.payment`); track cycle outcomes via the subscription/invoice webhooks.
275
+
174
276
  ### Webhook verification
175
277
 
176
278
  Delopay signs each outgoing webhook with HMAC-SHA512 over the raw request body and delivers the hex-encoded digest in the `X-Webhook-Signature-512` header. Use `express.raw()` (not `express.json()`) so the bytes reach the verifier unchanged.
package/dist/index.d.cts CHANGED
@@ -840,6 +840,19 @@ interface BillingProfileResponse {
840
840
  consecutive_recharge_failures: number;
841
841
  stripe_customer_id?: string | null;
842
842
  suspended_at?: string | null;
843
+ /**
844
+ * Whether the merchant is on the trusted list. Trusted merchants are
845
+ * exempt from automatic AND manual suspension until the flag is cleared.
846
+ */
847
+ is_trusted: boolean;
848
+ /**
849
+ * What caused the current suspension: `auto_recharge` or `admin`. Absent
850
+ * when the merchant is not suspended. An `admin` suspension is sticky — a
851
+ * top-up will not auto-reactivate it; only an admin unsuspend lifts it.
852
+ */
853
+ suspension_source?: string | null;
854
+ /** Admin-provided reason for a manual suspension. Absent otherwise. */
855
+ suspension_reason?: string | null;
843
856
  created_at: string;
844
857
  modified_at: string;
845
858
  /**
package/dist/index.d.ts CHANGED
@@ -840,6 +840,19 @@ interface BillingProfileResponse {
840
840
  consecutive_recharge_failures: number;
841
841
  stripe_customer_id?: string | null;
842
842
  suspended_at?: string | null;
843
+ /**
844
+ * Whether the merchant is on the trusted list. Trusted merchants are
845
+ * exempt from automatic AND manual suspension until the flag is cleared.
846
+ */
847
+ is_trusted: boolean;
848
+ /**
849
+ * What caused the current suspension: `auto_recharge` or `admin`. Absent
850
+ * when the merchant is not suspended. An `admin` suspension is sticky — a
851
+ * top-up will not auto-reactivate it; only an admin unsuspend lifts it.
852
+ */
853
+ suspension_source?: string | null;
854
+ /** Admin-provided reason for a manual suspension. Absent otherwise. */
855
+ suspension_reason?: string | null;
843
856
  created_at: string;
844
857
  modified_at: string;
845
858
  /**
package/dist/internal.cjs CHANGED
@@ -4010,6 +4010,48 @@ var PlatformBilling = class {
4010
4010
  body: params
4011
4011
  });
4012
4012
  }
4013
+ /**
4014
+ * Manually suspend a merchant (e.g. confirmed fraud or ToS violation),
4015
+ * independent of balance. A `reason` is required for audit. Throws 412 if
4016
+ * the merchant is trusted (clear the flag first) or already suspended.
4017
+ *
4018
+ * @param merchantId - The merchant account ID.
4019
+ * @param params - Suspension reason.
4020
+ * @returns The updated billing profile.
4021
+ */
4022
+ async suspend(merchantId, params) {
4023
+ return this.request("POST", `/billing/${encodeURIComponent(merchantId)}/admin/suspend`, {
4024
+ body: params
4025
+ });
4026
+ }
4027
+ /**
4028
+ * Lift a suspension. Restores the merchant to `active` (or `delinquent` if
4029
+ * the balance is at/below the hard floor) and resets the recharge-failure
4030
+ * counter. Throws 412 if the merchant is not suspended.
4031
+ *
4032
+ * @param merchantId - The merchant account ID.
4033
+ * @param params - Optional audit note.
4034
+ * @returns The updated billing profile.
4035
+ */
4036
+ async unsuspend(merchantId, params = {}) {
4037
+ return this.request("POST", `/billing/${encodeURIComponent(merchantId)}/admin/unsuspend`, {
4038
+ body: params
4039
+ });
4040
+ }
4041
+ /**
4042
+ * Set or clear the trusted (suspension-exempt) flag. Trusted merchants
4043
+ * cannot be suspended automatically or manually. Does not lift an existing
4044
+ * suspension — use {@link PlatformBilling.unsuspend} for that.
4045
+ *
4046
+ * @param merchantId - The merchant account ID.
4047
+ * @param params - The desired trusted state.
4048
+ * @returns The updated billing profile.
4049
+ */
4050
+ async setTrusted(merchantId, params) {
4051
+ return this.request("PATCH", `/billing/${encodeURIComponent(merchantId)}/admin/trusted`, {
4052
+ body: params
4053
+ });
4054
+ }
4013
4055
  };
4014
4056
 
4015
4057
  // src/internal/resources/platformFees.ts