diff --git a/src/models/transfer.js b/src/models/transfer.js index cfe8c118..cf3266d2 100644 --- a/src/models/transfer.js +++ b/src/models/transfer.js @@ -75,16 +75,13 @@ module.exports = class Transfer { * @param {String} transferId The current transfer id. * @param {Object} TansferRequest The new transfer object. */ - async update(currentTransferId, transferRequest) { - const { homeTransactionId: newTransferId } = transferRequest; - const response = { newTransferId }; - const reqStr = JSON.stringify(transferRequest); - const resStr = JSON.stringify(response); + async update(currentTransferId, transferResponse) { + const resStr = JSON.stringify(transferResponse); await this.db.run(` UPDATE ${transferTable} - SET id = ?, request = ?, response = ? - WHERE id = ?`, [newTransferId, reqStr, resStr, currentTransferId]); + SET response = ? + WHERE id = ?`, [resStr, currentTransferId]); } /** diff --git a/src/package.json b/src/package.json index d513f2bb..dcf9ee2e 100644 --- a/src/package.json +++ b/src/package.json @@ -1,15 +1,16 @@ { "name": "mojaloop-simulator", - "version": "11.0.3", + "version": "11.1.0", "description": "A canonical test example implementation of the parties, transfers and quotes resources of the Mojaloop API", "license": "Apache-2.0", "main": "index.js", "author": "Matt Kingston, ModusBox Inc.", "contributors": [ + "Aaron Reynoza ", "Kamuela Franco ", "Matt Kingston ", "Steven Oderayi ", - "Aaron Reynoza ", + "Valentin Genev ", "ModusBox", "Mowali" ], diff --git a/src/simulator/api.yaml b/src/simulator/api.yaml index faadb54b..64b048b0 100644 --- a/src/simulator/api.yaml +++ b/src/simulator/api.yaml @@ -183,6 +183,31 @@ paths: schema: $ref: '#/components/schemas/errorResponse' + /transfers/{transferId}: + put: + summary: Receive notification for a specific transfer + description: The HTTP request `PUT /transfers/{transferId}` is used to receive notification for transfer being fulfiled when the FSP is a Payee + tags: + - Transfers + parameters: + - $ref: '#/components/schemas/transferId' + requestBody: + description: An incoming notification for fulfiled transfer + content: + application/json: + schema: + $ref: '#/components/schemas/fulfilNotification' + responses: + 200: + description: The notification was accepted + 500: + description: An error occured processing the request + content: + application/json: + schema: + $ref: '#/components/schemas/errorResponse' + + /otp/{requestToPayId}: get: summary: Requests OTP @@ -958,6 +983,60 @@ components: message: type: string description: Error message text + + extensionList: + type: array + items: + $ref: '#/components/schemas/extensionItem' + minItems: 0 + maxItems: 16 + + extensionItem: + type: object + properties: + key: + type: string + minLength: 1 + maxLength: 32 + value: + type: string + minLength: 1 + maxLength: 128 + + transferState: + type: string + enum: + - RECEIVED + - RESERVED + - COMMITTED + - ABORTED + description: > + Below are the allowed values for the enumeration + - RECEIVED DFSP has received the transfer. + - RESERVED DFSP has reserved the transfer. + - COMMITTED DFSP has successfully performed the transfer. + - ABORTED DFSP has aborted the transfer due a rejection or failure to perform the transfer. + + fulfilNotification: + title: TransfersIDPatchResponse + type: object + description: PUT /transfers/{transferId} object + properties: + completedTimestamp: + $ref: '#/components/schemas/timestamp' + description: Time and date when the transaction was completed. + example: "2020-05-19T08:38:08.699-04:00" + transferState: + $ref: '#/components/schemas/transferState' + description: State of the transfer. + example: COMMITTED + extensionList: + $ref: '#/components/schemas/extensionList' + description: Optional extension, specific to deployment. + required: + - completedTimestamp + - transferState + diff --git a/src/simulator/handlers.js b/src/simulator/handlers.js index d501ea71..75371ec8 100644 --- a/src/simulator/handlers.js +++ b/src/simulator/handlers.js @@ -30,7 +30,6 @@ require('dotenv').config(); const { getStackOrInspect } = require('@internal/log'); const { ApiErrorCodes } = require('../models/errors.js'); - const getParticipantsByTypeAndId = async (ctx) => { try { const { idValue, idType } = ctx.state.path.params; @@ -48,7 +47,6 @@ const getParticipantsByTypeAndId = async (ctx) => { } }; - const getPartiesByTypeAndId = async (ctx) => { // TODO: check that the provided type was MSISDN? Or just encode that in the API spec.. try { @@ -80,7 +78,6 @@ const getOTPById = async (ctx) => { } }; - const postTransfers = async (ctx) => { try { const res = await ctx.state.model.transfer.create(ctx.request.body); @@ -94,6 +91,20 @@ const postTransfers = async (ctx) => { } }; +const putTransfersById = async (ctx) => { + try { + const res = await ctx.state.model.transfer.update(ctx.state.path.params.transferId, { + ...ctx.request.body, + }); + ctx.state.logger.log(`putTransfersById is returning body: ${util.inspect(res)}`); + ctx.response.body = ctx.request.body; + ctx.response.status = 200; + } catch (err) { + ctx.state.logger.log(`Error in putTransfersById: ${getStackOrInspect(err)}`); + ctx.response.body = ApiErrorCodes.SERVER_ERROR; + ctx.response.status = 500; + } +}; const postQuotes = async (ctx) => { try { @@ -121,7 +132,6 @@ const postBulkQuotes = async (ctx) => { } }; - const getBulkQuoteById = async (ctx) => { try { const { idValue } = ctx.state.path.params; @@ -222,6 +232,9 @@ const map = { '/otp/{requestToPayId}': { get: getOTPById, }, + '/transfers/{transferId}': { + put: putTransfersById, + }, }; diff --git a/src/test/simulator.js b/src/test/simulator.js index 4a369186..93f797fc 100644 --- a/src/test/simulator.js +++ b/src/test/simulator.js @@ -266,3 +266,20 @@ test('postBulkQuotes should handle 500 errors', async (t) => { t.deepEqual(t.context.response, expected, 'Response did not match expected'); t.pass(); }); + +test('putTransfersById should handle request', async (t) => { + // Arrange + // eslint-disable-next-line no-param-reassign + t.context.state.path = { params: { transferId: '1234' } }; + // eslint-disable-next-line no-throw-literal, no-param-reassign + t.context.request = { + body: { + completedTimestamp: '2017-11-15T14:16:09.663+01:00', + transferState: 'COMMITTED', + }, + }; + await map['/transfers/{transferId}'].put(t.context); + const expected = t.context.request.body; + t.deepEqual(t.context.response, { body: { ...expected }, status: 200 }, 'response is received'); + t.pass(); +});