@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.
- package/README.md +33 -10
- package/lib/module/client.js +184 -11
- package/lib/module/client.js.map +1 -1
- package/lib/module/constants.js +5 -0
- package/lib/module/constants.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/mock/makeRtpPayload.js +3 -0
- package/lib/module/mock/makeRtpPayload.js.map +1 -1
- package/lib/module/mock/mockTransport.js +9 -2
- package/lib/module/mock/mockTransport.js.map +1 -1
- package/lib/module/react/RtpProvider.js +13 -3
- package/lib/module/react/RtpProvider.js.map +1 -1
- package/lib/module/validate.js +42 -0
- package/lib/module/validate.js.map +1 -1
- package/lib/typescript/src/client.d.ts +12 -3
- package/lib/typescript/src/client.d.ts.map +1 -1
- package/lib/typescript/src/constants.d.ts +5 -0
- package/lib/typescript/src/constants.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/mock/makeRtpPayload.d.ts.map +1 -1
- package/lib/typescript/src/mock/mockTransport.d.ts +7 -1
- package/lib/typescript/src/mock/mockTransport.d.ts.map +1 -1
- package/lib/typescript/src/react/RtpProvider.d.ts +6 -2
- package/lib/typescript/src/react/RtpProvider.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +11 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/validate.d.ts +11 -0
- package/lib/typescript/src/validate.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +202 -13
- package/src/constants.ts +5 -0
- package/src/index.tsx +3 -1
- package/src/mock/makeRtpPayload.ts +3 -0
- package/src/mock/mockTransport.ts +18 -2
- package/src/react/RtpProvider.tsx +40 -5
- package/src/types.ts +11 -0
- package/src/validate.ts +48 -0
package/lib/module/validate.js
CHANGED
|
@@ -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;
|
|
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/
|
|
7
|
-
* Every external effect is injected so the same contract can be
|
|
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":"
|
|
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
|
|
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;
|
|
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,
|
|
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;
|
|
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) =>
|
|
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,
|
|
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":"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"}
|
|
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,
|
|
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
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/
|
|
29
|
-
* Every external effect is injected so the same contract can be
|
|
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
|
-
|
|
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
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
|
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
|
-
|
|
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',
|