@inno-isw/react-native-rtp 0.1.0 → 0.2.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 (39) hide show
  1. package/README.md +33 -10
  2. package/lib/module/client.js +184 -11
  3. package/lib/module/client.js.map +1 -1
  4. package/lib/module/constants.js +5 -0
  5. package/lib/module/constants.js.map +1 -1
  6. package/lib/module/index.js +2 -2
  7. package/lib/module/index.js.map +1 -1
  8. package/lib/module/mock/makeRtpPayload.js +3 -0
  9. package/lib/module/mock/makeRtpPayload.js.map +1 -1
  10. package/lib/module/mock/mockTransport.js +9 -2
  11. package/lib/module/mock/mockTransport.js.map +1 -1
  12. package/lib/module/react/RtpProvider.js +13 -3
  13. package/lib/module/react/RtpProvider.js.map +1 -1
  14. package/lib/module/validate.js +42 -0
  15. package/lib/module/validate.js.map +1 -1
  16. package/lib/typescript/src/client.d.ts +12 -3
  17. package/lib/typescript/src/client.d.ts.map +1 -1
  18. package/lib/typescript/src/constants.d.ts +5 -0
  19. package/lib/typescript/src/constants.d.ts.map +1 -1
  20. package/lib/typescript/src/index.d.ts +2 -2
  21. package/lib/typescript/src/index.d.ts.map +1 -1
  22. package/lib/typescript/src/mock/makeRtpPayload.d.ts.map +1 -1
  23. package/lib/typescript/src/mock/mockTransport.d.ts +7 -1
  24. package/lib/typescript/src/mock/mockTransport.d.ts.map +1 -1
  25. package/lib/typescript/src/react/RtpProvider.d.ts +6 -2
  26. package/lib/typescript/src/react/RtpProvider.d.ts.map +1 -1
  27. package/lib/typescript/src/types.d.ts +11 -0
  28. package/lib/typescript/src/types.d.ts.map +1 -1
  29. package/lib/typescript/src/validate.d.ts +11 -0
  30. package/lib/typescript/src/validate.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/client.ts +202 -13
  33. package/src/constants.ts +5 -0
  34. package/src/index.tsx +3 -1
  35. package/src/mock/makeRtpPayload.ts +3 -0
  36. package/src/mock/mockTransport.ts +18 -2
  37. package/src/react/RtpProvider.tsx +40 -5
  38. package/src/types.ts +11 -0
  39. package/src/validate.ts +48 -0
@@ -64,11 +64,53 @@ export function toRtpRequest(payload) {
64
64
  payee: payload.payee,
65
65
  narration: payload.narration,
66
66
  transactionRef: payload.transactionRef,
67
+ orderNumber: payload.orderNumber,
68
+ deepLink: payload.deepLink,
69
+ actionMessage: payload.actionMessage,
67
70
  expiresAt: payload.expiresAt,
68
71
  recipient: payload.recipient
69
72
  };
70
73
  }
71
74
 
75
+ /**
76
+ * Build a partial-request patch from an incoming payload, copying only the
77
+ * fields that are actually present. Used to overlay retrieved backend details
78
+ * without a partial response erasing data already held from the push.
79
+ */
80
+ export function toRequestPatch(payload) {
81
+ const patch = {};
82
+ if (payload.rtpId !== undefined) patch.id = payload.rtpId;
83
+ if (payload.amount !== undefined) patch.amount = toAmount(payload.amount);
84
+ if (payload.currency !== undefined) patch.currency = payload.currency;
85
+ if (payload.payer !== undefined) patch.payer = payload.payer;
86
+ if (payload.payee !== undefined) patch.payee = payload.payee;
87
+ if (payload.narration !== undefined) patch.narration = payload.narration;
88
+ if (payload.transactionRef !== undefined) patch.transactionRef = payload.transactionRef;
89
+ if (payload.orderNumber !== undefined) patch.orderNumber = payload.orderNumber;
90
+ if (payload.deepLink !== undefined) patch.deepLink = payload.deepLink;
91
+ if (payload.actionMessage !== undefined) patch.actionMessage = payload.actionMessage;
92
+ if (payload.expiresAt !== undefined) patch.expiresAt = payload.expiresAt;
93
+ if (payload.recipient !== undefined) patch.recipient = payload.recipient;
94
+ return patch;
95
+ }
96
+
97
+ /**
98
+ * Overlay a patch onto an existing request. Only defined, non-null values are
99
+ * copied so a partial response never erases information already held.
100
+ */
101
+ export function mergeRequest(current, patch) {
102
+ const next = {
103
+ ...current
104
+ };
105
+ for (const key of Object.keys(patch)) {
106
+ const value = patch[key];
107
+ if (value !== undefined && value !== null) {
108
+ next[key] = value;
109
+ }
110
+ }
111
+ return next;
112
+ }
113
+
72
114
  /** Pure expiry check. Re-evaluated on every transition, not just on receive. */
73
115
  export function isExpired(request, now) {
74
116
  const expiry = new Date(request.expiresAt).getTime();
@@ -1 +1 @@
1
- {"version":3,"names":["REQUIRED_FIELDS","isRtpPayload","payload","candidate","type","rtpId","findValidationErrors","errors","record","field","undefined","push","expiresAt","Number","isNaN","Date","getTime","side","party","name","toAmount","value","parsed","toRtpRequest","id","amount","currency","payer","payee","narration","transactionRef","recipient","isExpired","request","now","expiry"],"sourceRoot":"../../src","sources":["validate.ts"],"mappings":";;AAEA;AACA,MAAMA,eAAe,GAAG,CACtB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,OAAO,EACP,OAAO,EACP,WAAW,CACH;;AAEV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,YAAYA,CAACC,OAAgB,EAAyB;EACpE,IAAI,CAACA,OAAO,IAAI,OAAOA,OAAO,KAAK,QAAQ,EAAE;IAC3C,OAAO,KAAK;EACd;EACA,MAAMC,SAAS,GAAGD,OAAkC;EACpD,OAAOC,SAAS,CAACC,IAAI,KAAK,KAAK,IAAI,OAAOD,SAAS,CAACE,KAAK,KAAK,QAAQ;AACxE;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACJ,OAAmB,EAAY;EAClE,MAAMK,MAAgB,GAAG,EAAE;EAC3B,MAAMC,MAAM,GAAGN,OAA6C;EAE5D,KAAK,MAAMO,KAAK,IAAIT,eAAe,EAAE;IACnC,IAAIQ,MAAM,CAACC,KAAK,CAAC,KAAKC,SAAS,IAAIF,MAAM,CAACC,KAAK,CAAC,KAAK,IAAI,EAAE;MACzDF,MAAM,CAACI,IAAI,CAACF,KAAK,CAAC;IACpB;EACF;EAEA,IACEP,OAAO,CAACU,SAAS,KAAKF,SAAS,IAC/BG,MAAM,CAACC,KAAK,CAAC,IAAIC,IAAI,CAACb,OAAO,CAACU,SAAS,CAAC,CAACI,OAAO,CAAC,CAAC,CAAC,EACnD;IACAT,MAAM,CAACI,IAAI,CAAC,WAAW,CAAC;EAC1B;EAEA,KAAK,MAAMM,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAW;IAC9C,MAAMC,KAAK,GAAGhB,OAAO,CAACe,IAAI,CAAyB;IACnD,IAAI,CAACC,KAAK,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAI,OAAOA,KAAK,CAACC,IAAI,KAAK,QAAQ,EAAE;MACzEZ,MAAM,CAACI,IAAI,CAAC,GAAGM,IAAI,OAAO,CAAC;IAC7B;EACF;EAEA,OAAOV,MAAM;AACf;;AAEA;AACA,SAASa,QAAQA,CAACC,KAAc,EAAU;EACxC,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE;IAC7B,OAAOA,KAAK;EACd;EACA,MAAMC,MAAM,GAAGT,MAAM,CAACQ,KAAK,CAAC;EAC5B,OAAOR,MAAM,CAACC,KAAK,CAACQ,MAAM,CAAC,GAAG,CAAC,GAAGA,MAAM;AAC1C;;AAEA;AACA,OAAO,SAASC,YAAYA,CAACrB,OAAmB,EAAc;EAC5D,OAAO;IACLsB,EAAE,EAAEtB,OAAO,CAACG,KAAK;IACjBoB,MAAM,EAAEL,QAAQ,CAAClB,OAAO,CAACuB,MAAM,CAAC;IAChCC,QAAQ,EAAExB,OAAO,CAACwB,QAAQ;IAC1BC,KAAK,EAAEzB,OAAO,CAACyB,KAAK;IACpBC,KAAK,EAAE1B,OAAO,CAAC0B,KAAK;IACpBC,SAAS,EAAE3B,OAAO,CAAC2B,SAAS;IAC5BC,cAAc,EAAE5B,OAAO,CAAC4B,cAAc;IACtClB,SAAS,EAAEV,OAAO,CAACU,SAAS;IAC5BmB,SAAS,EAAE7B,OAAO,CAAC6B;EACrB,CAAC;AACH;;AAEA;AACA,OAAO,SAASC,SAASA,CAACC,OAAmB,EAAEC,GAAW,EAAW;EACnE,MAAMC,MAAM,GAAG,IAAIpB,IAAI,CAACkB,OAAO,CAACrB,SAAS,CAAC,CAACI,OAAO,CAAC,CAAC;EACpD,IAAIH,MAAM,CAACC,KAAK,CAACqB,MAAM,CAAC,EAAE;IACxB,OAAO,KAAK;EACd;EACA,OAAOA,MAAM,IAAID,GAAG;AACtB","ignoreList":[]}
1
+ {"version":3,"names":["REQUIRED_FIELDS","isRtpPayload","payload","candidate","type","rtpId","findValidationErrors","errors","record","field","undefined","push","expiresAt","Number","isNaN","Date","getTime","side","party","name","toAmount","value","parsed","toRtpRequest","id","amount","currency","payer","payee","narration","transactionRef","orderNumber","deepLink","actionMessage","recipient","toRequestPatch","patch","mergeRequest","current","next","key","Object","keys","isExpired","request","now","expiry"],"sourceRoot":"../../src","sources":["validate.ts"],"mappings":"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","ignoreList":[]}
@@ -1,11 +1,20 @@
1
+ import type { RtpStatus } from './constants.js';
1
2
  import type { RtpClient, RtpClientOptions } from './types.js';
3
+ /**
4
+ * Map a backend status string onto the normalized SDK status.
5
+ *
6
+ * Unknown values are deliberately **not** treated as success — they map to
7
+ * `undefined` so the caller can decide, rather than silently reporting an
8
+ * approved payment for a status the client does not understand.
9
+ */
10
+ export declare function normalizeBackendStatus(raw: unknown): RtpStatus | undefined;
2
11
  /**
3
12
  * Create a portable Request-to-Pay client.
4
13
  *
5
14
  * The client owns validation, de-duplication, expiry, status computation and
6
- * the accept/decline/status calls. It owns no UI, no navigation and no crypto.
7
- * Every external effect is injected so the same contract can be re-implemented
8
- * on other platforms.
15
+ * the accept/decline/retrieve calls. It owns no UI, no navigation and no
16
+ * crypto. Every external effect is injected so the same contract can be
17
+ * re-implemented on other platforms.
9
18
  */
10
19
  export declare function createRtpClient(options: RtpClientOptions): RtpClient;
11
20
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAKjB,MAAM,YAAS,CAAC;AAOjB;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CA+MpE"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,gBAAa,CAAC;AAUvD,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAMjB,MAAM,YAAS,CAAC;AAejB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAwB1E;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAgWpE"}
@@ -7,6 +7,8 @@
7
7
  export declare const RTP_STATUS: {
8
8
  /** Payload arrived and passed validation, but is not yet actionable. */
9
9
  readonly RECEIVED: "RECEIVED";
10
+ /** Authorization details are being fetched from the backend. */
11
+ readonly RETRIEVING: "RETRIEVING";
10
12
  /** Expired before it could be actioned. */
11
13
  readonly EXPIRED: "EXPIRED";
12
14
  /** Valid, but the user is not authenticated yet (login gate). */
@@ -15,6 +17,8 @@ export declare const RTP_STATUS: {
15
17
  readonly READY: "READY";
16
18
  /** Accept/decline in flight. */
17
19
  readonly PROCESSING: "PROCESSING";
20
+ /** Backend accepted the action but a final decision is still pending. */
21
+ readonly PENDING: "PENDING";
18
22
  /** Backend confirmed acceptance. */
19
23
  readonly ACCEPTED: "ACCEPTED";
20
24
  /** Backend confirmed (or user initiated) a decline. */
@@ -37,6 +41,7 @@ export type RtpEvent = (typeof RTP_EVENT)[keyof typeof RTP_EVENT];
37
41
  export declare const RTP_ERROR: {
38
42
  readonly INVALID_PAYLOAD: "INVALID_PAYLOAD";
39
43
  readonly RECIPIENT_MISMATCH: "RECIPIENT_MISMATCH";
44
+ readonly RETRIEVE_FAILED: "RETRIEVE_FAILED";
40
45
  readonly NETWORK_ERROR: "NETWORK_ERROR";
41
46
  readonly BACKEND_REJECTED: "BACKEND_REJECTED";
42
47
  readonly UNKNOWN: "UNKNOWN";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,UAAU;IACrB,wEAAwE;;IAExE,2CAA2C;;IAE3C,iEAAiE;;IAEjE,sEAAsE;;IAEtE,gCAAgC;;IAEhC,oCAAoC;;IAEpC,uDAAuD;;IAEvD,wEAAwE;;CAEhE,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAErE,oCAAoC;AACpC,eAAO,MAAM,SAAS;IACpB,8CAA8C;;IAE9C,uCAAuC;;IAEvC,sCAAsC;;CAE9B,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAElE,uEAAuE;AACvE,eAAO,MAAM,SAAS;;;;;;CAMZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,UAAU;IACrB,wEAAwE;;IAExE,gEAAgE;;IAEhE,2CAA2C;;IAE3C,iEAAiE;;IAEjE,sEAAsE;;IAEtE,gCAAgC;;IAEhC,yEAAyE;;IAEzE,oCAAoC;;IAEpC,uDAAuD;;IAEvD,wEAAwE;;CAEhE,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAErE,oCAAoC;AACpC,eAAO,MAAM,SAAS;IACpB,8CAA8C;;IAE9C,uCAAuC;;IAEvC,sCAAsC;;CAE9B,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAElE,uEAAuE;AACvE,eAAO,MAAM,SAAS;;;;;;;CAOZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC"}
@@ -1,7 +1,7 @@
1
- export { createRtpClient } from './client.js';
1
+ export { createRtpClient, normalizeBackendStatus } from './client.js';
2
2
  export { RTP_STATUS, RTP_EVENT, RTP_ERROR } from './constants.js';
3
3
  export type { RtpStatus, RtpEvent, RtpError } from './constants.js';
4
- export { isRtpPayload, findValidationErrors, toRtpRequest, isExpired, } from './validate.js';
4
+ export { isRtpPayload, findValidationErrors, toRtpRequest, toRequestPatch, mergeRequest, isExpired, } from './validate.js';
5
5
  export { mapPushToRtp } from './push.js';
6
6
  export type { PushEnvelope } from './push.js';
7
7
  export type { RtpPayload, RtpParty, RtpRequest, RtpCredential, RtpResult, RtpReceiveOutcome, RtpTransport, RtpStorage, RtpHttpResponse, RtpClient, RtpClientOptions, RtpEventMap, RtpUnsubscribe, } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAU,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAa,CAAC;AAC/D,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAa,CAAC;AACjE,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,SAAS,GACV,MAAM,eAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAQ,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAQ,CAAC;AAG3C,YAAY,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,cAAc,GACf,MAAM,YAAS,CAAC;AAGjB,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,wBAAqB,CAAC;AACtE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAG7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAsB,CAAC;AAC3D,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,YAAY,GACb,MAAM,yBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,0BAAuB,CAAC;AAC3E,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,aAAU,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAa,CAAC;AAC/D,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAa,CAAC;AACjE,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,SAAS,GACV,MAAM,eAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAQ,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAQ,CAAC;AAG3C,YAAY,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,cAAc,GACf,MAAM,YAAS,CAAC;AAGjB,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,wBAAqB,CAAC;AACtE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,wBAAqB,CAAC;AAG7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAsB,CAAC;AAC3D,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,YAAY,GACb,MAAM,yBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,0BAAuB,CAAC;AAC3E,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAAuB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"makeRtpPayload.d.ts","sourceRoot":"","sources":["../../../../src/mock/makeRtpPayload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAU,CAAC;AAO3C,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CACtD,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC,CAC3D;IACC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,GAAE,uBAA4B,GACtC,UAAU,CAkCZ;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAChC,SAAS,GAAE,uBAA4B,GACtC,UAAU,CAEZ"}
1
+ {"version":3,"file":"makeRtpPayload.d.ts","sourceRoot":"","sources":["../../../../src/mock/makeRtpPayload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAU,CAAC;AAO3C,MAAM,WAAW,uBAAwB,SAAQ,OAAO,CACtD,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC,CAC3D;IACC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,GAAE,uBAA4B,GACtC,UAAU,CAqCZ;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,CAChC,SAAS,GAAE,uBAA4B,GACtC,UAAU,CAEZ"}
@@ -6,8 +6,14 @@ export interface MockTransportOptions {
6
6
  failAccept?: boolean;
7
7
  /** Simulate a network failure on decline. */
8
8
  failDecline?: boolean;
9
+ /** Simulate a network failure on retrieve (details fetch). */
10
+ failRetrieve?: boolean;
9
11
  /** Backend status to return for accept. */
10
- acceptStatus?: 'ACCEPTED' | 'DECLINED' | 'FAILED';
12
+ acceptStatus?: 'ACCEPTED' | 'DECLINED' | 'FAILED' | 'PENDING' | 'EXPIRED';
13
+ /** Backend status to return for retrieve. Unknown values fall through to READY. */
14
+ retrieveStatus?: string;
15
+ /** Request details to return from retrieve (overlaid onto the held request). */
16
+ retrieveRequest?: Record<string, unknown>;
11
17
  }
12
18
  export interface RecordedCall {
13
19
  method: 'post' | 'get';
@@ -1 +1 @@
1
- {"version":3,"file":"mockTransport.d.ts","sourceRoot":"","sources":["../../../../src/mock/mockTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,aAAU,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,YAAY,CAAC;IACxB,mEAAmE;IACnE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAgEf"}
1
+ {"version":3,"file":"mockTransport.d.ts","sourceRoot":"","sources":["../../../../src/mock/mockTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,aAAU,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1E,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,YAAY,CAAC;IACxB,mEAAmE;IACnE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,oBAAyB,GACjC,aAAa,CA0Ef"}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { RtpClient, RtpCredential, RtpRequest, RtpResult } from '../types.js';
2
+ import type { RtpClient, RtpCredential, RtpReceiveOutcome, RtpRequest, RtpResult } from '../types.js';
3
3
  import type { RtpStatus } from '../constants.js';
4
4
  /**
5
5
  * A minimal persistence port for the provider. The host supplies its own
@@ -32,14 +32,18 @@ export interface RtpContextValue {
32
32
  status: RtpStatus | null;
33
33
  /** True when a request is ready for the user to act on. */
34
34
  isReady: boolean;
35
+ /** True while authorization details are being fetched from the backend. */
36
+ isLoading: boolean;
35
37
  /** Accept the active request with an opaque credential. */
36
38
  accept: (credential?: RtpCredential) => Promise<RtpResult | undefined>;
37
39
  /** Decline the active request. */
38
40
  decline: (reason?: string) => Promise<RtpResult | undefined>;
41
+ /** Fetch/refresh authorization details for the active request. */
42
+ retrieve: (id?: string) => Promise<RtpResult | undefined>;
39
43
  /** Dismiss the active request from the UI. */
40
44
  dismiss: () => void;
41
45
  /** Feed a raw decoded payload into the client (for host push adapters). */
42
- receive: (payload: unknown) => void;
46
+ receive: (payload: unknown) => Promise<RtpReceiveOutcome | undefined>;
43
47
  /** Last terminal result, for rendering feedback. */
44
48
  lastResult: RtpResult | null;
45
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RtpProvider.d.ts","sourceRoot":"","sources":["../../../../src/react/RtpProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAU,CAAC;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAc,CAAC;AAI9C;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,MAAM,EAAE,SAAS,CAAC;IAClB,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACvE,kCAAkC;IAClC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC7D,8CAA8C;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2EAA2E;IAC3E,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,oDAAoD;IACpD,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,UAAU,uCAA8C,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,QAAQ,GACT,EAAE,gBAAgB,qBAkHlB;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAQxC"}
1
+ {"version":3,"file":"RtpProvider.d.ts","sourceRoot":"","sources":["../../../../src/react/RtpProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,SAAS,EACV,MAAM,aAAU,CAAC;AAElB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAc,CAAC;AAI9C;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,MAAM,EAAE,SAAS,CAAC;IAClB,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC3B,8CAA8C;IAC9C,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACvE,kCAAkC;IAClC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC7D,kEAAkE;IAClE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC1D,8CAA8C;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2EAA2E;IAC3E,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAAC;IACtE,oDAAoD;IACpD,UAAU,EAAE,SAAS,GAAG,IAAI,CAAC;CAC9B;AAED,eAAO,MAAM,UAAU,uCAA8C,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,QAAQ,GACT,EAAE,gBAAgB,qBA2IlB;AAED;;GAEG;AACH,wBAAgB,MAAM,IAAI,eAAe,CAQxC"}
@@ -26,6 +26,12 @@ export interface RtpPayload {
26
26
  narration?: string;
27
27
  /** Backend reference for the transaction. */
28
28
  transactionRef?: string;
29
+ /** Merchant/issuer order number for the request (distinct from transactionRef). */
30
+ orderNumber?: string;
31
+ /** Secure transaction / deep-link reference the host can use to open the flow. */
32
+ deepLink?: string;
33
+ /** Instruction shown to the customer describing the action required. */
34
+ actionMessage?: string;
29
35
  /** ISO 8601 timestamp after which the request can no longer be actioned. */
30
36
  expiresAt: string;
31
37
  /** Alias (phone/email) the request is addressed to, for identity matching. */
@@ -50,6 +56,9 @@ export interface RtpRequest {
50
56
  payee: RtpParty;
51
57
  narration?: string;
52
58
  transactionRef?: string;
59
+ orderNumber?: string;
60
+ deepLink?: string;
61
+ actionMessage?: string;
53
62
  expiresAt: string;
54
63
  recipient?: string;
55
64
  }
@@ -125,6 +134,8 @@ export interface RtpEventMap {
125
134
  export interface RtpClient {
126
135
  isRtp: (payload: unknown) => payload is RtpPayload;
127
136
  receive: (payload: unknown) => Promise<RtpReceiveOutcome>;
137
+ /** Fetch/refresh authorization details for a request from the backend. */
138
+ retrieve: (id: string) => Promise<RtpResult>;
128
139
  resumeAuth: () => void;
129
140
  accept: (params: {
130
141
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAa,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,IAAI,EAAE,KAAK,CAAC;IACZ,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,KAAK,EAAE,QAAQ,CAAC;IAChB,yCAAyC;IACzC,KAAK,EAAE,QAAQ,CAAC;IAChB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sDAAsD;IACtD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,QAAQ,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC3B;AAID,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,GAAG;IACtC,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,CAAC,CAAC,GAAG,GAAG,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACjC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC7B,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC;AAED,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9D,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,4BAA4B;IAC5B,SAAS,EAAE,YAAY,CAAC;IACxB;;;OAGG;IACH,cAAc,CAAC,EAAE,MACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3D;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,qCAAqC;IACrC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACtC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,KAAK,EAAE,CAAC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1D,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,IAAI,UAAU,CAAC;IACnD,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC1D,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,EAAE,CAAC,MAAM,EAAE;QACf,EAAE,EAAE,MAAM,CAAC;QACX,UAAU,CAAC,EAAE,aAAa,CAAC;KAC5B,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACzB,OAAO,EAAE,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACzE,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IACjD,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IACnD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,EAAE,EAAE,CAAC,CAAC,SAAS,MAAM,WAAW,EAC9B,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,KACpB,cAAc,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,17 @@ export declare function isRtpPayload(payload: unknown): payload is RtpPayload;
17
17
  export declare function findValidationErrors(payload: RtpPayload): string[];
18
18
  /** Map a validated payload into the normalized request held by the SDK. */
19
19
  export declare function toRtpRequest(payload: RtpPayload): RtpRequest;
20
+ /**
21
+ * Build a partial-request patch from an incoming payload, copying only the
22
+ * fields that are actually present. Used to overlay retrieved backend details
23
+ * without a partial response erasing data already held from the push.
24
+ */
25
+ export declare function toRequestPatch(payload: Partial<RtpPayload>): Partial<RtpRequest>;
26
+ /**
27
+ * Overlay a patch onto an existing request. Only defined, non-null values are
28
+ * copied so a partial response never erases information already held.
29
+ */
30
+ export declare function mergeRequest(current: RtpRequest, patch: Partial<RtpRequest>): RtpRequest;
20
31
  /** Pure expiry check. Re-evaluated on every transition, not just on receive. */
21
32
  export declare function isExpired(request: RtpRequest, now: number): boolean;
22
33
  //# sourceMappingURL=validate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,UAAU,EAAE,UAAU,EAAE,MAAM,YAAS,CAAC;AAYhE;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAMpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,CAyBlE;AAWD,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAY5D;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAMnE"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,UAAU,EAAE,UAAU,EAAE,MAAM,YAAS,CAAC;AAYhE;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,UAAU,CAMpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,EAAE,CAyBlE;AAWD,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,CAe5D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAC3B,OAAO,CAAC,UAAU,CAAC,CAkBrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GACzB,UAAU,CASZ;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAMnE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inno-isw/react-native-rtp",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Request to Pay SDK for React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
package/src/client.ts CHANGED
@@ -5,12 +5,15 @@ import {
5
5
  findValidationErrors,
6
6
  isExpired,
7
7
  isRtpPayload,
8
+ mergeRequest,
9
+ toRequestPatch,
8
10
  toRtpRequest,
9
11
  } from './validate';
10
12
  import type {
11
13
  RtpClient,
12
14
  RtpClientOptions,
13
15
  RtpCredential,
16
+ RtpPayload,
14
17
  RtpReceiveOutcome,
15
18
  RtpRequest,
16
19
  RtpResult,
@@ -21,13 +24,54 @@ interface Entry {
21
24
  status: RtpStatus;
22
25
  }
23
26
 
27
+ /** Statuses after which a request is finished with. */
28
+ const TERMINAL_STATUSES: ReadonlySet<RtpStatus> = new Set([
29
+ RTP_STATUS.ACCEPTED,
30
+ RTP_STATUS.DECLINED,
31
+ RTP_STATUS.EXPIRED,
32
+ RTP_STATUS.FAILED,
33
+ ]);
34
+
35
+ /**
36
+ * Map a backend status string onto the normalized SDK status.
37
+ *
38
+ * Unknown values are deliberately **not** treated as success — they map to
39
+ * `undefined` so the caller can decide, rather than silently reporting an
40
+ * approved payment for a status the client does not understand.
41
+ */
42
+ export function normalizeBackendStatus(raw: unknown): RtpStatus | undefined {
43
+ if (typeof raw !== 'string') {
44
+ return undefined;
45
+ }
46
+ switch (raw.toUpperCase()) {
47
+ case 'ACCEPTED':
48
+ case 'APPROVED':
49
+ case 'SUCCESS':
50
+ case 'SUCCESSFUL':
51
+ return RTP_STATUS.ACCEPTED;
52
+ case 'DECLINED':
53
+ case 'USER_DECLINED':
54
+ return RTP_STATUS.DECLINED;
55
+ case 'EXPIRED':
56
+ return RTP_STATUS.EXPIRED;
57
+ case 'PENDING':
58
+ case 'PROCESSING':
59
+ return RTP_STATUS.PENDING;
60
+ case 'FAILED':
61
+ case 'REJECTED':
62
+ return RTP_STATUS.FAILED;
63
+ default:
64
+ return undefined;
65
+ }
66
+ }
67
+
24
68
  /**
25
69
  * Create a portable Request-to-Pay client.
26
70
  *
27
71
  * The client owns validation, de-duplication, expiry, status computation and
28
- * the accept/decline/status calls. It owns no UI, no navigation and no crypto.
29
- * Every external effect is injected so the same contract can be re-implemented
30
- * on other platforms.
72
+ * the accept/decline/retrieve calls. It owns no UI, no navigation and no
73
+ * crypto. Every external effect is injected so the same contract can be
74
+ * re-implemented on other platforms.
31
75
  */
32
76
  export function createRtpClient(options: RtpClientOptions): RtpClient {
33
77
  const {
@@ -46,11 +90,57 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
46
90
  const emitter = createEmitter();
47
91
  const entries = new Map<string, Entry>();
48
92
 
93
+ // --- expiry scheduling --------------------------------------------------
94
+ // Expiry is not only evaluated lazily: an inactive timer fires at `expiresAt`
95
+ // so a request cannot remain actionable after it has lapsed (INDV-3807/3808).
96
+ let expiryTimer: ReturnType<typeof setTimeout> | undefined;
97
+ let expiryTimerId: string | undefined;
98
+
99
+ function clearExpiryTimer(): void {
100
+ if (expiryTimer !== undefined) {
101
+ clearTimeout(expiryTimer);
102
+ }
103
+ expiryTimer = undefined;
104
+ expiryTimerId = undefined;
105
+ }
106
+
107
+ function scheduleExpiry(entry: Entry): void {
108
+ clearExpiryTimer();
109
+
110
+ const expiry = new Date(entry.request.expiresAt).getTime();
111
+ if (Number.isNaN(expiry)) {
112
+ return;
113
+ }
114
+
115
+ const id = entry.request.id;
116
+ expiryTimerId = id;
117
+ expiryTimer = setTimeout(
118
+ () => {
119
+ const current = entries.get(id);
120
+ if (!current || TERMINAL_STATUSES.has(current.status)) {
121
+ return;
122
+ }
123
+ logger('[react-native-rtp] request expired:', id);
124
+ emitResult({ id, status: RTP_STATUS.EXPIRED });
125
+ },
126
+ Math.max(0, expiry - now())
127
+ );
128
+
129
+ // Never keep a Node process (e.g. Jest) alive for a pending expiry.
130
+ const handle = expiryTimer as unknown as { unref?: () => void };
131
+ if (typeof handle?.unref === 'function') {
132
+ handle.unref();
133
+ }
134
+ }
135
+
49
136
  function setStatus(id: string, status: RtpStatus): void {
50
137
  const entry = entries.get(id);
51
138
  if (entry) {
52
139
  entry.status = status;
53
140
  }
141
+ if (TERMINAL_STATUSES.has(status) && expiryTimerId === id) {
142
+ clearExpiryTimer();
143
+ }
54
144
  emitter.emit(RTP_EVENT.STATE, { id, status });
55
145
  }
56
146
 
@@ -89,7 +179,8 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
89
179
  }
90
180
 
91
181
  const request = toRtpRequest(payload);
92
- entries.set(id, { request, status: RTP_STATUS.RECEIVED });
182
+ const entry: Entry = { request, status: RTP_STATUS.RECEIVED };
183
+ entries.set(id, entry);
93
184
 
94
185
  if (isExpired(request, now())) {
95
186
  const result = emitResult({ id, status: RTP_STATUS.EXPIRED });
@@ -100,6 +191,7 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
100
191
 
101
192
  if (!currentUser) {
102
193
  setStatus(id, RTP_STATUS.AWAITING_AUTH);
194
+ scheduleExpiry(entry);
103
195
  return { handled: true, request, status: RTP_STATUS.AWAITING_AUTH };
104
196
  }
105
197
 
@@ -114,10 +206,84 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
114
206
  }
115
207
 
116
208
  setStatus(id, RTP_STATUS.READY);
209
+ scheduleExpiry(entry);
117
210
  emitter.emit(RTP_EVENT.REQUEST, request);
118
211
  return { handled: true, request, status: RTP_STATUS.READY };
119
212
  }
120
213
 
214
+ /**
215
+ * Fetch (or refresh) authorization details for a request from the backend,
216
+ * and reconcile the backend status. This is the "retrieve details" step the
217
+ * authorization page needs before it can be trusted (INDV-3804).
218
+ */
219
+ async function retrieve(id: string): Promise<RtpResult> {
220
+ const entry = entries.get(id);
221
+ if (!entry) {
222
+ return fail(id, RTP_ERROR.UNKNOWN);
223
+ }
224
+
225
+ if (isExpired(entry.request, now())) {
226
+ return emitResult({ id, status: RTP_STATUS.EXPIRED });
227
+ }
228
+
229
+ if (TERMINAL_STATUSES.has(entry.status)) {
230
+ return { id, status: entry.status };
231
+ }
232
+
233
+ setStatus(id, RTP_STATUS.RETRIEVING);
234
+
235
+ try {
236
+ const headers = await getAuthHeaders();
237
+ const res = await transport.get(`${basePath}/${id}`, headers);
238
+ const data = (res?.data ?? {}) as Record<string, unknown>;
239
+
240
+ const mapped = normalizeBackendStatus(data.status);
241
+
242
+ if (
243
+ mapped === RTP_STATUS.EXPIRED ||
244
+ mapped === RTP_STATUS.DECLINED ||
245
+ mapped === RTP_STATUS.FAILED
246
+ ) {
247
+ return emitResult({
248
+ id,
249
+ status: mapped,
250
+ data,
251
+ error:
252
+ mapped === RTP_STATUS.FAILED
253
+ ? RTP_ERROR.BACKEND_REJECTED
254
+ : undefined,
255
+ });
256
+ }
257
+
258
+ if (mapped === RTP_STATUS.ACCEPTED) {
259
+ return emitResult({ id, status: RTP_STATUS.ACCEPTED, data });
260
+ }
261
+
262
+ if (mapped === RTP_STATUS.PENDING) {
263
+ return emitResult({ id, status: RTP_STATUS.PENDING, data });
264
+ }
265
+
266
+ // Merge any returned details (a full payload, or nested under `request`).
267
+ const incoming = (data.request ?? data) as
268
+ Partial<RtpPayload> | undefined;
269
+ if (incoming && typeof incoming === 'object') {
270
+ entry.request = mergeRequest(entry.request, toRequestPatch(incoming));
271
+ }
272
+
273
+ if (isExpired(entry.request, now())) {
274
+ return emitResult({ id, status: RTP_STATUS.EXPIRED });
275
+ }
276
+
277
+ setStatus(id, RTP_STATUS.READY);
278
+ scheduleExpiry(entry);
279
+ emitter.emit(RTP_EVENT.REQUEST, entry.request);
280
+ return { id, status: RTP_STATUS.READY, data };
281
+ } catch (err) {
282
+ logger('[react-native-rtp] retrieve failed:', err);
283
+ return fail(id, RTP_ERROR.RETRIEVE_FAILED);
284
+ }
285
+ }
286
+
121
287
  /**
122
288
  * Called by the host after a successful login to release any requests that
123
289
  * were waiting on the auth gate.
@@ -149,6 +315,7 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
149
315
  }
150
316
 
151
317
  setStatus(id, RTP_STATUS.READY);
318
+ scheduleExpiry(entry);
152
319
  emitter.emit(RTP_EVENT.REQUEST, entry.request);
153
320
  }
154
321
  }
@@ -176,18 +343,22 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
176
343
  { credential },
177
344
  headers
178
345
  );
179
- const backendStatus = res?.data?.status;
180
- const status: RtpStatus =
181
- backendStatus === 'DECLINED'
182
- ? RTP_STATUS.DECLINED
183
- : backendStatus === 'FAILED'
184
- ? RTP_STATUS.FAILED
185
- : RTP_STATUS.ACCEPTED;
346
+ const data = (res?.data ?? {}) as Record<string, unknown>;
347
+
348
+ // If the backend returned a status we recognise, honour it. If it
349
+ // returned no status at all, the accept call itself succeeded. If it
350
+ // returned a status we do NOT understand, fail closed rather than
351
+ // showing the customer an approved payment we cannot vouch for.
352
+ const hasStatus = data.status !== undefined && data.status !== null;
353
+ const mapped = normalizeBackendStatus(data.status);
354
+ const status: RtpStatus = hasStatus
355
+ ? (mapped ?? RTP_STATUS.FAILED)
356
+ : RTP_STATUS.ACCEPTED;
186
357
 
187
358
  return emitResult({
188
359
  id,
189
360
  status,
190
- data: res?.data,
361
+ data,
191
362
  error:
192
363
  status === RTP_STATUS.FAILED ? RTP_ERROR.BACKEND_REJECTED : undefined,
193
364
  });
@@ -216,7 +387,21 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
216
387
  { reason },
217
388
  headers
218
389
  );
219
- return emitResult({ id, status: RTP_STATUS.DECLINED, data: res?.data });
390
+ const data = (res?.data ?? {}) as Record<string, unknown>;
391
+
392
+ const mapped = normalizeBackendStatus(data.status);
393
+ const status: RtpStatus =
394
+ mapped === RTP_STATUS.EXPIRED || mapped === RTP_STATUS.FAILED
395
+ ? mapped
396
+ : RTP_STATUS.DECLINED;
397
+
398
+ return emitResult({
399
+ id,
400
+ status,
401
+ data,
402
+ error:
403
+ status === RTP_STATUS.FAILED ? RTP_ERROR.BACKEND_REJECTED : undefined,
404
+ });
220
405
  } catch (err) {
221
406
  logger('[react-native-rtp] decline failed:', err);
222
407
  return fail(id, RTP_ERROR.NETWORK_ERROR);
@@ -226,12 +411,16 @@ export function createRtpClient(options: RtpClientOptions): RtpClient {
226
411
  return {
227
412
  isRtp: isRtpPayload,
228
413
  receive,
414
+ retrieve,
229
415
  resumeAuth,
230
416
  accept,
231
417
  decline,
232
418
  getStatus: (id: string) => entries.get(id)?.status,
233
419
  getRequest: (id: string) => entries.get(id)?.request,
234
420
  acknowledge: (id: string) => {
421
+ if (expiryTimerId === id) {
422
+ clearExpiryTimer();
423
+ }
235
424
  entries.delete(id);
236
425
  },
237
426
  on: emitter.on,
package/src/constants.ts CHANGED
@@ -7,6 +7,8 @@
7
7
  export const RTP_STATUS = {
8
8
  /** Payload arrived and passed validation, but is not yet actionable. */
9
9
  RECEIVED: 'RECEIVED',
10
+ /** Authorization details are being fetched from the backend. */
11
+ RETRIEVING: 'RETRIEVING',
10
12
  /** Expired before it could be actioned. */
11
13
  EXPIRED: 'EXPIRED',
12
14
  /** Valid, but the user is not authenticated yet (login gate). */
@@ -15,6 +17,8 @@ export const RTP_STATUS = {
15
17
  READY: 'READY',
16
18
  /** Accept/decline in flight. */
17
19
  PROCESSING: 'PROCESSING',
20
+ /** Backend accepted the action but a final decision is still pending. */
21
+ PENDING: 'PENDING',
18
22
  /** Backend confirmed acceptance. */
19
23
  ACCEPTED: 'ACCEPTED',
20
24
  /** Backend confirmed (or user initiated) a decline. */
@@ -41,6 +45,7 @@ export type RtpEvent = (typeof RTP_EVENT)[keyof typeof RTP_EVENT];
41
45
  export const RTP_ERROR = {
42
46
  INVALID_PAYLOAD: 'INVALID_PAYLOAD',
43
47
  RECIPIENT_MISMATCH: 'RECIPIENT_MISMATCH',
48
+ RETRIEVE_FAILED: 'RETRIEVE_FAILED',
44
49
  NETWORK_ERROR: 'NETWORK_ERROR',
45
50
  BACKEND_REJECTED: 'BACKEND_REJECTED',
46
51
  UNKNOWN: 'UNKNOWN',