@mojaloop/sdk-scheme-adapter 11.18.8
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/.env.example +140 -0
- package/.eslintignore +2 -0
- package/.eslintrc.json +30 -0
- package/.nvmrc +1 -0
- package/.versionrc +15 -0
- package/CHANGELOG.md +118 -0
- package/InboundServer/api.yaml +3594 -0
- package/InboundServer/api_template.yaml +69 -0
- package/InboundServer/handlers.js +940 -0
- package/InboundServer/index.js +205 -0
- package/InboundServer/middlewares.js +426 -0
- package/OAuthTestServer/index.js +66 -0
- package/OAuthTestServer/model.js +70 -0
- package/OutboundServer/api.yaml +2732 -0
- package/OutboundServer/api_interfaces/index.d.ts +117 -0
- package/OutboundServer/api_interfaces/openapi.d.ts +1475 -0
- package/OutboundServer/api_template/components/parameters/bulkQuoteId.yaml +9 -0
- package/OutboundServer/api_template/components/parameters/bulkTransferId.yaml +9 -0
- package/OutboundServer/api_template/components/parameters/requestToPayTransactionId.yaml +9 -0
- package/OutboundServer/api_template/components/parameters/transferId.yaml +9 -0
- package/OutboundServer/api_template/components/responses/accountsCreationCompleted.yaml +5 -0
- package/OutboundServer/api_template/components/responses/accountsCreationError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/accountsCreationTimeout.yaml +5 -0
- package/OutboundServer/api_template/components/responses/authorizationPostSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/authorizationsServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkQuoteBadRequest.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkQuoteServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkQuoteSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkQuoteTimeout.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkTransferBadRequest.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkTransferServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkTransferSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/bulkTransferTimeout.yaml +5 -0
- package/OutboundServer/api_template/components/responses/partiesByIdError404.yaml +9 -0
- package/OutboundServer/api_template/components/responses/partiesByIdSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/quotesPostSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/quotesServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/requestToPaySuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/requestToPayTransferBadRequest.yaml +5 -0
- package/OutboundServer/api_template/components/responses/requestToPayTransferSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/simpleTransfersPostSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/simpleTransfersServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/transferBadRequest.yaml +5 -0
- package/OutboundServer/api_template/components/responses/transferServerError.yaml +5 -0
- package/OutboundServer/api_template/components/responses/transferSuccess.yaml +5 -0
- package/OutboundServer/api_template/components/responses/transferTimeout.yaml +5 -0
- package/OutboundServer/api_template/components/schemas/accountCreationStatus.yaml +18 -0
- package/OutboundServer/api_template/components/schemas/accountsCreationState.yaml +4 -0
- package/OutboundServer/api_template/components/schemas/accountsRequest.yaml +20 -0
- package/OutboundServer/api_template/components/schemas/accountsResponse.yaml +15 -0
- package/OutboundServer/api_template/components/schemas/async2SyncCurrentState.yaml +5 -0
- package/OutboundServer/api_template/components/schemas/authorizationsPostRequest.yaml +15 -0
- package/OutboundServer/api_template/components/schemas/authorizationsPostResponse.yaml +19 -0
- package/OutboundServer/api_template/components/schemas/bulkQuoteErrorResponse.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/bulkQuoteRequest.yaml +26 -0
- package/OutboundServer/api_template/components/schemas/bulkQuoteResponse.yaml +21 -0
- package/OutboundServer/api_template/components/schemas/bulkQuoteStatus.yaml +4 -0
- package/OutboundServer/api_template/components/schemas/bulkQuoteStatusResponse.yaml +17 -0
- package/OutboundServer/api_template/components/schemas/bulkTransferErrorResponse.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/bulkTransferRequest.yaml +26 -0
- package/OutboundServer/api_template/components/schemas/bulkTransferResponse.yaml +16 -0
- package/OutboundServer/api_template/components/schemas/bulkTransferStatus.yaml +4 -0
- package/OutboundServer/api_template/components/schemas/bulkTransferStatusResponse.yaml +17 -0
- package/OutboundServer/api_template/components/schemas/errorAccountsResponse.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/errorAuthorizationsResponse.yaml +3 -0
- package/OutboundServer/api_template/components/schemas/errorQuotesResponse.yaml +9 -0
- package/OutboundServer/api_template/components/schemas/errorResponse.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/errorSimpleTransfersResponse.yaml +3 -0
- package/OutboundServer/api_template/components/schemas/errorTransferResponse.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/extensionListEmptiable.yaml +6 -0
- package/OutboundServer/api_template/components/schemas/individualQuote.yaml +32 -0
- package/OutboundServer/api_template/components/schemas/individualQuoteResult.yaml +28 -0
- package/OutboundServer/api_template/components/schemas/individualTransfer.yaml +32 -0
- package/OutboundServer/api_template/components/schemas/individualTransferFulfilment.yaml +13 -0
- package/OutboundServer/api_template/components/schemas/individualTransferResult.yaml +41 -0
- package/OutboundServer/api_template/components/schemas/mojaloopError.yaml +5 -0
- package/OutboundServer/api_template/components/schemas/mojaloopTransactionRequestState.yaml +2 -0
- package/OutboundServer/api_template/components/schemas/partiesByIdResponse.yaml +13 -0
- package/OutboundServer/api_template/components/schemas/quote.yaml +3 -0
- package/OutboundServer/api_template/components/schemas/quoteError.yaml +16 -0
- package/OutboundServer/api_template/components/schemas/quotesPostRequest.yaml +13 -0
- package/OutboundServer/api_template/components/schemas/quotesPostResponse.yaml +48 -0
- package/OutboundServer/api_template/components/schemas/requestToPayRequest.yaml +39 -0
- package/OutboundServer/api_template/components/schemas/requestToPayResponse.yaml +41 -0
- package/OutboundServer/api_template/components/schemas/requestToPayTransferRequest.yaml +42 -0
- package/OutboundServer/api_template/components/schemas/requestToPayTransferResponse.yaml +58 -0
- package/OutboundServer/api_template/components/schemas/simpleTransferServerError.yaml +5 -0
- package/OutboundServer/api_template/components/schemas/simpleTransfersPostRequest.yaml +12 -0
- package/OutboundServer/api_template/components/schemas/simpleTransfersPostResponse.yaml +11 -0
- package/OutboundServer/api_template/components/schemas/transactionType.yaml +4 -0
- package/OutboundServer/api_template/components/schemas/transferContinuationAcceptOTP.yaml +9 -0
- package/OutboundServer/api_template/components/schemas/transferContinuationAcceptParty.yaml +8 -0
- package/OutboundServer/api_template/components/schemas/transferContinuationAcceptQuote.yaml +9 -0
- package/OutboundServer/api_template/components/schemas/transferError.yaml +16 -0
- package/OutboundServer/api_template/components/schemas/transferFulfilment.yaml +3 -0
- package/OutboundServer/api_template/components/schemas/transferParty.yaml +40 -0
- package/OutboundServer/api_template/components/schemas/transferRequest.yaml +37 -0
- package/OutboundServer/api_template/components/schemas/transferResponse.yaml +58 -0
- package/OutboundServer/api_template/components/schemas/transferStatus.yaml +6 -0
- package/OutboundServer/api_template/components/schemas/transferStatusResponse.yaml +13 -0
- package/OutboundServer/api_template/health.yaml +12 -0
- package/OutboundServer/api_template/openapi.yaml +55 -0
- package/OutboundServer/api_template/paths/accounts.yaml +26 -0
- package/OutboundServer/api_template/paths/authorizations.yaml +19 -0
- package/OutboundServer/api_template/paths/bulkQuotes.yaml +23 -0
- package/OutboundServer/api_template/paths/bulkQuotes_bulkQuoteId.yaml +24 -0
- package/OutboundServer/api_template/paths/bulkTransfers.yaml +23 -0
- package/OutboundServer/api_template/paths/bulkTransfers_bulkTransferId.yaml +24 -0
- package/OutboundServer/api_template/paths/parties_Type_ID.yaml +20 -0
- package/OutboundServer/api_template/paths/parties_Type_ID_SubId.yaml +22 -0
- package/OutboundServer/api_template/paths/quotes.yaml +20 -0
- package/OutboundServer/api_template/paths/requestToPay.yaml +22 -0
- package/OutboundServer/api_template/paths/requestToPayTransfer.yaml +57 -0
- package/OutboundServer/api_template/paths/requestToPayTransfer_requestToPayTransactionId.yaml +34 -0
- package/OutboundServer/api_template/paths/simpleTransfers.yaml +19 -0
- package/OutboundServer/api_template/paths/transfers.yaml +55 -0
- package/OutboundServer/api_template/paths/transfers_transferId.yaml +58 -0
- package/OutboundServer/handlers.js +622 -0
- package/OutboundServer/index.js +137 -0
- package/OutboundServer/middlewares.js +67 -0
- package/TestServer/api.yaml +62 -0
- package/TestServer/handlers.js +63 -0
- package/TestServer/index.js +215 -0
- package/audit-resolve.json +65 -0
- package/babel.config.js +3 -0
- package/config.js +158 -0
- package/index.d.ts +1 -0
- package/index.js +149 -0
- package/jest.config.js +15 -0
- package/lib/api/index.js +12 -0
- package/lib/cache.js +352 -0
- package/lib/check.js +25 -0
- package/lib/model/AccountsModel.js +396 -0
- package/lib/model/Async2SyncModel.js +283 -0
- package/lib/model/AuthorizationsModel.js +86 -0
- package/lib/model/InboundTransfersModel.js +730 -0
- package/lib/model/OutboundBulkQuotesModel.js +485 -0
- package/lib/model/OutboundBulkTransfersModel.js +479 -0
- package/lib/model/OutboundRequestToPayModel.js +517 -0
- package/lib/model/OutboundRequestToPayTransferModel.js +893 -0
- package/lib/model/OutboundTransfersModel.js +823 -0
- package/lib/model/PartiesModel.js +70 -0
- package/lib/model/ProxyModel/MatchRules/Expression.js +48 -0
- package/lib/model/ProxyModel/MatchRules/Headers.js +65 -0
- package/lib/model/ProxyModel/MatchRules/MatchRule.js +27 -0
- package/lib/model/ProxyModel/MatchRules/Path.js +36 -0
- package/lib/model/ProxyModel/MatchRules/Query.js +65 -0
- package/lib/model/ProxyModel/MatchRules/index.js +19 -0
- package/lib/model/ProxyModel/Route.js +82 -0
- package/lib/model/ProxyModel/configSchema.json +118 -0
- package/lib/model/ProxyModel/index.js +138 -0
- package/lib/model/QuotesModel.js +94 -0
- package/lib/model/TransfersModel.js +81 -0
- package/lib/model/common/BackendError.js +26 -0
- package/lib/model/common/PersistentStateMachine.js +93 -0
- package/lib/model/common/index.js +18 -0
- package/lib/model/index.js +43 -0
- package/lib/model/lib/deferredJob.js +113 -0
- package/lib/model/lib/index.js +9 -0
- package/lib/model/lib/requests/backendRequests.js +227 -0
- package/lib/model/lib/requests/common.js +76 -0
- package/lib/model/lib/requests/index.js +19 -0
- package/lib/model/lib/shared.js +468 -0
- package/lib/randomphrase/index.js +21 -0
- package/lib/randomphrase/words.json +3397 -0
- package/lib/router.js +28 -0
- package/lib/validate.js +205 -0
- package/package.json +102 -0
- package/test/__mocks__/@mojaloop/sdk-standard-components.js +152 -0
- package/test/__mocks__/javascript-state-machine.js +21 -0
- package/test/__mocks__/redis.js +49 -0
- package/test/__mocks__/uuidv4.js +16 -0
- package/test/config/integration.env +136 -0
- package/test/integration/lib/Outbound/authorizations.test.js +58 -0
- package/test/integration/lib/Outbound/data/authorizationsPostRequest.json +43 -0
- package/test/integration/lib/Outbound/data/quotesPostRequest.json +52 -0
- package/test/integration/lib/Outbound/data/transfersPostRequest.json +24 -0
- package/test/integration/lib/Outbound/parties.test.js +28 -0
- package/test/integration/lib/Outbound/quotes.test.js +58 -0
- package/test/integration/lib/Outbound/simpleTransfers.test.js +67 -0
- package/test/integration/lib/cache.test.js +80 -0
- package/test/integration/testEnv.js +7 -0
- package/test/unit/InboundServer.test.js +443 -0
- package/test/unit/TestServer.test.js +394 -0
- package/test/unit/api/accounts/accounts.test.js +128 -0
- package/test/unit/api/accounts/data/postAccountsBody.json +7 -0
- package/test/unit/api/accounts/data/postAccountsErrorMojaloopResponse.json +25 -0
- package/test/unit/api/accounts/data/postAccountsErrorTimeoutResponse.json +19 -0
- package/test/unit/api/accounts/data/postAccountsSuccessResponse.json +17 -0
- package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError1.json +21 -0
- package/test/unit/api/accounts/data/postAccountsSuccessResponseWithError2.json +21 -0
- package/test/unit/api/accounts/utils.js +65 -0
- package/test/unit/api/proxy/data/proxyConfig.yaml +82 -0
- package/test/unit/api/proxy/data/requestBody.json +22 -0
- package/test/unit/api/proxy/data/requestHeaders.json +5 -0
- package/test/unit/api/proxy/data/requestQuery.json +6 -0
- package/test/unit/api/proxy/data/responseBody.json +21 -0
- package/test/unit/api/proxy/data/responseHeaders.json +5 -0
- package/test/unit/api/proxy/proxy.test.js +220 -0
- package/test/unit/api/proxy/utils.js +79 -0
- package/test/unit/api/transfers/data/getTransfersCommittedResponse.json +21 -0
- package/test/unit/api/transfers/data/getTransfersErrorNotFound.json +17 -0
- package/test/unit/api/transfers/data/postQuotesBody.json +52 -0
- package/test/unit/api/transfers/data/postTransfersBadBody.json +17 -0
- package/test/unit/api/transfers/data/postTransfersBody.json +24 -0
- package/test/unit/api/transfers/data/postTransfersErrorMojaloopResponse.json +53 -0
- package/test/unit/api/transfers/data/postTransfersErrorTimeoutResponse.json +47 -0
- package/test/unit/api/transfers/data/postTransfersSimpleBody.json +26 -0
- package/test/unit/api/transfers/data/postTransfersSuccessResponse.json +101 -0
- package/test/unit/api/transfers/data/putPartiesBody.json +20 -0
- package/test/unit/api/transfers/data/putQuotesBody.json +37 -0
- package/test/unit/api/transfers/data/putTransfersBody.json +17 -0
- package/test/unit/api/transfers/transfers.test.js +191 -0
- package/test/unit/api/transfers/utils.js +183 -0
- package/test/unit/api/utils.js +75 -0
- package/test/unit/config.test.js +119 -0
- package/test/unit/data/commonHttpHeaders.json +6 -0
- package/test/unit/data/defaultConfig.json +58 -0
- package/test/unit/data/postQuotesBody.json +52 -0
- package/test/unit/data/putParticipantsBody.json +12 -0
- package/test/unit/data/putPartiesBody.json +20 -0
- package/test/unit/data/testFile.json +29 -0
- package/test/unit/data/testFile.yaml +14 -0
- package/test/unit/inboundApi/data/mockArguments.json +117 -0
- package/test/unit/inboundApi/data/mockTransactionRequest.json +42 -0
- package/test/unit/inboundApi/handlers.test.js +799 -0
- package/test/unit/index.test.js +55 -0
- package/test/unit/lib/cache.test.js +146 -0
- package/test/unit/lib/model/AccountsModel.test.js +121 -0
- package/test/unit/lib/model/AuthorizationsModel.test.js +460 -0
- package/test/unit/lib/model/InboundTransfersModel.test.js +628 -0
- package/test/unit/lib/model/OutboundBulkQuotesModel.test.js +249 -0
- package/test/unit/lib/model/OutboundBulkTransfersModel.test.js +244 -0
- package/test/unit/lib/model/OutboundRequestToPayModel.test.js +166 -0
- package/test/unit/lib/model/OutboundRequestToPayTransferModel.test.js +245 -0
- package/test/unit/lib/model/OutboundTransfersModel.test.js +836 -0
- package/test/unit/lib/model/PartiesModel.test.js +468 -0
- package/test/unit/lib/model/QuotesModel.test.js +470 -0
- package/test/unit/lib/model/TransfersModel.test.js +474 -0
- package/test/unit/lib/model/common/PersistentStateMachine.test.js +179 -0
- package/test/unit/lib/model/data/authorizationsResponse.json +13 -0
- package/test/unit/lib/model/data/bulkQuoteRequest.json +27 -0
- package/test/unit/lib/model/data/bulkQuoteResponse.json +35 -0
- package/test/unit/lib/model/data/bulkTransferFulfil.json +13 -0
- package/test/unit/lib/model/data/bulkTransferRequest.json +29 -0
- package/test/unit/lib/model/data/defaultConfig.json +47 -0
- package/test/unit/lib/model/data/getBulkTransfersBackendResponse.json +42 -0
- package/test/unit/lib/model/data/getBulkTransfersMojaloopResponse.json +22 -0
- package/test/unit/lib/model/data/getTransfersBackendResponse.json +34 -0
- package/test/unit/lib/model/data/getTransfersMojaloopResponse.json +17 -0
- package/test/unit/lib/model/data/mockArguments.json +131 -0
- package/test/unit/lib/model/data/mockTxnRequestsArguments.json +63 -0
- package/test/unit/lib/model/data/notificationToPayee.json +10 -0
- package/test/unit/lib/model/data/payeeParty.json +16 -0
- package/test/unit/lib/model/data/putAuthorizationsResponse.json +10 -0
- package/test/unit/lib/model/data/putQuotesResponse.json +33 -0
- package/test/unit/lib/model/data/putTransfersResponse.json +5 -0
- package/test/unit/lib/model/data/quoteResponse.json +31 -0
- package/test/unit/lib/model/data/requestToPayRequest.json +20 -0
- package/test/unit/lib/model/data/requestToPayTransferRequest.json +27 -0
- package/test/unit/lib/model/data/transactionRequestResponse.json +18 -0
- package/test/unit/lib/model/data/transferFulfil.json +8 -0
- package/test/unit/lib/model/data/transferRequest.json +26 -0
- package/test/unit/lib/model/mockedLibRequests.js +74 -0
- package/test/unit/mockLogger.js +39 -0
- package/test/unit/outboundApi/data/bulkQuoteRequest.json +28 -0
- package/test/unit/outboundApi/data/bulkTransferRequest.json +28 -0
- package/test/unit/outboundApi/data/mockBulkQuoteError.json +45 -0
- package/test/unit/outboundApi/data/mockBulkTransferError.json +48 -0
- package/test/unit/outboundApi/data/mockError.json +41 -0
- package/test/unit/outboundApi/data/mockGetPartiesError.json +4 -0
- package/test/unit/outboundApi/data/mockRequestToPayError.json +32 -0
- package/test/unit/outboundApi/data/mockRequestToPayTransferError.json +39 -0
- package/test/unit/outboundApi/data/requestToPay.json +21 -0
- package/test/unit/outboundApi/data/requestToPayTransferRequest.json +20 -0
- package/test/unit/outboundApi/data/transferRequest.json +21 -0
- package/test/unit/outboundApi/handlers.test.js +986 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
/**************************************************************************
|
|
2
|
+
* (C) Copyright ModusBox Inc. 2019 - All rights reserved. *
|
|
3
|
+
* *
|
|
4
|
+
* This file is made available under the terms of the license agreement *
|
|
5
|
+
* specified in the corresponding source code repository. *
|
|
6
|
+
* *
|
|
7
|
+
* ORIGINAL AUTHOR: *
|
|
8
|
+
* Murthy Kakarlamudi - murthy@modusbox.com *
|
|
9
|
+
**************************************************************************/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const util = require('util');
|
|
14
|
+
const { uuid } = require('uuidv4');
|
|
15
|
+
const StateMachine = require('javascript-state-machine');
|
|
16
|
+
const { MojaloopRequests } = require('@mojaloop/sdk-standard-components');
|
|
17
|
+
const { BackendError } = require('./common');
|
|
18
|
+
const PartiesModel = require('./PartiesModel');
|
|
19
|
+
|
|
20
|
+
const transferStateEnum = {
|
|
21
|
+
'WAITING_FOR_PARTY_ACCEPTANCE': 'WAITING_FOR_PARTY_ACCEPTANCE',
|
|
22
|
+
'WAITING_FOR_QUOTE_ACCEPTANCE': 'WAITING_FOR_QUOTE_ACCEPTANCE',
|
|
23
|
+
'ERROR_OCCURRED': 'ERROR_OCCURRED',
|
|
24
|
+
'COMPLETED': 'COMPLETED',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
class OutboundRequestToPayModel {
|
|
28
|
+
|
|
29
|
+
constructor(config) {
|
|
30
|
+
this._cache = config.cache;
|
|
31
|
+
this._logger = config.logger;
|
|
32
|
+
this._requestProcessingTimeoutSeconds = config.requestProcessingTimeoutSeconds;
|
|
33
|
+
this._dfspId = config.dfspId;
|
|
34
|
+
this._expirySeconds = config.expirySeconds;
|
|
35
|
+
this._autoAcceptParty = config.autoAcceptParty;
|
|
36
|
+
|
|
37
|
+
this._requests = new MojaloopRequests({
|
|
38
|
+
logger: this._logger,
|
|
39
|
+
peerEndpoint: config.peerEndpoint,
|
|
40
|
+
alsEndpoint: config.alsEndpoint,
|
|
41
|
+
dfspId: config.dfspId,
|
|
42
|
+
tls: config.tls,
|
|
43
|
+
jwsSign: config.jwsSign,
|
|
44
|
+
jwsSignPutParties: config.jwsSignPutParties,
|
|
45
|
+
jwsSigningKey: config.jwsSigningKey,
|
|
46
|
+
wso2: config.wso2,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Initializes the request to pay model
|
|
52
|
+
*
|
|
53
|
+
* @param data {object} - The inbound API POST /requestToPay request body
|
|
54
|
+
*/
|
|
55
|
+
async initialize(data) {
|
|
56
|
+
this.data = data;
|
|
57
|
+
|
|
58
|
+
// add a transactionRequestId if one is not present e.g. on first submission
|
|
59
|
+
if(!this.data.hasOwnProperty('transactionRequestId')) {
|
|
60
|
+
this.data.transactionRequestId = uuid();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// initialize the transfer state machine to its starting state
|
|
64
|
+
if(!this.data.hasOwnProperty('currentState')) {
|
|
65
|
+
this.data.currentState = 'start';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//Set fsp id in the from section of the request that gets sent back in the response
|
|
69
|
+
this.data.from.fspId = this._dfspId;
|
|
70
|
+
|
|
71
|
+
this._initStateMachine(this.data.currentState);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Initializes the internal state machine object
|
|
76
|
+
*/
|
|
77
|
+
_initStateMachine (initState) {
|
|
78
|
+
this.stateMachine = new StateMachine({
|
|
79
|
+
init: initState,
|
|
80
|
+
transitions: [
|
|
81
|
+
{ name: 'resolvePayee', from: 'start', to: 'payeeResolved' },
|
|
82
|
+
{ name: 'executeTransactionRequest', from: 'payeeResolved', to: 'succeeded' },
|
|
83
|
+
{ name: 'error', from: '*', to: 'errored' },
|
|
84
|
+
],
|
|
85
|
+
methods: {
|
|
86
|
+
onTransition: this._handleTransition.bind(this),
|
|
87
|
+
onAfterTransition: this._afterTransition.bind(this),
|
|
88
|
+
onPendingTransition: (transition, from, to) => {
|
|
89
|
+
// allow transitions to 'error' state while other transitions are in progress
|
|
90
|
+
if(transition !== 'error') {
|
|
91
|
+
throw new Error(`Transition requested while another transition is in progress: ${transition} from: ${from} to: ${to}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return this.stateMachine[initState];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Handles state machine transitions
|
|
102
|
+
*/
|
|
103
|
+
async _handleTransition(lifecycle, ...args) {
|
|
104
|
+
this._logger.log(`Request To Pay ${this.data.transactionRequestId} is transitioning from ${lifecycle.from} to ${lifecycle.to} in response to ${lifecycle.transition}`);
|
|
105
|
+
|
|
106
|
+
switch(lifecycle.transition) {
|
|
107
|
+
case 'init':
|
|
108
|
+
// init, just allow the fsm to start
|
|
109
|
+
return;
|
|
110
|
+
|
|
111
|
+
case 'resolvePayee':
|
|
112
|
+
// resolve the payee
|
|
113
|
+
return this._resolvePayee();
|
|
114
|
+
|
|
115
|
+
case 'executeTransactionRequest':
|
|
116
|
+
// call request to pay
|
|
117
|
+
return this._executeTransactionRequest();
|
|
118
|
+
|
|
119
|
+
case 'error':
|
|
120
|
+
this._logger.log(`State machine is erroring with error: ${util.inspect(args)}`);
|
|
121
|
+
this.data.lastError = args[0] || new Error('unspecified error');
|
|
122
|
+
break;
|
|
123
|
+
|
|
124
|
+
default:
|
|
125
|
+
throw new Error(`Unhandled state transition for transfer ${this.data.transferId}: ${util.inspect(args)}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Updates the internal state representation to reflect that of the state machine itself
|
|
131
|
+
*/
|
|
132
|
+
_afterTransition() {
|
|
133
|
+
this._logger.log(`State machine transitioned: ${this.data.currentState} -> ${this.stateMachine.state}`);
|
|
134
|
+
this.data.currentState = this.stateMachine.state;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Resolves the payee.
|
|
139
|
+
* Starts the payee resolution process by sending a GET /parties request to the switch;
|
|
140
|
+
* then waits for a notification from the cache that the payee has been resolved.
|
|
141
|
+
*/
|
|
142
|
+
async _resolvePayee() {
|
|
143
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
144
|
+
return new Promise(async (resolve, reject) => {
|
|
145
|
+
// listen for resolution events on the payee idType and idValue
|
|
146
|
+
const payeeKey = PartiesModel.channelName({
|
|
147
|
+
type: this.data.to.idType,
|
|
148
|
+
id: this.data.to.idValue,
|
|
149
|
+
subId: this.data.to.idSubValue
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// hook up a subscriber to handle response messages
|
|
153
|
+
const subId = await this._cache.subscribe(payeeKey, (cn, msg, subId) => {
|
|
154
|
+
try {
|
|
155
|
+
let payee = JSON.parse(msg);
|
|
156
|
+
|
|
157
|
+
if(payee.errorInformation) {
|
|
158
|
+
// this is an error response to our GET /parties request
|
|
159
|
+
const err = new BackendError(`Got an error response resolving party: ${util.inspect(payee)}`, 500);
|
|
160
|
+
err.mojaloopError = payee;
|
|
161
|
+
|
|
162
|
+
// cancel the timeout handler
|
|
163
|
+
clearTimeout(timeout);
|
|
164
|
+
return reject(err);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if(!payee.party) {
|
|
168
|
+
// we should never get a non-error response without a party, but just in case...
|
|
169
|
+
// cancel the timeout handler
|
|
170
|
+
clearTimeout(timeout);
|
|
171
|
+
return reject(new Error(`Resolved payee has no party object: ${util.inspect(payee)}`));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
payee = payee.party;
|
|
175
|
+
|
|
176
|
+
// cancel the timeout handler
|
|
177
|
+
clearTimeout(timeout);
|
|
178
|
+
|
|
179
|
+
this._logger.push({ payee }).log('Payee resolved');
|
|
180
|
+
|
|
181
|
+
// stop listening for payee resolution messages
|
|
182
|
+
// no need to await for the unsubscribe to complete.
|
|
183
|
+
// we dont really care if the unsubscribe fails but we should log it regardless
|
|
184
|
+
this._cache.unsubscribe(payeeKey, subId).catch(e => {
|
|
185
|
+
this._logger.log(`Error unsubscribing (in callback) ${payeeKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// check we got the right payee and info we need
|
|
189
|
+
if(payee.partyIdInfo.partyIdType !== this.data.to.idType) {
|
|
190
|
+
const err = new Error(`Expecting resolved payee party IdType to be ${this.data.to.idType} but got ${payee.partyIdInfo.partyIdType}`);
|
|
191
|
+
return reject(err);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if(payee.partyIdInfo.partyIdentifier !== this.data.to.idValue) {
|
|
195
|
+
const err = new Error(`Expecting resolved payee party identifier to be ${this.data.to.idValue} but got ${payee.partyIdInfo.partyIdentifier}`);
|
|
196
|
+
return reject(err);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if(payee.partyIdInfo.partySubIdOrType !== this.data.to.idSubValue) {
|
|
200
|
+
const err = new Error(`Expecting resolved payee party subTypeId to be ${this.data.to.idSubValue} but got ${payee.partyIdInfo.partySubIdOrType}`);
|
|
201
|
+
return reject(err);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if(!payee.partyIdInfo.fspId) {
|
|
205
|
+
const err = new Error(`Expecting resolved payee party to have an FSPID: ${util.inspect(payee.partyIdInfo)}`);
|
|
206
|
+
return reject(err);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// now we got the payee, add the details to our data so we can use it
|
|
210
|
+
// in the quote request
|
|
211
|
+
this.data.to.fspId = payee.partyIdInfo.fspId;
|
|
212
|
+
|
|
213
|
+
if(payee.personalInfo) {
|
|
214
|
+
if(payee.personalInfo.complexName) {
|
|
215
|
+
this.data.to.firstName = payee.personalInfo.complexName.firstName || this.data.to.firstName;
|
|
216
|
+
this.data.to.middleName = payee.personalInfo.complexName.middleName || this.data.to.middleName;
|
|
217
|
+
this.data.to.lastName = payee.personalInfo.complexName.lastName || this.data.to.lastName;
|
|
218
|
+
}
|
|
219
|
+
this.data.to.dateOfBirth = payee.personalInfo.dateOfBirth;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return resolve(payee);
|
|
223
|
+
}
|
|
224
|
+
catch(err) {
|
|
225
|
+
return reject(err);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// set up a timeout for the resolution
|
|
230
|
+
const timeout = setTimeout(() => {
|
|
231
|
+
const err = new BackendError(`Timeout resolving payee for transfer ${this.data.transferId}`, 504);
|
|
232
|
+
|
|
233
|
+
// we dont really care if the unsubscribe fails but we should log it regardless
|
|
234
|
+
this._cache.unsubscribe(payeeKey, subId).catch(e => {
|
|
235
|
+
this._logger.log(`Error unsubscribing (in timeout handler) ${payeeKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return reject(err);
|
|
239
|
+
}, this._requestProcessingTimeoutSeconds * 1000);
|
|
240
|
+
|
|
241
|
+
// now we have a timeout handler and a cache subscriber hooked up we can fire off
|
|
242
|
+
// a GET /parties request to the switch
|
|
243
|
+
try {
|
|
244
|
+
const res = await this._requests.getParties(this.data.to.idType, this.data.to.idValue,
|
|
245
|
+
this.data.to.idSubValue);
|
|
246
|
+
this._logger.push({ peer: res }).log('Party lookup sent to peer');
|
|
247
|
+
}
|
|
248
|
+
catch(err) {
|
|
249
|
+
// cancel the timout and unsubscribe before rejecting the promise
|
|
250
|
+
clearTimeout(timeout);
|
|
251
|
+
|
|
252
|
+
// we dont really care if the unsubscribe fails but we should log it regardless
|
|
253
|
+
this._cache.unsubscribe(payeeKey, subId).catch(e => {
|
|
254
|
+
this._logger.log(`Error unsubscribing ${payeeKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return reject(err);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async _executeTransactionRequest() {
|
|
263
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
264
|
+
return new Promise(async (resolve, reject) => {
|
|
265
|
+
// create a transfer prepare request
|
|
266
|
+
const transactionRequest = this._buildTransactionRequest();
|
|
267
|
+
|
|
268
|
+
// listen for events on the transactionRequestId
|
|
269
|
+
const transactionRequestKey = `txnreq_${this.data.transactionRequestId}`;
|
|
270
|
+
|
|
271
|
+
const subId = await this._cache.subscribe(transactionRequestKey, async (cn, msg, subId) => {
|
|
272
|
+
try {
|
|
273
|
+
let error;
|
|
274
|
+
let message = JSON.parse(msg);
|
|
275
|
+
|
|
276
|
+
// if (message.type === 'transactionRequestFail') {
|
|
277
|
+
// error = new BackendError(`Got an error response processing transaction request: ${util.inspect(message.data)}`, 500);
|
|
278
|
+
// error.mojaloopError = message.data;
|
|
279
|
+
// } else {
|
|
280
|
+
// this._logger.push({ message }).log(`Ignoring cache notification for transfer ${transactionRequestKey}. Uknokwn message type ${message.type}.`);
|
|
281
|
+
// return;
|
|
282
|
+
// }
|
|
283
|
+
|
|
284
|
+
// cancel the timeout handler
|
|
285
|
+
clearTimeout(timeout);
|
|
286
|
+
|
|
287
|
+
// stop listening for transfer fulfil messages
|
|
288
|
+
this._cache.unsubscribe(transactionRequestKey, subId).catch(e => {
|
|
289
|
+
this._logger.log(`Error unsubscribing (in callback) ${transactionRequestKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
if (error) {
|
|
293
|
+
return reject(error);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const transactionRequestResponse = message.data;
|
|
297
|
+
this._logger.push({ transactionRequestResponse }).log('Transaction Request Response received');
|
|
298
|
+
this.data.requestToPayState = transactionRequestResponse.transactionRequestState;
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
return resolve(transactionRequestResponse);
|
|
302
|
+
}
|
|
303
|
+
catch(err) {
|
|
304
|
+
return reject(err);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// set up a timeout for the request
|
|
309
|
+
const timeout = setTimeout(() => {
|
|
310
|
+
const err = new BackendError(`Timeout waiting for fulfil for transfer ${this.data.transferId}`, 504);
|
|
311
|
+
|
|
312
|
+
// we dont really care if the unsubscribe fails but we should log it regardless
|
|
313
|
+
this._cache.unsubscribe(transactionRequestKey, subId).catch(e => {
|
|
314
|
+
this._logger.log(`Error unsubscribing (in timeout handler) ${transactionRequestKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
return reject(err);
|
|
318
|
+
}, this._requestProcessingTimeoutSeconds * 1000);
|
|
319
|
+
|
|
320
|
+
// now we have a timeout handler and a cache subscriber hooked up we can fire off
|
|
321
|
+
// a POST /transfers request to the switch
|
|
322
|
+
try {
|
|
323
|
+
const res = await this._requests.postTransactionRequests(transactionRequest, this.data.to.fspId);
|
|
324
|
+
this._logger.push({ res }).log('Transfer prepare sent to peer');
|
|
325
|
+
}
|
|
326
|
+
catch(err) {
|
|
327
|
+
// cancel the timout and unsubscribe before rejecting the promise
|
|
328
|
+
clearTimeout(timeout);
|
|
329
|
+
|
|
330
|
+
// we dont really care if the unsubscribe fails but we should log it regardless
|
|
331
|
+
this._cache.unsubscribe(transactionRequestKey, subId).catch(e => {
|
|
332
|
+
this._logger.log(`Error unsubscribing (in error handler) ${transactionRequestKey} ${subId}: ${e.stack || util.inspect(e)}`);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
return reject(err);
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Builds a transaction request payload from current state
|
|
342
|
+
*
|
|
343
|
+
* @returns {object} - the transaction request payload
|
|
344
|
+
*/
|
|
345
|
+
_buildTransactionRequest() {
|
|
346
|
+
let transactionRequest = {
|
|
347
|
+
transactionRequestId: this.data.transactionRequestId,
|
|
348
|
+
payer: {
|
|
349
|
+
partyIdType: this.data.from.idType,
|
|
350
|
+
partyIdentifier: this.data.from.idValue,
|
|
351
|
+
fspId: this._dfspId
|
|
352
|
+
},
|
|
353
|
+
payee: {
|
|
354
|
+
partyIdInfo: {
|
|
355
|
+
partyIdType: this.data.to.idType,
|
|
356
|
+
partyIdentifier: this.data.to.idValue,
|
|
357
|
+
fspId: this.data.to.fspId,
|
|
358
|
+
},
|
|
359
|
+
personalInfo: {
|
|
360
|
+
complexName: {
|
|
361
|
+
firstName: this.data.to.firstName,
|
|
362
|
+
middleName: this.data.to.middleName,
|
|
363
|
+
lastName: this.data.to.lastName
|
|
364
|
+
},
|
|
365
|
+
dateOfBirth: this.data.to.dateOfBirth
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
amount: {
|
|
369
|
+
currency: this.data.currency,
|
|
370
|
+
amount: this.data.amount
|
|
371
|
+
},
|
|
372
|
+
transactionType: {
|
|
373
|
+
scenario: this.data.scenario,
|
|
374
|
+
initiator: this.data.initiator,
|
|
375
|
+
initiatorType: this.data.initiatorType
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// add extensions list if provided
|
|
380
|
+
// if(this.data.transferRequestExtensions && this.data.transferRequestExtensions.length > 0) {
|
|
381
|
+
// prepare.extensionList = {
|
|
382
|
+
// extension: this.data.transferRequestExtensions
|
|
383
|
+
// };
|
|
384
|
+
// }
|
|
385
|
+
|
|
386
|
+
return transactionRequest;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Loads a transfer model from cache for resumption of the transfer process
|
|
391
|
+
*
|
|
392
|
+
* @param transferId {string} - UUID transferId of the model to load from cache
|
|
393
|
+
*/
|
|
394
|
+
async load(transactionRequestId) {
|
|
395
|
+
try {
|
|
396
|
+
const data = await this._cache.get(`txnReqModel_${transactionRequestId}`);
|
|
397
|
+
if(!data) {
|
|
398
|
+
throw new Error(`No cached data found for transactionRequestId: ${transactionRequestId}`);
|
|
399
|
+
}
|
|
400
|
+
await this.initialize(data);
|
|
401
|
+
this._logger.push({ cache: this.data }).log('TransactionRequest model loaded from cached state');
|
|
402
|
+
}
|
|
403
|
+
catch(err) {
|
|
404
|
+
this._logger.push({ err }).log('Error loading transfer model');
|
|
405
|
+
throw err;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Returns a promise that resolves when the state machine has reached a terminal state
|
|
411
|
+
*/
|
|
412
|
+
async run() {
|
|
413
|
+
try {
|
|
414
|
+
// run transitions based on incoming state
|
|
415
|
+
switch(this.data.currentState) {
|
|
416
|
+
case 'start':
|
|
417
|
+
// next transition is to resolvePayee
|
|
418
|
+
await this.stateMachine.resolvePayee();
|
|
419
|
+
this._logger.log(`Payee resolved for transfer ${this.data.transferId}`);
|
|
420
|
+
if(this.stateMachine.state === 'payeeResolved' && !this._autoAcceptParty) {
|
|
421
|
+
//we break execution here and return the resolved party details to allow asynchronous accept or reject
|
|
422
|
+
//of the resolved party
|
|
423
|
+
await this._save();
|
|
424
|
+
return this.getResponse();
|
|
425
|
+
}
|
|
426
|
+
break;
|
|
427
|
+
|
|
428
|
+
case 'payeeResolved':
|
|
429
|
+
// next transition is to requestQuote
|
|
430
|
+
await this.stateMachine.executeTransactionRequest();
|
|
431
|
+
this._logger.log(`Transaction Request for ${this.data.transactionRequestId} has been completed`);
|
|
432
|
+
break;
|
|
433
|
+
|
|
434
|
+
case 'succeeded':
|
|
435
|
+
// all steps complete so return
|
|
436
|
+
this._logger.log('Transaction Request completed successfully');
|
|
437
|
+
await this._save();
|
|
438
|
+
return this.getResponse();
|
|
439
|
+
|
|
440
|
+
case 'errored':
|
|
441
|
+
// stopped in errored state
|
|
442
|
+
this._logger.log('State machine in errored state');
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// now call ourslves recursively to deal with the next transition
|
|
447
|
+
this._logger.log(`Transfer model state machine transition completed in state: ${this.stateMachine.state}. Recusring to handle next transition.`);
|
|
448
|
+
return this.run();
|
|
449
|
+
}
|
|
450
|
+
catch(err) {
|
|
451
|
+
this._logger.log(`Error running transfer model: ${util.inspect(err)}`);
|
|
452
|
+
|
|
453
|
+
// as this function is recursive, we dont want to error the state machine multiple times
|
|
454
|
+
if(this.data.currentState !== 'errored') {
|
|
455
|
+
// err should not have a transferState property here!
|
|
456
|
+
if(err.transferState) {
|
|
457
|
+
this._logger.log(`State machine is broken: ${util.inspect(err)}`);
|
|
458
|
+
}
|
|
459
|
+
// transition to errored state
|
|
460
|
+
await this.stateMachine.error(err);
|
|
461
|
+
|
|
462
|
+
// avoid circular ref between transferState.lastError and err
|
|
463
|
+
err.transferState = JSON.parse(JSON.stringify(this.getResponse()));
|
|
464
|
+
}
|
|
465
|
+
throw err;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Returns an object representing the final state of the transfer suitable for the outbound API
|
|
471
|
+
*
|
|
472
|
+
* @returns {object} - Response representing the result of the transfer process
|
|
473
|
+
*/
|
|
474
|
+
getResponse() {
|
|
475
|
+
// we want to project some of our internal state into a more useful
|
|
476
|
+
// representation to return to the SDK API consumer
|
|
477
|
+
let resp = { ...this.data };
|
|
478
|
+
|
|
479
|
+
switch(this.data.currentState) {
|
|
480
|
+
case 'payeeResolved':
|
|
481
|
+
resp.currentState = transferStateEnum.WAITING_FOR_PARTY_ACCEPTANCE;
|
|
482
|
+
break;
|
|
483
|
+
|
|
484
|
+
case 'succeeded':
|
|
485
|
+
resp.currentState = transferStateEnum.COMPLETED;
|
|
486
|
+
break;
|
|
487
|
+
|
|
488
|
+
case 'errored':
|
|
489
|
+
resp.currentState = transferStateEnum.ERROR_OCCURRED;
|
|
490
|
+
break;
|
|
491
|
+
|
|
492
|
+
default:
|
|
493
|
+
this._logger.log(`Transaction Request model response being returned from an unexpected state: ${this.data.currentState}. Returning ERROR_OCCURRED state`);
|
|
494
|
+
resp.currentState = transferStateEnum.ERROR_OCCURRED;
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return resp;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Persists the model state to cache for reinstantiation at a later point
|
|
503
|
+
*/
|
|
504
|
+
async _save() {
|
|
505
|
+
try {
|
|
506
|
+
this.data.currentState = this.stateMachine.state;
|
|
507
|
+
const res = await this._cache.set(`txnReqModel_${this.data.transactionRequestId}`, this.data);
|
|
508
|
+
this._logger.push({ res }).log('Persisted transaction request model in cache');
|
|
509
|
+
}
|
|
510
|
+
catch(err) {
|
|
511
|
+
this._logger.push({ err }).log('Error saving transfer model');
|
|
512
|
+
throw err;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
module.exports = OutboundRequestToPayModel;
|