tupay 0.16.0 → 0.18.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.
Files changed (48) hide show
  1. package/README.md +33 -0
  2. package/dist/cjs/cli-arguments.d.ts +28 -0
  3. package/dist/cjs/cli-arguments.d.ts.map +1 -0
  4. package/dist/cjs/cli-arguments.js +101 -0
  5. package/dist/cjs/cli-arguments.js.map +1 -0
  6. package/dist/cjs/cli.d.ts +9 -0
  7. package/dist/cjs/cli.d.ts.map +1 -0
  8. package/dist/cjs/cli.js +56 -0
  9. package/dist/cjs/cli.js.map +1 -0
  10. package/dist/cjs/index.d.ts +9 -1
  11. package/dist/cjs/index.d.ts.map +1 -1
  12. package/dist/cjs/index.js +10 -1
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/relais.d.ts +88 -0
  15. package/dist/cjs/relais.d.ts.map +1 -0
  16. package/dist/cjs/relais.js +156 -0
  17. package/dist/cjs/relais.js.map +1 -0
  18. package/dist/cjs/resources/accounts.d.ts +2 -1
  19. package/dist/cjs/resources/accounts.d.ts.map +1 -1
  20. package/dist/cjs/resources/accounts.js.map +1 -1
  21. package/dist/cjs/webhooks.d.ts +20 -0
  22. package/dist/cjs/webhooks.d.ts.map +1 -1
  23. package/dist/cjs/webhooks.js +34 -9
  24. package/dist/cjs/webhooks.js.map +1 -1
  25. package/dist/esm/cli-arguments.d.ts +28 -0
  26. package/dist/esm/cli-arguments.d.ts.map +1 -0
  27. package/dist/esm/cli-arguments.js +96 -0
  28. package/dist/esm/cli-arguments.js.map +1 -0
  29. package/dist/esm/cli.d.ts +9 -0
  30. package/dist/esm/cli.d.ts.map +1 -0
  31. package/dist/esm/cli.js +54 -0
  32. package/dist/esm/cli.js.map +1 -0
  33. package/dist/esm/index.d.ts +9 -1
  34. package/dist/esm/index.d.ts.map +1 -1
  35. package/dist/esm/index.js +7 -2
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/relais.d.ts +88 -0
  38. package/dist/esm/relais.d.ts.map +1 -0
  39. package/dist/esm/relais.js +150 -0
  40. package/dist/esm/relais.js.map +1 -0
  41. package/dist/esm/resources/accounts.d.ts +2 -1
  42. package/dist/esm/resources/accounts.d.ts.map +1 -1
  43. package/dist/esm/resources/accounts.js.map +1 -1
  44. package/dist/esm/webhooks.d.ts +20 -0
  45. package/dist/esm/webhooks.d.ts.map +1 -1
  46. package/dist/esm/webhooks.js +33 -9
  47. package/dist/esm/webhooks.js.map +1 -1
  48. package/package.json +4 -1
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Relayer les événements de TEST vers votre poste — `tupay listen`.
3
+ *
4
+ * ── Le problème ────────────────────────────────────────────────────
5
+ * Tupay ne joint pas `localhost` : pour recevoir un webhook pendant que
6
+ * vous développez, il fallait un tunnel (Cloudflare Tunnel, ngrok) et
7
+ * déclarer son URL publique comme endpoint. C'est l'équivalent de
8
+ * `stripe listen` qui manquait.
9
+ *
10
+ * ── Comment, sans rien ouvrir ──────────────────────────────────────
11
+ * Le relais INTERROGE l'API (`GET /events`, avec votre clé de test) et
12
+ * POSTE chaque événement nouveau à votre serveur local. Aucun port à
13
+ * ouvrir, aucun compte de tunnel, aucun endpoint à déclarer : seule une
14
+ * connexion sortante vers Tupay, comme n'importe quel appel du SDK.
15
+ *
16
+ * La signature est faite avec un secret LOCAL (`whsec_…`, affiché au
17
+ * démarrage), et non celui d'un endpoint : le relais ne connaît pas vos
18
+ * secrets d'endpoint, et n'a pas à les connaître. Votre code de
19
+ * vérification est le même — seul le secret change.
20
+ *
21
+ * ── Ce qu'il ne fait pas ───────────────────────────────────────────
22
+ * Il ne relaie que ce qui naît APRÈS son démarrage (les anciens se
23
+ * rejouent depuis l'écran Événements), et n'enregistre aucune livraison
24
+ * chez Tupay : votre écran Webhooks ne le voit pas.
25
+ */
26
+ import { randomBytes } from 'node:crypto';
27
+ import { generateTestHeader } from './webhooks.js';
28
+ /** Le plafond de l'API par page. */
29
+ const PAGE = 100;
30
+ /** Au-delà, votre serveur est considéré comme muet pour cet envoi. */
31
+ const DELAI_ENVOI_MS = 10_000;
32
+ export function genererSecretLocal() {
33
+ return 'whsec_' + randomBytes(32).toString('hex');
34
+ }
35
+ export class Relais {
36
+ /** Le plus récent événement déjà vu. `undefined` : il n'y en avait aucun. */
37
+ #curseur;
38
+ #demarre = false;
39
+ #o;
40
+ constructor(options) {
41
+ this.#o = {
42
+ source: options.source,
43
+ forwardTo: options.forwardTo,
44
+ secret: options.secret,
45
+ apiVersion: options.apiVersion ?? '2026-01-01',
46
+ journal: options.journal ?? ((l) => console.log(l)),
47
+ fetch: options.fetch ?? globalThis.fetch,
48
+ types: options.types && options.types.length > 0 ? new Set(options.types) : null,
49
+ };
50
+ }
51
+ /**
52
+ * Retient le plus récent événement existant : seuls ceux qui naîtront
53
+ * ENSUITE seront relayés. Relayer l'historique au démarrage ferait
54
+ * recevoir à votre serveur des paiements d'hier comme s'ils arrivaient.
55
+ */
56
+ async demarrer() {
57
+ const page = await this.#o.source.list({ limit: 1 });
58
+ this.#curseur = page.data[0]?.id;
59
+ this.#demarre = true;
60
+ }
61
+ /**
62
+ * Un passage : lit ce qui est né depuis le dernier, le relaie du plus
63
+ * ANCIEN au plus récent — l'ordre où les faits sont arrivés. Rend le
64
+ * nombre d'événements relayés.
65
+ */
66
+ async tour() {
67
+ if (!this.#demarre)
68
+ await this.demarrer();
69
+ let relayes = 0;
70
+ for (;;) {
71
+ // `ending_before` rend la page ADJACENTE au curseur, du plus
72
+ // récent au plus ancien ; `has_more` dit qu'il en reste de plus
73
+ // récents. Sans curseur (aucun événement au démarrage), tout ce qui
74
+ // existe est nouveau.
75
+ const page = await this.#o.source.list(this.#curseur === undefined ? { limit: PAGE } : { limit: PAGE, endingBefore: this.#curseur });
76
+ const nouveaux = [...page.data].reverse();
77
+ for (const evenement of nouveaux) {
78
+ if (this.#o.types === null || this.#o.types.has(evenement.type)) {
79
+ await this.#transmettre(evenement);
80
+ relayes++;
81
+ }
82
+ }
83
+ if (page.data[0])
84
+ this.#curseur = page.data[0].id;
85
+ if (!page.has_more || page.data.length === 0 || this.#curseur === undefined)
86
+ return relayes;
87
+ }
88
+ }
89
+ async #transmettre(evenement) {
90
+ // L'enveloppe telle que Tupay la livre à un endpoint : même forme,
91
+ // donc le même code de réception.
92
+ const corps = JSON.stringify({
93
+ id: evenement.id,
94
+ object: 'event',
95
+ type: evenement.type,
96
+ apiVersion: this.#o.apiVersion,
97
+ created: evenement.created,
98
+ livemode: evenement.livemode,
99
+ data: evenement.data,
100
+ });
101
+ const heure = new Date().toLocaleTimeString('fr-FR');
102
+ try {
103
+ const reponse = await this.#o.fetch(this.#o.forwardTo, {
104
+ method: 'POST',
105
+ headers: {
106
+ 'content-type': 'application/json',
107
+ 'user-agent': 'Tupay-Listen/1.0',
108
+ 'tupay-signature': generateTestHeader({ payload: corps, secret: this.#o.secret }),
109
+ 'tupay-event-id': evenement.id,
110
+ 'tupay-event-type': evenement.type,
111
+ },
112
+ body: corps,
113
+ signal: AbortSignal.timeout(DELAI_ENVOI_MS),
114
+ });
115
+ this.#o.journal(`${heure} ${evenement.type} ${evenement.id} → ${reponse.status}`);
116
+ }
117
+ catch (err) {
118
+ // Votre serveur est arrêté ou a planté : on le dit, et on continue.
119
+ // Le relais ne rejoue pas — l'écran Événements le fait.
120
+ const raison = err instanceof Error ? err.message : String(err);
121
+ this.#o.journal(`${heure} ${evenement.type} ${evenement.id} → échec : ${raison}`);
122
+ }
123
+ }
124
+ }
125
+ /**
126
+ * Tourne jusqu'à `signal`. Une erreur de l'API (réseau coupé, clé
127
+ * révoquée) est dite et le passage suivant réessaie : un relais qui
128
+ * s'arrête au premier hoquet obligerait à surveiller le relais.
129
+ */
130
+ export async function ecouter(relais, options = {}) {
131
+ const intervalle = options.intervalleMs ?? 2000;
132
+ const journal = options.journal ?? ((l) => console.error(l));
133
+ await relais.demarrer();
134
+ while (!options.signal?.aborted) {
135
+ try {
136
+ await relais.tour();
137
+ }
138
+ catch (err) {
139
+ journal(`Lecture des événements impossible : ${err instanceof Error ? err.message : String(err)}`);
140
+ }
141
+ await new Promise((fin) => {
142
+ const minuteur = setTimeout(fin, intervalle);
143
+ options.signal?.addEventListener('abort', () => {
144
+ clearTimeout(minuteur);
145
+ fin();
146
+ }, { once: true });
147
+ });
148
+ }
149
+ }
150
+ //# sourceMappingURL=relais.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relais.js","sourceRoot":"","sources":["../../src/relais.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,8 @@ export interface CreateAccountParams {
19
19
  tgcRate?: TgcRate;
20
20
  /**
21
21
  * Coordonnées bancaires XPF du vendeur. Facultatives à la création —
22
- * tant qu'elles manquent, `payoutsEnabled` est faux.
22
+ * tant qu'elles manquent, `payoutsEnabled` est faux. IBAN français ;
23
+ * la clé de contrôle est vérifiée, un caractère mal recopié est refusé.
23
24
  */
24
25
  ibanXpf?: string;
25
26
  /** Omise, le SDK génère un UUID v4 — la requête devient rejouable. */
@@ -1 +1 @@
1
- {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../src/resources/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,UAAU,EACV,MAAM,EACN,OAAO,EACR,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;IAE1C,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ5C;;;;;;OAMG;IACH;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQ1D;;;;;;OAMG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAU7E,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;CAQ3C"}
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../src/resources/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,UAAU,EACV,MAAM,EACN,OAAO,EACR,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;IAE1C,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ5C;;;;;;OAMG;IACH;;;;;;;;;;;OAWG;IACG,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQ1D;;;;;;OAMG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAU7E,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;CAQ3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/resources/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EACL,eAAe,EACf,eAAe,GAGhB,MAAM,aAAa,CAAA;AAkCpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAEpD,KAAK,CAAC,MAAM,CAAC,MAA2B;QACtC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAA;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAoB;YAC5D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW;YACjB,IAAI;YACJ,cAAc,EAAE,cAAc,IAAI,WAAW,CAAC,cAAc,EAAE;SAC/D,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAoB;YAC5D,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE;SAC5C,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,eAAe,CAAC,EAAU;QAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAA2B;YACnE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,UAAU;SACpD,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,EAAU,EAAE,SAAqB,EAAE;QACnD,OAAO,eAAe,CACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAqB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,UAAU;YACnD,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC;SAC/B,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,eAAe,CACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAsB;YAC7C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,WAAW;SAClB,CAAC,CACH,CAAA;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/resources/accounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EACL,eAAe,EACf,eAAe,GAGhB,MAAM,aAAa,CAAA;AAmCpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAEpD,KAAK,CAAC,MAAM,CAAC,MAA2B;QACtC,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAA;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAoB;YAC5D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW;YACjB,IAAI;YACJ,cAAc,EAAE,cAAc,IAAI,WAAW,CAAC,cAAc,EAAE;SAC/D,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAoB;YAC5D,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE;SAC5C,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,eAAe,CAAC,EAAU;QAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAA2B;YACnE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,UAAU;SACpD,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,EAAU,EAAE,SAAqB,EAAE;QACnD,OAAO,eAAe,CACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAqB;YAC5C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,UAAU;YACnD,KAAK,EAAE,eAAe,CAAC,MAAM,CAAC;SAC/B,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,eAAe,CACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAsB;YAC7C,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,WAAW;SAClB,CAAC,CACH,CAAA;IACH,CAAC;CACF"}
@@ -28,4 +28,24 @@ export interface ConstructEventOptions {
28
28
  * est invalide — répondez alors 400 sans traiter l'événement.
29
29
  */
30
30
  export declare function constructEvent(payload: string | Buffer, header: string | null | undefined, secret: string, options?: ConstructEventOptions): WebhookEvent;
31
+ /**
32
+ * Fabrique un en-tête `Tupay-Signature` valide — pour vos TESTS.
33
+ *
34
+ * Votre gestionnaire de webhooks se teste sans réseau : signez un corps
35
+ * avec le secret de test, passez-le à votre route, vérifiez qu'elle
36
+ * l'accepte — et qu'elle refuse un corps modifié.
37
+ *
38
+ * C'est aussi ce que fait `tupay listen` pour relayer vers votre poste.
39
+ *
40
+ * @example
41
+ * const corps = JSON.stringify(evenement)
42
+ * const entete = generateTestHeader({ payload: corps, secret: 'whsec_test' })
43
+ * await request(app).post('/hook').set('tupay-signature', entete).send(corps)
44
+ */
45
+ export declare function generateTestHeader(params: {
46
+ payload: string;
47
+ secret: string;
48
+ /** Secondes Unix. Défaut : maintenant. */
49
+ timestamp?: number;
50
+ }): string;
31
51
  //# sourceMappingURL=webhooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,YAAY,CAiDd"}
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,YAAY,CAsDd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,MAAM,CAIT"}
@@ -15,7 +15,7 @@ import { TupaySignatureVerificationError } from './errors.js';
15
15
  export const DEFAULT_TOLERANCE_SECONDS = 300;
16
16
  function parseHeader(header) {
17
17
  let timestamp = null;
18
- let v1 = null;
18
+ const v1 = [];
19
19
  for (const part of header.split(',')) {
20
20
  const separator = part.indexOf('=');
21
21
  if (separator === -1)
@@ -28,10 +28,10 @@ function parseHeader(header) {
28
28
  timestamp = parsed;
29
29
  }
30
30
  else if (key === 'v1') {
31
- v1 = value;
31
+ v1.push(value);
32
32
  }
33
33
  }
34
- return timestamp === null || v1 === null ? null : { timestamp, v1 };
34
+ return timestamp === null || v1.length === 0 ? null : { timestamp, v1 };
35
35
  }
36
36
  /**
37
37
  * Vérifie la signature et renvoie l'événement typé.
@@ -59,12 +59,17 @@ export function constructEvent(payload, header, secret, options = {}) {
59
59
  throw new TupaySignatureVerificationError(`Horodatage hors tolérance (${tolerance} s) — possible rejeu d’une livraison capturée.`);
60
60
  }
61
61
  const raw = typeof payload === 'string' ? payload : payload.toString('utf8');
62
- const expected = createHmac('sha256', secret)
63
- .update(`${parts.timestamp}.${raw}`, 'utf8')
64
- .digest('hex');
65
- // Longueurs comparées d'abord : timingSafeEqual lève si elles diffèrent.
66
- if (expected.length !== parts.v1.length ||
67
- !timingSafeEqual(Buffer.from(expected, 'utf8'), Buffer.from(parts.v1, 'utf8'))) {
62
+ const expected = Buffer.from(createHmac('sha256', secret).update(`${parts.timestamp}.${raw}`, 'utf8').digest('hex'), 'utf8');
63
+ // UNE signature qui correspond suffit (renouvellement du secret en
64
+ // cours). Toutes sont comparées, sans sortie anticipée. Longueurs
65
+ // comparées d'abord : timingSafeEqual lève si elles diffèrent.
66
+ let valide = false;
67
+ for (const candidat of parts.v1) {
68
+ const recu = Buffer.from(candidat, 'utf8');
69
+ if (recu.length === expected.length && timingSafeEqual(expected, recu))
70
+ valide = true;
71
+ }
72
+ if (!valide) {
68
73
  throw new TupaySignatureVerificationError('Signature invalide — la charge utile ne correspond pas au secret de cet endpoint.');
69
74
  }
70
75
  try {
@@ -74,4 +79,23 @@ export function constructEvent(payload, header, secret, options = {}) {
74
79
  throw new TupaySignatureVerificationError('Signature valide mais corps illisible : le JSON est malformé.');
75
80
  }
76
81
  }
82
+ /**
83
+ * Fabrique un en-tête `Tupay-Signature` valide — pour vos TESTS.
84
+ *
85
+ * Votre gestionnaire de webhooks se teste sans réseau : signez un corps
86
+ * avec le secret de test, passez-le à votre route, vérifiez qu'elle
87
+ * l'accepte — et qu'elle refuse un corps modifié.
88
+ *
89
+ * C'est aussi ce que fait `tupay listen` pour relayer vers votre poste.
90
+ *
91
+ * @example
92
+ * const corps = JSON.stringify(evenement)
93
+ * const entete = generateTestHeader({ payload: corps, secret: 'whsec_test' })
94
+ * await request(app).post('/hook').set('tupay-signature', entete).send(corps)
95
+ */
96
+ export function generateTestHeader(params) {
97
+ const t = params.timestamp ?? Math.floor(Date.now() / 1000);
98
+ const v1 = createHmac('sha256', params.secret).update(`${t}.${params.payload}`, 'utf8').digest('hex');
99
+ return `t=${t},v1=${v1}`;
100
+ }
77
101
  //# sourceMappingURL=webhooks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/webhooks.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tupay",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "SDK Node officiel de Tupay : encaissement en XPF pour la Polynésie française.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -10,6 +10,9 @@
10
10
  "main": "./dist/cjs/index.js",
11
11
  "module": "./dist/esm/index.js",
12
12
  "types": "./dist/esm/index.d.ts",
13
+ "bin": {
14
+ "tupay": "./dist/esm/cli.js"
15
+ },
13
16
  "exports": {
14
17
  ".": {
15
18
  "import": {