@delopay/sdk 0.35.0 → 0.36.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
@@ -273,6 +273,36 @@ const all = await delopay.subscriptions.list({ limit: 20 }, opts);
273
273
  Each billing cycle raises an invoice (`sub.invoice`) with its own payment leg
274
274
  (`sub.payment`); track cycle outcomes via the subscription/invoice webhooks.
275
275
 
276
+ ### Platform fee rules
277
+
278
+ Price the platform fee by payment method, connector, amount, currency or card
279
+ network. Build the rule program with `feeProgram()` — rules are tried in order,
280
+ first match wins, otherwise the default applies:
281
+
282
+ ```typescript
283
+ import { Delopay, feeProgram } from '@delopay/sdk';
284
+
285
+ const delopay = new Delopay(process.env.DELOPAY_API_KEY ?? '');
286
+
287
+ const algorithm = feeProgram()
288
+ .rule({ name: 'crypto', when: { paymentMethod: 'crypto' }, fee: { percentage: 1.0 } })
289
+ .rule({
290
+ name: 'card_on_cryptomus',
291
+ when: { paymentMethod: 'card', connector: 'cryptomus' },
292
+ fee: { percentage: 2.0 },
293
+ })
294
+ .otherwise({ percentage: 3.0 })
295
+ .build();
296
+
297
+ await delopay.fees.rules.upsert({ algorithm }, 'merchant_abc123');
298
+
299
+ const program = await delopay.fees.rules.retrieve('merchant_abc123'); // or null
300
+ await delopay.fees.rules.delete('merchant_abc123'); // revert to flat schedules
301
+ ```
302
+
303
+ Merchants without a rule program keep their existing flat fee schedules / volume
304
+ tier unchanged.
305
+
276
306
  ### Webhook verification
277
307
 
278
308
  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.
@@ -625,6 +625,7 @@ var Events = class {
625
625
  var Fees = class {
626
626
  constructor(request) {
627
627
  this.request = request;
628
+ this.rules = new FeeRulesManager(request);
628
629
  }
629
630
  /**
630
631
  * Create a merchant-scoped fee schedule (optionally per-shop).
@@ -666,6 +667,46 @@ var Fees = class {
666
667
  return this.request("DELETE", `/merchant-fees/${encodeURIComponent(feeId)}`);
667
668
  }
668
669
  };
670
+ var FeeRulesManager = class {
671
+ constructor(request) {
672
+ this.request = request;
673
+ }
674
+ /**
675
+ * Create or replace the merchant's fee-rule program (a new active version;
676
+ * the previous version is deactivated server-side).
677
+ *
678
+ * @param params - The program plus optional name / shop scope / validity window.
679
+ * @param merchantId - The merchant account ID.
680
+ */
681
+ async upsert(params, merchantId) {
682
+ const body = { ...params, fee_owner: "merchant" };
683
+ return this.request("PUT", "/merchant-fees/rules", {
684
+ body,
685
+ query: { merchant_id: merchantId }
686
+ });
687
+ }
688
+ /**
689
+ * Retrieve the merchant's active fee-rule program, or `null` if none.
690
+ *
691
+ * @param merchantId - The merchant account ID.
692
+ */
693
+ async retrieve(merchantId) {
694
+ return this.request("GET", "/merchant-fees/rules", {
695
+ query: { merchant_id: merchantId }
696
+ });
697
+ }
698
+ /**
699
+ * Deactivate the merchant's active fee-rule program (falls back to the flat
700
+ * fee schedules / volume tier). Idempotent.
701
+ *
702
+ * @param merchantId - The merchant account ID.
703
+ */
704
+ async delete(merchantId) {
705
+ await this.request("DELETE", "/merchant-fees/rules", {
706
+ query: { merchant_id: merchantId }
707
+ });
708
+ }
709
+ };
669
710
 
670
711
  // src/resources/mandates.ts
671
712
  var Mandates = class {
@@ -3017,6 +3058,74 @@ var Delopay = class {
3017
3058
  /** Utility for verifying incoming webhook signatures (static, no instance needed). */
3018
3059
  Delopay.webhooks = Webhooks;
3019
3060
 
3061
+ // src/feeProgram.ts
3062
+ function toFeeOutput(spec) {
3063
+ const hasPct = spec.percentage != null;
3064
+ const hasFlat = spec.flat != null;
3065
+ const feeType = hasPct && hasFlat ? "combined" : hasFlat ? "flat" : "percentage";
3066
+ return {
3067
+ fee_type: feeType,
3068
+ percentage_fee: spec.percentage ?? null,
3069
+ flat_fee_amount: spec.flat ?? null,
3070
+ flat_fee_currency: spec.flatCurrency ?? null,
3071
+ min_fee_amount: spec.min ?? null,
3072
+ max_fee_amount: spec.max ?? null
3073
+ };
3074
+ }
3075
+ function enumCondition(lhs, value) {
3076
+ return { lhs, comparison: "equal", value: { type: "enum_variant", value }, metadata: {} };
3077
+ }
3078
+ function numberCondition(lhs, comparison, value) {
3079
+ return { lhs, comparison, value: { type: "number", value }, metadata: {} };
3080
+ }
3081
+ function buildConditions(when = {}, raw = []) {
3082
+ const out = [];
3083
+ if (when.paymentMethod != null) out.push(enumCondition("payment_method", when.paymentMethod));
3084
+ if (when.connector != null) out.push(enumCondition("connector", when.connector));
3085
+ if (when.currency != null) out.push(enumCondition("currency", when.currency));
3086
+ if (when.cardNetwork != null) out.push(enumCondition("card_network", when.cardNetwork));
3087
+ if (when.amountEquals != null) out.push(numberCondition("amount", "equal", when.amountEquals));
3088
+ if (when.amountGreaterThan != null) {
3089
+ out.push(numberCondition("amount", "greater_than", when.amountGreaterThan));
3090
+ }
3091
+ if (when.amountLessThan != null) {
3092
+ out.push(numberCondition("amount", "less_than", when.amountLessThan));
3093
+ }
3094
+ out.push(...raw);
3095
+ return out;
3096
+ }
3097
+ var FeeProgramBuilder = class {
3098
+ constructor() {
3099
+ this.rules = [];
3100
+ this.defaultFee = null;
3101
+ }
3102
+ /** Append a rule. Provided `when`/`rawConditions` are ANDed. */
3103
+ rule(input) {
3104
+ this.rules.push({
3105
+ name: input.name,
3106
+ connectorSelection: { fee: toFeeOutput(input.fee) },
3107
+ statements: [{ condition: buildConditions(input.when, input.rawConditions) }]
3108
+ });
3109
+ return this;
3110
+ }
3111
+ /** Set the default selection (applied when no rule matches). */
3112
+ otherwise(fee) {
3113
+ this.defaultFee = toFeeOutput(fee);
3114
+ return this;
3115
+ }
3116
+ /** Produce the wire-ready program. */
3117
+ build() {
3118
+ return {
3119
+ defaultSelection: { fee: this.defaultFee },
3120
+ rules: this.rules,
3121
+ metadata: {}
3122
+ };
3123
+ }
3124
+ };
3125
+ function feeProgram() {
3126
+ return new FeeProgramBuilder();
3127
+ }
3128
+
3020
3129
  // src/branding.ts
3021
3130
  var FONT_STACKS = {
3022
3131
  inter: "'Inter Variable', 'Inter', system-ui, -apple-system, sans-serif",
@@ -3663,6 +3772,8 @@ export {
3663
3772
  Regions,
3664
3773
  Subscriptions,
3665
3774
  Delopay,
3775
+ FeeProgramBuilder,
3776
+ feeProgram,
3666
3777
  fontStack,
3667
3778
  radiusValue,
3668
3779
  fontWeightValue,
@@ -3692,4 +3803,4 @@ export {
3692
3803
  applyBrandingVariables,
3693
3804
  shadowFor
3694
3805
  };
3695
- //# sourceMappingURL=chunk-45OPT3EW.js.map
3806
+ //# sourceMappingURL=chunk-ZS7ALFE7.js.map