Skip to content

Commit

Permalink
Merge pull request #133 from mojaloop/feature/MP-495
Browse files Browse the repository at this point in the history
MP-637/MP-495: Implement GET /transfers API on inbound and outbound interfaces
  • Loading branch information
kirgene authored Mar 27, 2020
2 parents 65e1948 + 7bd639e commit dff6d05
Show file tree
Hide file tree
Showing 43 changed files with 1,275 additions and 404 deletions.
70 changes: 70 additions & 0 deletions docs/dfspInboundApi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,23 @@ paths:
500:
$ref: '#/components/responses/500'

get:
summary: Retrieves information for a specific transfer
description: The HTTP request `GET /transfers/{transferId}` is used to get information regarding a transfer created or requested earlier. The `{transferId}` in the URI should contain the `transferId` that was used for the creation of the transfer.
tags:
- Transfers
parameters:
- $ref: '#/components/parameters/transferId'
responses:
200:
description: The transfer was accepted
content:
application/json:
schema:
$ref: '#/components/schemas/transferDetailsResponse'
500:
$ref: '#/components/responses/500'

components:
schemas:

Expand Down Expand Up @@ -642,6 +659,20 @@ components:
type: string
description: Up to 4 digits specifying the sender's merchant classification, if known and applicable.

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.
transferRequest:
type: object
required:
Expand Down Expand Up @@ -683,6 +714,45 @@ components:
type: string
description: Transaction ID from the DFSP backend, used to reconcile transactions between the Switch and DFSP backend systems.

transferDetailsResponse:
type: object
required:
- homeTransactionId
- from
- to
- amountType
- currency
- amount
- transferState
- transactionType
- timestamp
properties:
homeTransactionId:
type: string
description: Transaction ID from the DFSP backend, used to reconcile transactions between the Switch and DFSP backend systems.
from:
$ref: '#/components/schemas/transferParty'
to:
$ref: '#/components/schemas/transferParty'
amountType:
$ref: '#/components/schemas/amountType'
currency:
$ref: '#/components/schemas/currency'
amount:
$ref: '#/components/schemas/money'
transferState:
$ref: '#/components/schemas/transferState'
timestamp:
$ref: '#/components/schemas/timestamp'
transactionType:
$ref: '#/components/schemas/transactionType'
note:
maxLength: 128
type: string
extensions:
$ref: '#/components/schemas/extensionList'


transferStatus:
type: string
enum:
Expand Down
5 changes: 1 addition & 4 deletions src/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
{
"env": {
"es6": true,
"es2020": true,
"node": true,
"jest": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 11
},
"rules": {
"indent": [
"error",
Expand Down
1 change: 1 addition & 0 deletions src/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
10 changes: 5 additions & 5 deletions src/InboundServer/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3521,11 +3521,11 @@ components:
- COMMITTED
- ABORTED
description: >-
Below are the allowed values for the enumeration - RECEIVED Next ledger
has received the transfer. - RESERVED Next ledger has reserved the
transfer. - COMMITTED Next ledger has successfully performed the
transfer. - ABORTED Next ledger has aborted the transfer due a rejection
or failure to perform the transfer.
Below are the allowed values for the enumeration
- RECEIVED Next ledger has received the transfer.
- RESERVED Next ledger has reserved the transfer.
- COMMITTED Next ledger has successfully performed the transfer.
- ABORTED Next ledger has aborted the transfer due a rejection or failure to perform the transfer.
UndefinedEnum:
title: UndefinedEnum
type: string
Expand Down
52 changes: 50 additions & 2 deletions src/InboundServer/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,53 @@ const postTransfers = async (ctx) => {
ctx.response.body = '';
};

/**
* Handles a GET /transfers/{ID} request
*/
const getTransfersById = async (ctx) => {
// kick off an asyncronous operation to handle the request
(async () => {
try {
if (ctx.state.conf.enableTestFeatures) {
// we are in test mode so cache the request
const req = {
headers: ctx.request.headers
};
const res = await ctx.state.cache.set(
`request_${ctx.state.path.params.ID}`, req);
ctx.state.logger.log(`Caching request : ${util.inspect(res)}`);
}

// use the transfers model to execute asynchronous stages with the switch
const model = new Model({
...ctx.state.conf,
cache: ctx.state.cache,
logger: ctx.state.logger,
wso2Auth: ctx.state.wso2Auth,
});

const sourceFspId = ctx.request.headers['fspiop-source'];

// use the model to handle the request
const response = await model.getTransfer(ctx.state.path.params.ID,
sourceFspId);

// log the result
ctx.state.logger.push({response}).
log('Inbound transfers model handled GET /transfers/{ID} request');
}
catch(err) {
// nothing we can do if an error gets thrown back to us here apart from log it and continue
ctx.state.logger.push({ err }).log('Error handling GET /transfers/{ID}');
}
})();

// Note that we will have passed request validation, JWS etc... by this point
// so it is safe to return 202
ctx.response.status = 202;
ctx.response.body = '';
};

/**
* Handles a POST /transactionRequests request
*/
Expand Down Expand Up @@ -377,7 +424,7 @@ const putTransactionRequestsById = async (ctx) => {
};

/**
* Handles a PUT /transfers/{ID}. This is a response to a POST /transfers request
* Handles a PUT /transfers/{ID}. This is a response to a POST|GET /transfers request
*/
const putTransfersById = async (ctx) => {
if(ctx.state.conf.enableTestFeatures) {
Expand All @@ -387,7 +434,7 @@ const putTransfersById = async (ctx) => {
data: ctx.request.body
};
const res = await ctx.state.cache.set(`callback_${ctx.state.path.params.ID}`, req);
ctx.state.logger.log(`Cacheing callback: ${util.inspect(res)}`);
ctx.state.logger.log(`Caching callback: ${util.inspect(res)}`);
}

// publish an event onto the cache for subscribers to action
Expand Down Expand Up @@ -579,6 +626,7 @@ module.exports = {
post: postTransfers
},
'/transfers/{ID}': {
get: getTransfersById,
put: putTransfersById
},
'/transfers/{ID}/error': {
Expand Down
32 changes: 25 additions & 7 deletions src/OutboundServer/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,13 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/transferResponse'
$ref: '#/components/schemas/transferStatusResponse'
500:
$ref: '#/components/responses/transferServerError'
description: An error occurred processing the transfer
content:
application/json:
schema:
$ref: '#/components/schemas/errorResponse'

/requestToPay:
post:
Expand Down Expand Up @@ -757,6 +761,20 @@ components:
or an object representing other types of error e.g. exceptions that may occur inside the scheme adapter.
$ref: '#/components/schemas/transferError'

transferStatusResponse:
type: object
required:
- transferId
- currentState
- fulfil
properties:
transferId:
$ref: '#/components/schemas/mojaloopIdentifier'
currentState:
$ref: '#/components/schemas/transferStatus'
fulfil:
$ref: '#/components/schemas/transferFulfilment'

quote:
type: object
description: Mojaloop API response to a quote request
Expand Down Expand Up @@ -830,11 +848,11 @@ components:
- COMMITTED
- ABORTED
description: >
Below are the allowed values for the enumeration - RECEIVED Next ledger
has received the transfer. - RESERVED Next ledger has reserved the
transfer. - COMMITTED Next ledger has successfully performed the
transfer. - ABORTED Next ledger has aborted the transfer due a rejection
or failure to perform the transfer.
Below are the allowed values for the enumeration
- RECEIVED Next ledger has received the transfer.
- RESERVED Next ledger has reserved the transfer.
- COMMITTED Next ledger has successfully performed the transfer.
- ABORTED Next ledger has aborted the transfer due a rejection or failure to perform the transfer.
mojaloopTransactionRequestState:
title: TransactionRequestStateEnum
Expand Down
34 changes: 34 additions & 0 deletions src/OutboundServer/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,39 @@ const postTransfers = async (ctx) => {
};


/**
* Handler for outbound transfer request
*/
const getTransfers = async (ctx) => {
try {
let transferRequest = {
...ctx.request.body,
transferId: ctx.state.path.params.transferId,
currentState: 'getTransfer',
};

// use the transfers model to execute asynchronous stages with the switch
const model = new OutboundTransfersModel({
...ctx.state.conf,
cache: ctx.state.cache,
logger: ctx.state.logger,
wso2Auth: ctx.state.wso2Auth,
});

// initialize the transfer model and start it running
await model.initialize(transferRequest);
const response = await model.run();

// return the result
ctx.response.status = 200;
ctx.response.body = response;
}
catch(err) {
return handleTransferError('getTransfers', err, ctx);
}
};



/**
* Handler for resuming outbound transfers in scenarios where two-step transfers are enabled
Expand Down Expand Up @@ -201,6 +234,7 @@ module.exports = {
post: postTransfers
},
'/transfers/{transferId}': {
get: getTransfers,
put: putTransfers
},
'/accounts': {
Expand Down
3 changes: 3 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ module.exports = {
autoAcceptQuotes: env.get('AUTO_ACCEPT_QUOTES').default('true').asBool(),
autoAcceptParty: env.get('AUTO_ACCEPT_PARTY').default('true').asBool(),

/* TODO: high-risk transactions can require additional clearing check */
// enableClearingCheck: env.get('ENABLE_CLEARING_CHECK').default('false').asBool(),

useQuoteSourceFSPAsTransferPayeeFSP: env.get('USE_QUOTE_SOURCE_FSP_AS_TRANSFER_PAYEE_FSP').default('false').asBool(),

// Getting secrets from files instead of environment variables reduces the likelihood of
Expand Down
Loading

0 comments on commit dff6d05

Please sign in to comment.