@thepayulink/server 2.2.1 → 2.2.2

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.
@@ -37,7 +37,7 @@ __export(src_exports, {
37
37
  module.exports = __toCommonJS(src_exports);
38
38
  var import_node_crypto = __toESM(require("node:crypto"), 1);
39
39
  var rupees = (r) => Math.round(Number(r) * 100);
40
- var toRupees = (paise) => Number(paise) / 100;
40
+ var toRupees = (paise2) => Number(paise2) / 100;
41
41
  var PayuLinkError = class extends Error {
42
42
  constructor(message, { status, code, body } = {}) {
43
43
  super(message);
@@ -62,6 +62,15 @@ function safeEqual(a, b) {
62
62
  const bb = Buffer.from(String(b ?? ""));
63
63
  return ba.length === bb.length && ba.length > 0 && import_node_crypto.default.timingSafeEqual(ba, bb);
64
64
  }
65
+ function paise(value) {
66
+ const n = Number(value);
67
+ const whole = Math.round(n);
68
+ if (!Number.isFinite(n) || Math.abs(n - whole) > 1e-6) {
69
+ throw new PayuLinkError("`amount` must be a whole number of PAISE (19950 = \u20B9199.50). Tip: use the `rupees()` helper \u2014 rupees(199.5) === 19950.");
70
+ }
71
+ if (whole < 100) throw new PayuLinkError("`amount` must be at least 100 paise (\u20B91).");
72
+ return whole;
73
+ }
65
74
  var PayuLink = class {
66
75
  /**
67
76
  * @param {object} opts
@@ -161,10 +170,7 @@ var PayuLink = class {
161
170
  * backward compatibility but only affects legacy version-1 callbacks, not signed webhooks.)
162
171
  */
163
172
  _createOrder(p = {}) {
164
- const amount = Math.round(Number(p.amount));
165
- if (!Number.isFinite(amount) || amount < 100) {
166
- throw new PayuLinkError("`amount` is required, in PAISE, and must be >= 100 (\u20B91). Tip: use the `rupees()` helper \u2014 rupees(199.5) === 19950.");
167
- }
173
+ const amount = paise(p.amount);
168
174
  return this._request("POST", "/v1/orders", {
169
175
  body: {
170
176
  amount,
@@ -188,10 +194,7 @@ var PayuLink = class {
188
194
  * @param {string} [p.narration]
189
195
  */
190
196
  _createPayout(p = {}) {
191
- const amount = Math.round(Number(p.amount));
192
- if (!Number.isFinite(amount) || amount < 100) {
193
- throw new PayuLinkError("`amount` is required, in PAISE, and must be >= 100 (\u20B91).");
194
- }
197
+ const amount = paise(p.amount);
195
198
  if (p.mode !== "bank" && p.mode !== "upi") throw new PayuLinkError('`mode` must be "bank" or "upi".');
196
199
  if (!p.beneficiary) throw new PayuLinkError("`beneficiary` is required.");
197
200
  return this._request("POST", "/v1/payouts", {
@@ -289,4 +292,4 @@ var PayuLink = class {
289
292
  rupees,
290
293
  toRupees
291
294
  });
292
- (()=>{const ns=module.exports,C=ns.default;if(C){C.PayulinkError=ns.PayulinkError;C.Payulink=C;C.default=C;module.exports=C;}})();
295
+ (()=>{const ns=module.exports,C=ns.default;if(C){for(const k of Object.keys(ns))if(k!=="default")C[k]=ns[k];C.PayuLink=C;C.Payulink=C;C.PayulinkError=ns.PayuLinkError;C.default=C;module.exports=C;}})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thepayulink/server",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "PayuLink server SDK — create orders and verify payments/webhooks with your key_secret.",
5
5
  "type": "module",
6
6
  "main": "./dist/payulink-server.cjs",
package/src/index.js CHANGED
@@ -47,6 +47,22 @@ function safeEqual(a, b) {
47
47
  return ba.length === bb.length && ba.length > 0 && crypto.timingSafeEqual(ba, bb);
48
48
  }
49
49
 
50
+ /**
51
+ * A whole number of paise, >= 100. Floating-point noise (19.99 * 100 === 1998.9999999999998)
52
+ * is rounded away; a real fraction (199.5) is refused rather than silently rounded, since it
53
+ * usually means rupees were passed where paise were expected. The API refuses it too.
54
+ */
55
+ function paise(value) {
56
+ const n = Number(value);
57
+ const whole = Math.round(n);
58
+ if (!Number.isFinite(n) || Math.abs(n - whole) > 1e-6) {
59
+ throw new PayuLinkError('`amount` must be a whole number of PAISE (19950 = ₹199.50). '
60
+ + 'Tip: use the `rupees()` helper — rupees(199.5) === 19950.');
61
+ }
62
+ if (whole < 100) throw new PayuLinkError('`amount` must be at least 100 paise (₹1).');
63
+ return whole;
64
+ }
65
+
50
66
  export default class PayuLink {
51
67
  /**
52
68
  * @param {object} opts
@@ -147,11 +163,7 @@ export default class PayuLink {
147
163
  * backward compatibility but only affects legacy version-1 callbacks, not signed webhooks.)
148
164
  */
149
165
  _createOrder(p = {}) {
150
- const amount = Math.round(Number(p.amount));
151
- if (!Number.isFinite(amount) || amount < 100) {
152
- throw new PayuLinkError('`amount` is required, in PAISE, and must be >= 100 (₹1). '
153
- + 'Tip: use the `rupees()` helper — rupees(199.5) === 19950.');
154
- }
166
+ const amount = paise(p.amount);
155
167
  return this._request('POST', '/v1/orders', {
156
168
  body: {
157
169
  amount,
@@ -176,10 +188,7 @@ export default class PayuLink {
176
188
  * @param {string} [p.narration]
177
189
  */
178
190
  _createPayout(p = {}) {
179
- const amount = Math.round(Number(p.amount));
180
- if (!Number.isFinite(amount) || amount < 100) {
181
- throw new PayuLinkError('`amount` is required, in PAISE, and must be >= 100 (₹1).');
182
- }
191
+ const amount = paise(p.amount);
183
192
  if (p.mode !== 'bank' && p.mode !== 'upi') throw new PayuLinkError('`mode` must be "bank" or "upi".');
184
193
  if (!p.beneficiary) throw new PayuLinkError('`beneficiary` is required.');
185
194
  return this._request('POST', '/v1/payouts', {