account-lookup-service 17.7.0-snapshot.2 → 17.7.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/CHANGELOG.md +7 -0
- package/package.json +6 -9
- package/src/constants.js +2 -34
- package/src/domain/parties/deps.js +3 -4
- package/src/domain/parties/getPartiesByTypeAndID.js +13 -9
- package/src/domain/parties/partiesUtils.js +34 -4
- package/src/domain/parties/putParties.js +71 -26
- package/src/domain/parties/services/BasePartiesService.js +15 -137
- package/src/domain/parties/services/GetPartiesService.js +164 -190
- package/src/domain/parties/services/PutPartiesErrorService.js +27 -50
- package/src/domain/parties/services/PutPartiesService.js +33 -51
- package/src/domain/timeout/index.js +1 -11
- package/src/handlers/TimeoutHandler.js +2 -2
- package/src/lib/util.js +3 -11
- package/test/fixtures/index.js +0 -38
- package/test/unit/domain/parties/parties.test.js +18 -26
- package/test/unit/domain/parties/{services/BasePartiesService.test.js → utils.test.js} +34 -33
- package/test/unit/domain/timeout/index.test.js +5 -5
- package/test/util/index.js +6 -5
- package/test/unit/domain/parties/partiesUtils.test.js +0 -51
- package/test/unit/domain/parties/services/GetPartiesService.test.js +0 -222
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +0 -49
- package/test/unit/domain/parties/services/deps.js +0 -49
- package/test/util/mockDeps.js +0 -52
@@ -32,82 +32,64 @@ const BasePartiesService = require('./BasePartiesService')
|
|
32
32
|
const { RestMethods } = BasePartiesService.enums()
|
33
33
|
|
34
34
|
class PutPartiesService extends BasePartiesService {
|
35
|
-
async handleRequest () {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
const { source, proxy, proxyEnabled } = this.state
|
49
|
-
const log = this.log.child({ source, proxy, method: 'validateSourceParticipant' })
|
50
|
-
this.stepInProgress('validateSourceParticipant-1')
|
51
|
-
|
52
|
-
const schemeParticipant = await super.validateParticipant(source)
|
53
|
-
if (!schemeParticipant) {
|
54
|
-
if (!proxyEnabled || !proxy) {
|
55
|
-
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.sourceFspNotFound, log)
|
35
|
+
// async handleRequest () {
|
36
|
+
// // todo: add impl.
|
37
|
+
// }
|
38
|
+
|
39
|
+
async validateSourceParticipant ({ source, proxy }) {
|
40
|
+
this.deps.stepState.inProgress('validateSourceParticipant-1')
|
41
|
+
const requesterParticipant = await super.validateParticipant(source)
|
42
|
+
|
43
|
+
if (!requesterParticipant) {
|
44
|
+
if (!this.proxyEnabled || !proxy) {
|
45
|
+
const errMessage = ERROR_MESSAGES.sourceFspNotFound
|
46
|
+
this.log.warn(`${errMessage} and no proxy`, { source })
|
47
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
56
48
|
}
|
57
|
-
|
58
49
|
const isCached = await this.deps.proxyCache.addDfspIdToProxyMapping(source, proxy)
|
59
50
|
if (!isCached) {
|
60
|
-
|
51
|
+
const errMessage = 'failed to addDfspIdToProxyMapping'
|
52
|
+
this.log.warn(errMessage, { source, proxy })
|
53
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
61
54
|
}
|
62
55
|
|
63
|
-
log.info('addDfspIdToProxyMapping is done', { source, proxy })
|
56
|
+
this.log.info('addDfspIdToProxyMapping is done', { source, proxy })
|
64
57
|
}
|
65
58
|
}
|
66
59
|
|
67
|
-
async checkProxySuccessResponse () {
|
68
|
-
if (this.
|
69
|
-
this.
|
70
|
-
const { headers, params } = this.inputs
|
71
|
-
const { destination, source } = this.state
|
60
|
+
async checkProxySuccessResponse ({ destination, source, headers, params }) {
|
61
|
+
if (this.proxyEnabled) {
|
62
|
+
this.deps.stepState.inProgress('checkProxySuccessResponse-2')
|
72
63
|
const alsReq = this.deps.partiesUtils.alsRequestDto(destination, params)
|
73
64
|
|
74
65
|
const isExists = await this.deps.proxyCache.receivedSuccessResponse(alsReq)
|
75
|
-
if (
|
76
|
-
this.log.verbose('NOT inter-scheme receivedSuccessResponse case')
|
77
|
-
await this.removeProxyGetPartiesTimeout(alsReq)
|
78
|
-
return
|
79
|
-
}
|
80
|
-
|
81
|
-
const schemeParticipant = await super.validateParticipant(destination)
|
82
|
-
if (schemeParticipant) {
|
66
|
+
if (isExists) {
|
83
67
|
await this.#updateOracleWithParticipantMapping({ source, headers, params })
|
68
|
+
return
|
84
69
|
}
|
70
|
+
this.log.warn('destination is NOT in scheme, and no cached sendToProxiesList', { destination, alsReq })
|
71
|
+
// todo: think, if we need to throw an error here
|
85
72
|
}
|
86
73
|
}
|
87
74
|
|
88
|
-
async identifyDestinationForSuccessCallback () {
|
89
|
-
|
90
|
-
this.stepInProgress('identifyDestinationForSuccessCallback')
|
75
|
+
async identifyDestinationForSuccessCallback (destination) {
|
76
|
+
this.deps.stepState.inProgress('validateDestinationParticipant-4')
|
91
77
|
const destinationParticipant = await super.validateParticipant(destination)
|
92
78
|
if (destinationParticipant) {
|
93
|
-
|
94
|
-
return
|
79
|
+
return destinationParticipant.name
|
95
80
|
}
|
96
81
|
|
97
|
-
const proxyName = this.
|
82
|
+
const proxyName = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
98
83
|
if (!proxyName) {
|
99
84
|
const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
|
100
85
|
this.log.warn(`${errMessage} and no proxy`, { destination })
|
101
86
|
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR, errMessage)
|
102
87
|
}
|
103
|
-
|
104
|
-
this.state.requester = proxyName
|
88
|
+
return proxyName
|
105
89
|
}
|
106
90
|
|
107
|
-
async sendSuccessCallback () {
|
108
|
-
|
109
|
-
const sendTo = this.state.requester
|
110
|
-
this.stepInProgress('sendSuccessCallback')
|
91
|
+
async sendSuccessCallback ({ sendTo, headers, params, dataUri }) {
|
92
|
+
this.deps.stepState.inProgress('#sendSuccessCallback-6')
|
111
93
|
const payload = PutPartiesService.decodeDataUriPayload(dataUri)
|
112
94
|
const callbackEndpointType = this.deps.partiesUtils.putPartyCbType(params.SubId)
|
113
95
|
const options = this.deps.partiesUtils.partiesRequestOptionsDto(params)
|
@@ -115,11 +97,11 @@ class PutPartiesService extends BasePartiesService {
|
|
115
97
|
await this.deps.participant.sendRequest(
|
116
98
|
headers, sendTo, callbackEndpointType, RestMethods.PUT, payload, options
|
117
99
|
)
|
118
|
-
this.log.verbose('sendSuccessCallback is
|
100
|
+
this.log.verbose('sendSuccessCallback is done', { sendTo, payload })
|
119
101
|
}
|
120
102
|
|
121
103
|
async #updateOracleWithParticipantMapping ({ source, headers, params }) {
|
122
|
-
this.
|
104
|
+
this.deps.stepState.inProgress('#updateOracleWithParticipantMapping-3')
|
123
105
|
const mappingPayload = {
|
124
106
|
fspId: source
|
125
107
|
}
|
@@ -52,10 +52,6 @@ const timeoutInterschemePartiesLookups = async ({ proxyCache, batchSize }) => {
|
|
52
52
|
return proxyCache.processExpiredAlsKeys(sendTimeoutCallback, batchSize)
|
53
53
|
}
|
54
54
|
|
55
|
-
const timeoutProxyGetPartiesLookups = async ({ proxyCache, batchSize }) => {
|
56
|
-
return proxyCache.processExpiredProxyGetPartiesKeys(sendTimeoutCallback, batchSize)
|
57
|
-
}
|
58
|
-
|
59
55
|
const sendTimeoutCallback = async (cacheKey) => {
|
60
56
|
const histTimerEnd = Metrics.getHistogram(
|
61
57
|
'eg_timeoutInterschemePartiesLookups',
|
@@ -63,7 +59,7 @@ const sendTimeoutCallback = async (cacheKey) => {
|
|
63
59
|
['success']
|
64
60
|
).startTimer()
|
65
61
|
let step
|
66
|
-
const [destination, partyType, partyId] =
|
62
|
+
const [, destination, partyType, partyId] = cacheKey.split(':')
|
67
63
|
const { errorInformation, params, headers, endpointType, span } = await timeoutCallbackDto({ destination, partyId, partyType })
|
68
64
|
logger.debug('sendTimeoutCallback details:', { destination, partyType, partyId, cacheKey })
|
69
65
|
|
@@ -107,13 +103,7 @@ const finishSpan = async (span, err) => {
|
|
107
103
|
}
|
108
104
|
}
|
109
105
|
|
110
|
-
const parseCacheKey = (cacheKey) => {
|
111
|
-
const [destination, partyType, partyId] = cacheKey.split(':').slice(-3)
|
112
|
-
return [destination, partyType, partyId]
|
113
|
-
}
|
114
|
-
|
115
106
|
module.exports = {
|
116
107
|
timeoutInterschemePartiesLookups,
|
117
|
-
timeoutProxyGetPartiesLookups,
|
118
108
|
sendTimeoutCallback // Exposed for testing
|
119
109
|
}
|
@@ -41,13 +41,13 @@ let isRunning
|
|
41
41
|
|
42
42
|
const timeout = async (options) => {
|
43
43
|
if (isRunning) return
|
44
|
+
|
44
45
|
const { logger } = options
|
45
46
|
|
46
47
|
try {
|
47
48
|
isRunning = true
|
49
|
+
logger.debug('Timeout handler triggered')
|
48
50
|
await TimeoutService.timeoutInterschemePartiesLookups(options)
|
49
|
-
await TimeoutService.timeoutProxyGetPartiesLookups(options)
|
50
|
-
logger.verbose('ALS timeout handler is done')
|
51
51
|
} catch (err) {
|
52
52
|
logger.error('error in timeout: ', err)
|
53
53
|
} finally {
|
package/src/lib/util.js
CHANGED
@@ -29,11 +29,10 @@ const util = require('node:util')
|
|
29
29
|
const Path = require('node:path')
|
30
30
|
const EventSdk = require('@mojaloop/event-sdk')
|
31
31
|
const Enum = require('@mojaloop/central-services-shared').Enum
|
32
|
-
const { HeaderValidation } = require('@mojaloop/central-services-shared').Util
|
32
|
+
const { HeaderValidation, Hapi } = require('@mojaloop/central-services-shared').Util
|
33
33
|
const rethrow = require('@mojaloop/central-services-shared').Util.rethrow.with('ALS')
|
34
34
|
|
35
35
|
const Config = require('../lib/config')
|
36
|
-
const { API_TYPES } = require('../constants')
|
37
36
|
const { logger } = require('./index')
|
38
37
|
|
39
38
|
const getSpanTags = ({ headers }, transactionType, transactionAction) => {
|
@@ -70,7 +69,7 @@ const pathForInterface = ({ isAdmin, isMockInterface }) => {
|
|
70
69
|
if (isMockInterface) {
|
71
70
|
apiFile = 'api_swagger.json'
|
72
71
|
} else {
|
73
|
-
apiFile = Config.API_TYPE === API_TYPES.iso20022
|
72
|
+
apiFile = Config.API_TYPE === Hapi.API_TYPES.iso20022
|
74
73
|
? 'api-swagger-iso20022-parties.yaml'
|
75
74
|
: 'api-swagger.yaml'
|
76
75
|
}
|
@@ -101,14 +100,7 @@ const countFspiopError = (error, options) => {
|
|
101
100
|
rethrow.countFspiopError(error, options)
|
102
101
|
}
|
103
102
|
|
104
|
-
|
105
|
-
* An immutable object representing the step state
|
106
|
-
* @typedef {Object} StepState
|
107
|
-
* @property {string} step - The current step value (read-only getter property)
|
108
|
-
* @property {(string) => void} inProgress - Method to update the current step
|
109
|
-
*/
|
110
|
-
|
111
|
-
/** @returns {StepState} */
|
103
|
+
// todo: think better name
|
112
104
|
const initStepState = (initStep = 'start') => {
|
113
105
|
let step = initStep
|
114
106
|
return Object.freeze({
|
package/test/fixtures/index.js
CHANGED
@@ -1,30 +1,3 @@
|
|
1
|
-
/*****
|
2
|
-
License
|
3
|
-
--------------
|
4
|
-
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
-
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
-
|
7
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
|
9
|
-
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
|
-
|
11
|
-
Contributors
|
12
|
-
--------------
|
13
|
-
This is the official list of the Mojaloop project contributors for this file.
|
14
|
-
Names of the original copyright holders (individuals or organizations)
|
15
|
-
should be listed with a '*' in the first column. People who have
|
16
|
-
contributed from an organization can be listed under the organization
|
17
|
-
that actually holds the copyright for their contributions (see the
|
18
|
-
Mojaloop Foundation for an example). Those individuals should have
|
19
|
-
their names indented and be marked with a '-'. Email address can be added
|
20
|
-
optionally within square brackets <email>.
|
21
|
-
|
22
|
-
* Mojaloop Foundation
|
23
|
-
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
24
|
-
|
25
|
-
--------------
|
26
|
-
******/
|
27
|
-
|
28
1
|
const { randomUUID } = require('node:crypto')
|
29
2
|
const { Enum } = require('@mojaloop/central-services-shared')
|
30
3
|
const isoFixtures = require('./iso')
|
@@ -47,16 +20,6 @@ const headersDto = ({
|
|
47
20
|
'content-type': contentType || accept
|
48
21
|
})
|
49
22
|
|
50
|
-
const partiesParamsDto = ({
|
51
|
-
Type = 'MSISDN',
|
52
|
-
ID = String(Date.now()),
|
53
|
-
SubId
|
54
|
-
} = {}) => ({
|
55
|
-
Type,
|
56
|
-
ID,
|
57
|
-
...(SubId && { SubId })
|
58
|
-
})
|
59
|
-
|
60
23
|
const protocolVersionsDto = () => ({
|
61
24
|
CONTENT: {
|
62
25
|
DEFAULT: '2.1',
|
@@ -179,7 +142,6 @@ const mockHapiRequestDto = ({ // https://hapi.dev/api/?v=21.3.3#request-properti
|
|
179
142
|
module.exports = {
|
180
143
|
...isoFixtures,
|
181
144
|
partiesCallHeadersDto,
|
182
|
-
partiesParamsDto,
|
183
145
|
participantsCallHeadersDto,
|
184
146
|
oracleRequestResponseDto,
|
185
147
|
putPartiesSuccessResponseDto,
|
@@ -56,7 +56,7 @@ const fixtures = require('../../../fixtures')
|
|
56
56
|
const { type: proxyCacheType, proxyConfig: proxyCacheConfig } = Config.PROXY_CACHE_CONFIG
|
57
57
|
|
58
58
|
const { encodePayload } = Util.StreamingProtocol
|
59
|
-
const { RestMethods
|
59
|
+
const { RestMethods } = Enum.Http
|
60
60
|
|
61
61
|
Logger.isDebugEnabled = jest.fn(() => true)
|
62
62
|
Logger.isErrorEnabled = jest.fn(() => true)
|
@@ -192,26 +192,24 @@ describe('Parties Tests', () => {
|
|
192
192
|
expect(cached).toBe(proxy)
|
193
193
|
})
|
194
194
|
|
195
|
-
it('should
|
196
|
-
Config.PROXY_CACHE_CONFIG.enabled = true
|
195
|
+
it('should send error callback if destination is not in the scheme, and not in proxyCache', async () => {
|
197
196
|
participant.validateParticipant = sandbox.stub()
|
198
197
|
.onFirstCall().resolves({}) // source
|
199
198
|
.onSecondCall().resolves(null) // destination
|
200
199
|
participant.sendRequest = sandbox.stub().resolves()
|
201
200
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
202
201
|
sandbox.stub(oracle, 'oracleRequest')
|
203
|
-
const proxy = 'some-proxy'
|
204
|
-
Util.proxies.getAllProxiesNames = sandbox.stub().resolves([proxy])
|
205
202
|
const headers = fixtures.partiesCallHeadersDto()
|
206
203
|
|
207
204
|
await partiesDomain.getPartiesByTypeAndID(headers, Helper.getByTypeIdRequest.params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query, Helper.mockSpan(), null, proxyCache)
|
208
205
|
|
209
|
-
expect(
|
210
|
-
expect(
|
211
|
-
expect(participant.
|
212
|
-
|
213
|
-
const
|
214
|
-
expect(
|
206
|
+
expect(participant.sendRequest.callCount).toBe(0)
|
207
|
+
expect(oracle.oracleRequest.callCount).toBe(0)
|
208
|
+
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
209
|
+
|
210
|
+
const { errorInformation } = participant.sendErrorToParticipant.getCall(0).args[2]
|
211
|
+
expect(errorInformation.errorCode).toBe('3200')
|
212
|
+
expect(errorInformation.errorDescription).toContain(ERROR_MESSAGES.partyDestinationFspNotFound)
|
215
213
|
})
|
216
214
|
|
217
215
|
it('should send request to proxy, if destination is not in the scheme, but has proxyMapping', async () => {
|
@@ -472,7 +470,7 @@ describe('Parties Tests', () => {
|
|
472
470
|
expect(firstCallArgs[2]).toBe(expectedCallbackEnpointType)
|
473
471
|
})
|
474
472
|
|
475
|
-
it('should send
|
473
|
+
it('should send request to proxy if oracle returns dfsp NOT from the scheme', async () => {
|
476
474
|
Config.PROXY_CACHE_CONFIG.enabled = true
|
477
475
|
const proxyName = `proxy-${Date.now()}`
|
478
476
|
const fspId = `dfspNotFromScheme-${Date.now()}`
|
@@ -481,7 +479,7 @@ describe('Parties Tests', () => {
|
|
481
479
|
})
|
482
480
|
sandbox.stub(oracle, 'oracleRequest').resolves(oracleResponse)
|
483
481
|
participant.validateParticipant = sandbox.stub()
|
484
|
-
.onFirstCall().resolves(
|
482
|
+
.onFirstCall().resolves({}) // source
|
485
483
|
.onSecondCall().resolves(null) // oracle dfsp
|
486
484
|
participant.sendRequest = sandbox.stub().resolves()
|
487
485
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
@@ -489,20 +487,15 @@ describe('Parties Tests', () => {
|
|
489
487
|
const isAdded = await proxyCache.addDfspIdToProxyMapping(fspId, proxyName)
|
490
488
|
expect(isAdded).toBe(true)
|
491
489
|
|
492
|
-
const
|
493
|
-
const headers = fixtures.partiesCallHeadersDto({ destination: '', source, proxy: 'proxy' })
|
490
|
+
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
494
491
|
const { params, method, query } = Helper.getByTypeIdRequest
|
495
492
|
|
496
493
|
await partiesDomain.getPartiesByTypeAndID(headers, params, method, query, null, null, proxyCache)
|
497
494
|
|
498
|
-
expect(participant.
|
499
|
-
expect(participant.
|
500
|
-
|
501
|
-
|
502
|
-
expect(sentTo).toBe(source)
|
503
|
-
expect(payload.errorInformation.errorCode).toBe('3200')
|
504
|
-
expect(sentHeaders[Headers.FSPIOP.SOURCE]).toBe(Config.HUB_NAME)
|
505
|
-
expect(sentHeaders[Headers.FSPIOP.DESTINATION]).toBe(headers[Headers.FSPIOP.SOURCE])
|
495
|
+
expect(participant.sendErrorToParticipant.callCount).toBe(0)
|
496
|
+
expect(participant.sendRequest.callCount).toBe(1)
|
497
|
+
const calledProxy = participant.sendRequest.getCall(0).args[1]
|
498
|
+
expect(calledProxy).toBe(proxyName)
|
506
499
|
})
|
507
500
|
|
508
501
|
it('handles error when `oracleRequest` returns no result', async () => {
|
@@ -561,14 +554,13 @@ describe('Parties Tests', () => {
|
|
561
554
|
participant.sendRequest = sandbox.stub().rejects(new Error('Some network issue'))
|
562
555
|
participant.sendErrorToParticipant = sandbox.stub().resolves()
|
563
556
|
const headers = fixtures.partiesCallHeadersDto({ destination: '' })
|
564
|
-
const params = fixtures.partiesParamsDto()
|
565
557
|
|
566
|
-
await partiesDomain.getPartiesByTypeAndID(headers, params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query, Helper.mockSpan(), null, proxyCache)
|
558
|
+
await partiesDomain.getPartiesByTypeAndID(headers, Helper.getByTypeIdRequest.params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query, Helper.mockSpan(), null, proxyCache)
|
567
559
|
|
568
560
|
expect(participant.sendRequest.callCount).toBe(proxyNames.length)
|
569
561
|
expect(participant.sendErrorToParticipant.callCount).toBe(1)
|
570
562
|
|
571
|
-
const { errorInformation } = participant.sendErrorToParticipant.
|
563
|
+
const { errorInformation } = participant.sendErrorToParticipant.getCall(0).args[2]
|
572
564
|
expect(errorInformation.errorCode).toBe('3200')
|
573
565
|
expect(errorInformation.errorDescription).toContain(ERROR_MESSAGES.proxyConnectionError)
|
574
566
|
})
|
@@ -3,9 +3,7 @@
|
|
3
3
|
--------------
|
4
4
|
Copyright © 2020-2025 Mojaloop Foundation
|
5
5
|
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
-
|
7
6
|
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
|
9
7
|
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
10
8
|
|
11
9
|
Contributors
|
@@ -15,43 +13,46 @@
|
|
15
13
|
should be listed with a '*' in the first column. People who have
|
16
14
|
contributed from an organization can be listed under the organization
|
17
15
|
that actually holds the copyright for their contributions (see the
|
18
|
-
Mojaloop Foundation for an example). Those individuals should have
|
16
|
+
Mojaloop Foundation organization for an example). Those individuals should have
|
19
17
|
their names indented and be marked with a '-'. Email address can be added
|
20
18
|
optionally within square brackets <email>.
|
21
|
-
|
22
19
|
* Mojaloop Foundation
|
23
|
-
|
20
|
+
- Name Surname <name.surname@mojaloop.io>
|
24
21
|
|
22
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
25
23
|
--------------
|
26
|
-
|
27
|
-
|
28
|
-
const
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
24
|
+
**********/
|
25
|
+
|
26
|
+
const mockSendRequest = jest.fn()
|
27
|
+
|
28
|
+
jest.mock('@mojaloop/central-services-shared', () => ({
|
29
|
+
...jest.requireActual('@mojaloop/central-services-shared'),
|
30
|
+
Util: {
|
31
|
+
...jest.requireActual('@mojaloop/central-services-shared').Util,
|
32
|
+
Endpoints: { getEndpoint: jest.fn() },
|
33
|
+
Request: { sendRequest: mockSendRequest }
|
34
|
+
}
|
35
|
+
}))
|
36
|
+
|
37
|
+
const { API_TYPES } = require('@mojaloop/central-services-shared').Util.Hapi
|
38
|
+
const { logger } = require('../../../../src/lib')
|
39
|
+
const partiesUtils = require('../../../../src/domain/parties/partiesUtils')
|
40
|
+
const config = require('../../../../src/lib/config')
|
41
|
+
const fixtures = require('../../../fixtures')
|
42
|
+
|
43
|
+
describe('parties utils Tests -->', () => {
|
44
|
+
test('should send error party callback in ISO format', async () => {
|
45
|
+
const isoConfig = { ...config, API_TYPE: API_TYPES.iso20022 }
|
46
|
+
const err = new Error('test error')
|
47
|
+
const source = 'dfsp1'
|
46
48
|
const headers = fixtures.partiesCallHeadersDto({ source })
|
47
|
-
const params =
|
48
|
-
|
49
|
-
|
50
|
-
await
|
51
|
-
|
52
|
-
|
53
|
-
const
|
54
|
-
expect(sentTo).toBe(source)
|
49
|
+
const params = { ID: '1234', Type: 'MSISDN' }
|
50
|
+
|
51
|
+
const handleError = partiesUtils.createErrorHandlerOnSendingCallback(isoConfig, logger)
|
52
|
+
await handleError(err, headers, params, source)
|
53
|
+
|
54
|
+
expect(mockSendRequest).toHaveBeenCalledTimes(1)
|
55
|
+
const { payload } = mockSendRequest.mock.calls[0][0]
|
55
56
|
expect(payload.Rpt.Rsn.Cd).toBe('2001')
|
56
57
|
expect(payload.Rpt.OrgnlId).toBe(`${params.Type}/${params.ID}`)
|
57
58
|
expect(payload.Assgnmt.Assgnr.Agt.FinInstnId.Othr.Id).toBe(source)
|
@@ -64,16 +64,16 @@ describe('Timeout Domain', () => {
|
|
64
64
|
|
65
65
|
describe('sendTimeoutCallback', () => {
|
66
66
|
it('should send error to participant', async () => {
|
67
|
-
|
68
|
-
jest.spyOn(Participant, 'validateParticipant').mockResolvedValue({ fspId: SOURCE_ID })
|
67
|
+
jest.spyOn(Participant, 'validateParticipant').mockResolvedValue({ fspId: 'sourceId' })
|
69
68
|
|
70
|
-
const cacheKey =
|
69
|
+
const cacheKey = 'als:sourceId:2:3:expiresAt'
|
70
|
+
const [, destination] = cacheKey.split(':')
|
71
71
|
|
72
72
|
await TimeoutDomain.sendTimeoutCallback(cacheKey)
|
73
73
|
|
74
|
-
expect(Participant.validateParticipant).toHaveBeenCalledWith(
|
74
|
+
expect(Participant.validateParticipant).toHaveBeenCalledWith('sourceId')
|
75
75
|
expect(Participant.sendErrorToParticipant).toHaveBeenCalledWith(
|
76
|
-
|
76
|
+
destination,
|
77
77
|
'FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR',
|
78
78
|
{ errorInformation: { errorCode: '3300', errorDescription: 'Generic expired error' } },
|
79
79
|
expect.any(Object), expect.any(Object), undefined, expect.any(Object)
|
package/test/util/index.js
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
const { AlsApiClient, ProxyApiClient } = require('./apiClients')
|
2
|
-
const mockDeps = require('./mockDeps')
|
3
1
|
const onboarding = require('./onboarding')
|
2
|
+
const {
|
3
|
+
AlsApiClient,
|
4
|
+
ProxyApiClient
|
5
|
+
} = require('./apiClients')
|
4
6
|
|
5
7
|
module.exports = {
|
8
|
+
onboarding,
|
6
9
|
AlsApiClient,
|
7
|
-
ProxyApiClient
|
8
|
-
mockDeps,
|
9
|
-
onboarding
|
10
|
+
ProxyApiClient
|
10
11
|
}
|
@@ -1,51 +0,0 @@
|
|
1
|
-
/*****
|
2
|
-
License
|
3
|
-
--------------
|
4
|
-
Copyright © 2020-2025 Mojaloop Foundation
|
5
|
-
The Mojaloop files are made available by the Mojaloop Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
6
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
7
|
-
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
8
|
-
|
9
|
-
Contributors
|
10
|
-
--------------
|
11
|
-
This is the official list of the Mojaloop project contributors for this file.
|
12
|
-
Names of the original copyright holders (individuals or organizations)
|
13
|
-
should be listed with a '*' in the first column. People who have
|
14
|
-
contributed from an organization can be listed under the organization
|
15
|
-
that actually holds the copyright for their contributions (see the
|
16
|
-
Mojaloop Foundation organization for an example). Those individuals should have
|
17
|
-
their names indented and be marked with a '-'. Email address can be added
|
18
|
-
optionally within square brackets <email>.
|
19
|
-
* Mojaloop Foundation
|
20
|
-
- Name Surname <name.surname@mojaloop.io>
|
21
|
-
|
22
|
-
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
23
|
-
--------------
|
24
|
-
**********/
|
25
|
-
|
26
|
-
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
27
|
-
const partiesUtils = require('#src/domain/parties/partiesUtils')
|
28
|
-
const config = require('#src/lib/config')
|
29
|
-
const { API_TYPES } = require('#src/constants')
|
30
|
-
const fixtures = require('#test/fixtures/index')
|
31
|
-
|
32
|
-
describe('partiesUtils Tests -->', () => {
|
33
|
-
describe('makePutPartiesErrorPayload Tests', () => {
|
34
|
-
const error = ErrorHandler.Factory.reformatFSPIOPError(new Error('Test Error'))
|
35
|
-
const ERR_CODE = '2001'
|
36
|
-
const headers = fixtures.partiesCallHeadersDto()
|
37
|
-
const params = fixtures.partiesParamsDto()
|
38
|
-
|
39
|
-
test('should make putParties error payload in FSPIOP format', async () => {
|
40
|
-
const fspiopConfig = { ...config, API_TYPE: API_TYPES.fspiop }
|
41
|
-
const payload = await partiesUtils.makePutPartiesErrorPayload(fspiopConfig, error, headers, params)
|
42
|
-
expect(payload.errorInformation.errorCode).toBe(ERR_CODE)
|
43
|
-
})
|
44
|
-
|
45
|
-
test('should make putParties error payload in ISO20022 format', async () => {
|
46
|
-
const fspiopConfig = { ...config, API_TYPE: API_TYPES.iso20022 }
|
47
|
-
const payload = await partiesUtils.makePutPartiesErrorPayload(fspiopConfig, error, headers, params)
|
48
|
-
expect(payload.Rpt.Rsn.Cd).toBe(ERR_CODE)
|
49
|
-
})
|
50
|
-
})
|
51
|
-
})
|