Open mjbrichards opened 2 years ago
A sequence diagram to visualize the suggested mapping would help a lot for my understanding..
I attach a proposed revision of the API definition according to the principles outlined above, and a sequence diagram showing how the revised API would work with the proposed Google Imali interface Draft PISP Specification Changes for Imali.docx
Thanks a lot @mjbrichards! I had a quick look at the sequence diagram and I just have some minor comments/questions for now:
(the body of a POST /thirdpartyRequests/transactions request, perhaps with the payee.fspId left blank to indicate the requirement for discovery)
Meaning that discovery would happen after 3PPI requests initiation of transfer by debtor DFSP?
In reference to my story https://github.com/mojaloop/project/issues/2668, added additional notes related to implementation there
Hi @ehenrka , thanks for your comments.
@kleyow, the question you raise relates to a thought that didn't make it through to the sequence diagram or the API definition. When we map our three-part transfer sequence onto the two-part sequence that Imali (and, I think, many others) use, we originally thought that the first part corresponded with discovery and the second part with agreement (quote) and execution. I now think it's a better fit to map discovery and agreement onto the first part, and execution onto the second. My impression is that that makes it easier for two-parters to understand. It then occurred to me that we could make it easier by folding the discovery part into the thirdPartyRequests/transactionRequests message, and that we could do that by leaving the payee fspId blank, which the payer DFSP would interpret as "please identify the DFSP to which this identifier belongs." But, as you see, that thinking didn't make it as far as the sequence diagram or the API definition.
It then occurred to me that we could make it easier by folding the discovery part into the thirdPartyRequests/transactionRequests message, and that we could do that by leaving the payee fspId blank, which the payer DFSP would interpret as "please identify the DFSP to which this identifier belongs." But, as you see, that thinking didn't make it as far as the sequence diagram or the API definition.
Yep I interpreted that statement exactly as you described.
Thanks for this Michael,
In general this looks like a great simplification to what we already have, and I'm yet to find any drawbacks. I'm looking forward to discussing it later on.
My notes below:
It would also remove the need for a 3PPI to support the FSPIOP GET /parties endpoint. Can you please clarify this? I take it to mean that the 3PPI won't need to call
GET /parties
, but this could be construed otherwise.
thirdpartyRequests/transactions
and thirdpartyRequests/transfers
seems dangerous to me. Are there better names we can use to better distinguish between the 2 phases?In section 3.1.6.1.2 POST /thirdPartyRequests/transfers
:
Used by: DFSP The HTTP request POST /thirdPartyRequests/transfers is used to request the validation by a customer for the transfer described in the request.
This doesn't line up with the sequence diagram, where this call is made by the PISP, not the DFSP.
This proposal looks non-backwards compatible to me, as we are repurposing exsting endpoints for other purposes. So do you imagine we are going to be updating to the Third Party API to v2.0 here?
This proposal looks non-backwards compatible to me, as we are repurposing existing endpoints for other purposes. So do you imagine we are going to be updating to the Third Party API to v2.0 here?
Agreed in SIG Meeting
@MichaelJBRichards I've got the following suggestions for the 2 endpoint names (in no particular preference order):
thirdpartyRequests/initiate
and thirdpartyRequests/transfer
?thirdpartyRequests/terms
and thirdpartyRequests/accept
thirdpartyRequests/propose
and thirdpartyRequests/execute
@lewisdaly and @mjbrichards, isn't it in essence a quote and a transfer that is done in the sequence flow, but requested from a thirdparty?
Hence, my suggestion would simply be /3pQuotes
and /3pTransfers
, which names would align well with the new proposed/fxQuotes
and /fxTransfers
resources in #89.
Yeah I like that suggestion @ehenrka. And do I understand your statement well that we remove the thirdpartyRequests
prefix?
Thanks @lewisdaly, yes I think it is fine to remove the longer prefix thirdpartyRequests/
as it should be easy to distinguish based on the 3p
prefix. I'm also fine with using something longer like ThirdpartyQuotes
and ThirdpartyTransfers
if just prefix 3p
is a bit cryptic.
Does that mean, @ehenrka and @lewisdaly, that we should add the prefix to all the currently non-prefixed endpoints (/accounts, /consentRequests, etc.)? This would make it clear that they all belong to the same family.
I've taken an executive decision and renamed all the PISP endpoints to use the prefix "tpp" (Third Party Provider). On the question of quotes, I think that what we actually have is an analogue to the FSPIOP /transactionRequests endpoint, so I have renamed it accordingly. Let me know what you think. Draft PISP Specification Changes for Imali.docx
@mjbrichards, I would say that there is a major difference in the /transactionRequests
endpoint compared to the flow in https://github.com/mojaloop/mojaloop-specification/issues/107#issuecomment-1036043849.
In the FSPIOP /transactionRequests
, an FSP (the Payee FSP) is requesting another FSP (the Payer FSP) to ask if their account holder (the Payer) accepts a transaction. In this case it will be the Payee FSP that sends the POST /transactionRequests
, but then it is the Payer FSP that sends the POST /quotes
and the POST /transfers
. So there will be a change in who is driving the flow.
In the sequence diagram in https://github.com/mojaloop/mojaloop-specification/issues/107#issuecomment-1036043849, the flow is controlled by the Third Party. The Payment Manager acting as the third party first sends a GET /parties
to the Switch, then a POST /thirdpartyrequests/transactions
to the Switch to get the quote for the transaction, then the POST /thirdpartyrequests/transfers
to the Switch to perform the transaction as detailed in the quote. This is very similar to the normal Payer initiated flow in FSPIOP, where the Payer FSP first sends a GET /parties
, then POST /quotes
, then POST /transfers
.
As ususal, @ehenrka, you are completely correct; but I think that this is the correct structure for the third party interaction. In the FSPIOP interaction, the requester is the creditor party and authorisation for the transfer is given out-of-band by the debtor party; so the debtor DFSP is driving the flow. In the TPP interaction, however, the requester is the debtor party, and the TPP is managing the authorisation process: so it seems to me correct that the TPP should be managing the flow.
However, you raise an important point which I think we should consider. As I've said, the pattern that I propose seems to me appropriate for the interaction we're considering; but I think that this is a consequence of the fact that the TPP is acting on behalf of the authorising party in the process of authorisation. The API therefore needs to provide a break in the transactional flow to allow the debtor customer to review the terms of the transfer and give their consent to it. We should, however, also consider the case where the TPP wants to request the initiation of a payment, but where it wants authorisation to be carried out by the debtor's DFSP: for instance, where a fintech wants to request a subscription payment from a customer. Here the TPP is (acting for) the creditor, not the debtor; but it cannot rely on obtaining information about the transfer from its DFSP, since it is not making the request through the creditor DFSP, as would be the case if it were using MRTP via the FSPIOP API. It seems to me that, in this case, the correct response to the POST /tppTransactionRequests call would be a message which contains the content of the PUT /tppTransactionRequests call, but without the challenge field (since authorisation by the TPP is not required,) and with an additional transferState field informing the TPP of the outcome of the transfer.
So we might say that the OpenAPI definition for this message should include a oneOf containing the challenge field if authorisation is to be obtained by the TPP, or the transferState field if authorisation has been obtained by the debtor DFSP and the transfer has completed.
I'm not quite sure how we represent alternatives in our specification; but does that make sense?
Thanks @mjbrichards, but I still don't really understand why it should be /tppTransactionRequests in this case. There is not a Payee that is requesting a transaction through the PISP as in the FSPIOP version /transactionRequests, where the Payee requests the Payer to perform the transaction, and the Payee can then expect an incoming transaction later (if the request is accepted the Payer).
In the flow in https://github.com/mojaloop/mojaloop-specification/issues/107#issuecomment-1036043849, the Payer is requesting a quote for a transaction to the Payee via the PISP. The quote can later be executed by the Payer sending the signed challenge again via the PISP. The Payee is not involved in this flow at all, the Payee just receives funds. This is similar to the normal Payer initiated flow in FSPIOP, which just uses /quotes and /transfers, but the signed challenge is handled internally in the Payer FSP. Hence, I still think it should be /tppQuotes.
Based on your comment above, it seems like you want to use the same /tppTransactionRequests request for both a merchant initiated payment use case (or similar Payee-initiated transactions) and a person to person transfer (or other similar Payer-initiated transactions) but with alternative fields.
To me, it seems appropriate to use a similar pattern as in FSPIOP (Payer- vs Payee-initiated flow), where you use a separate request if you as a Payee is requesting a transaction from a Payer, instead of where the Payer is performing the transaction directly without involving the Payee. This would avoid any alternative fields that are based on the use case, and instead make it clear both which use case it is and which fields that should be used for that specific use case.
I think I (somehow) agree with both of you @ehenrka and @mjbrichards!
If I can try and restate your point @MichaelJBRichards, right now we are mainly imagining a P2P use case, but initiated by a 3rd party, so this should be considered a transaction request. But we could also imagine a future where this isn't necessarily the case (e.g. a PISP that helps users automate bill payments by sending transaction requests when bills are due)
Is there a 3rd term (not /transfers or /transactionRequests) that we could generalize over both (or all) use cases? Or at least allow us to disambiguate between this API and the FSPIOP API?
Sorry, @ehenrka and @lewisdaly, that I didn't express myself very clearly. The point I was trying to make is that there are really three separate decisions that a TPP needs to make, and that these decisions are orthogonal to each other. The first decision is whether the TPP is acting on behalf of the debtor (which is the GooglePay example) or of the creditor. The second is whether or not the TPP wants the debtor institution to delegate authorisation for the transfer to the TPP; and the third is whether the TPP wants the chance to assent to the final terms of the transfer.
Let's imagine a situation in which a fintech has developed an application for merchants to use. It will include a module which allows the merchant to request payment from a customer, and another module which allows the merchant to order supplies from one or more wholesalers based on monitoring stock levels. In the first module, the merchant is the creditor; in the second, it is the debtor. In both cases, the fintech is defining the terms of a payment which will then be agreed and executed by the appropriate DFSP parties.
In order to establish the argument for orthogonality between origination and authorisation, we need to answer the following questions in the negative: first, are there any circumstances in which we might want to support the merchant application authorising a payment even though it was acting for the creditor party; and, second, are there any circumstances in which we might want to support the merchant application asking the debtor DFSP to manage authorisation when the TPP was acting for the debtor party?
I think that the answer to the second question is definitely yes. Our merchant application might want to manage the re-ordering process without also wanting to take the responsibility of assuring the DFSP which held the merchant's bank account that it had properly obtained the merchant's authorisation for the transfer. In this it would be like the existing MRTP flow, except that the flow is initiated by a representative of the debtor party, not the creditor party. So the app tells the merchant that she needs to order more cans of Coke from her supplier: the merchant initiates the order, and her DFSP contacts her to approve the funds transfer.
The more counter-intuitive question is the first; but I think that here too we can propose a use case in which the merchant app might want to authorise on behalf of the creditor party to a transfer. Let's imagine a merchant whose store is located in a semi-permanent refugee camp. The refugees in the camp don't have access to mobile money systems, or possibly even phones; but an NGO is disbursing funds to support their day-to-day existence. The NGO wants to ensure that the funds are really going to the intended beneficiaries. The NGO has an enrolment program which records an ID for each refugee, together with their fingerprint. Now a refugee can go to the merchant's store and buy goods. When they want to pay, the merchant app records their ID number and their fingerprint; and this is taken by the NGO's DFSP as authorisation to credit the merchant's account, and debit the refugee's share of the overall disbursement, in respect of that particular refugee. So the NGO can make disbursements without needing to hand out cash; the disbursements are spent with local merchants, not international suppliers; and the refugees are brought into the financial system. All of this depends on the merchant app being able to authorise the credit party to the satisfaction of the debit party.
Now we need to think about the question of approval by the TPP application. Here I think that the question of orthogonality turns on the following test: can we imagine a circumstance in which the TPP's customer would want to approve a transfer even though the TPP is not responsible for authorising the transfer? Here I think that the answer is definitely yes. Let's suppose that our merchant app is generating a purchase request to replenish the merchant's stock of cans of Coke. The merchant's normal supplier has moved their account to a DFSP which charges a significant sum for processing the transfer. The merchant's TPP app should be able to pass this information back to the merchant and allow her to decide whether to go ahead with the purchase and bear the charge, or to look for an alternative supplier. This needs to be done by the TPP app rather than the authorising DFSP app, because it's part of the service that the TPP app provides to know about alternative suppliers, and the DFSP app doesn't provide that service.
So I think that this means that we have three separate things that our API will need to cover: the first is a request to perform a transfer between two named parties. This will be the same whether the TPP is acting on behalf of the credit party or the debit party, and it will always be addressed to the debit party's DFSP. The second is the question of whether the transfer is to be authorised by the TPP or by a DFSP. The third is the question of whether the TPP wants to be able to approve the transfer before it is executed or not. Now, I don't have a strong preference about the names we give to these things; but I do think that we (will) need to accommodate them in the way I've described. Would you agree?
Thanks for the additional context @mjbrichards!
First a question regarding the following:
So I think that this means that we have three separate things that our API will need to cover: the first is a request to perform a transfer between two named parties. This will be the same whether the TPP is acting on behalf of the credit party or the debit party, and it will always be addressed to the debit party's DFSP.
Maybe I missed something here, but why will it be the same, and why will it always be addressed to the Payer FSP? If the TPP is acting on behalf of the Payee (the credit party), what is stopping you from sending a request to the Payee FSP, and the Payee FSP then sends a FSPIOP POST /transactionRequests to the Payer FSP to ask the Payer for confirmation? If this was the case, then only the Payee FSP would need to support the TPP interface (meaning a possible competitive advantage in selling fintech services for PISPs for the Payee FSP in this case).
Your refugee example seems to be similar to Payee Initiated Transaction using OTP, but instead of using OTP you are using ID number and fingerprint as the authorisation to pay. I think it makes good sense here to extend the possible authentication types in FSPIOP so that you can use additional methods. But yes, there must be a way for the TPP to say which type of authentication it should be.
Regarding your last example with generating a purchase request to replenish the merchant's stock, does the question to the merchant really have to be in the API? In my view, the TPP app just sends a quote for the transaction to the supplier, the TPP app sees that this transfer now costs a lot of money and therefore asks the merchant to confirm. I just don't see any need to have this part in the API, but I might have missed something.
Hi @ehenrka, and thank you as usual for your acute comments. My answers are as follows...
I think that there's a problem with sending the request to the payee DFSP. If the Payee DFSP then sends a FSPIOP POST /transactionRequests to the Payer DFSP to ask the Payer for confirmation, how is it to notify to the payer DFSP that the TPP wants to undertake authorisation? The FSPIOP POST /transactionRequests doesn't accommodate that. So that scenario would work if the TPP wanted the Payer DFSP to undertake authorisation, but not if it didn't. Which introduces what seems to me an unpleasingly asymmetric quality to the interface; but perhaps that doesn't matter.
I think that the difference between my example and the OTP /authorizations endpoint is that in the OTP example, the authorisation process is still being carried out by the payer DFSP, but using material provided by the addressee of the request (e.g. the operator of an ATM.) In the TPP example, the TPP really is carrying out the authorisation itself, and is then providing the payee DFSP with a testable assertion that it has in fact performed the authorisation. Now, perhaps there's no substantive difference between the two; but they seem to me to be different things...
In the third point, I wanted to be able to draw a distinction between authorisation and confirmation. If the TPP wants the payer DFSP to perform authorisation, then in the normal run of things it wouldn't need to do a confirmation (which we kind of expect to be part of the authorisation.) It would just send the request to the DFSP and wait to hear what the response was. So it might be possible to say that the TPP could infer from an error response that the merchant had declined the authorisation, and that the TPP should therefore find out more about why and perhaps suggest alternatives. Perhaps that would be the way forward, provided that it was clear that the payer DFSP needed to send the declined status to the TPP so that the TPP could take action if it wanted to.
Thanks @mjbrichards,
I think that there's a problem with sending the request to the payee DFSP. If the Payee DFSP then sends a FSPIOP POST /transactionRequests to the Payer DFSP to ask the Payer for confirmation, how is it to notify to the payer DFSP that the TPP wants to undertake authorisation? The FSPIOP POST /transactionRequests doesn't accommodate that.
With this I assume that you mean that the Payer will be authorised in the TPP, like if I'm buying something from a merchant and enter my credentials/fingerprint in the merchant's device? At least that high-level use case is supported in the FSPIOP API, but just using OTP or QR code as of now. I don't see a problem with adding additional authorisation possibilities, potentially through some kind of testable assertion as you mention your following paragraph. One example could be that the Payer can prove that he/she is accepting the transaction by signing with his/her private key, which the Payee FSP can easily verify by the Payer's public key.
At least in my world, this would simplify things as the TPP would talk to its user's FSP, irregardless if the user is currently acting as the Payer or Payee. No need for both Payer and Payee FSP to support the Third Party API. It would also improve both the Third Party API and the FSPIOP API.
Following our discussion at the SIG, a thought on fraud. @jgeewax raised the question of the danger of impersonation frauds, in which bad actors convince account holders to re-route funds from the legitimate beneficiary to a fake account controlled by the fraudster. He was concerned, rightly of course, that in allowing PISPs to make payment requests to multiple subscribers (for instance, M-Kopa reminding its subscribers that their payments are due via an RTP) we should not create a use case which could be used fraudulently. I think that this worry should probably be allayed by the fact that any PISP joining a Mojaloop scheme would need to be explicitly approved by the scheme (and reviewed while a member.) So it should not be possible for an alert scheme to allow an actor called N-Kopa into the scheme as a PISP. These frauds are enabled by the fact that the bad actors can use out-of-band methods of persuasion like fake mails to convince their victims to make payments in which the fraudulent beneficiaries are ordinary customers of existing FIs. Being able to regulate PISPs as a specific class of actors should, in my view, help considerably in reducing the possibility of frauds of this type.
Following discussion in the newly formed PISP SIG, we hope to get agreement to the changes proposed so that a v2.0 API of the PISP can be published. To help with this I have prepared and overview sequence diagram summarising what has been agreed to to date. Please review to make sure that it aligns with everyone's understanding.
Here is the update draft specification document for review. Draft.PISP.Specification.Changes.for.v2_0
Which include the edits discussed above, and the new accounts request resource that enables authorisation to distribute the account information during discovery as described in issue #123.
Refactoring the 3PPI Transfer Interface
Table of Contents
1. Preface
This section contains basic information regarding the change request.
1.1 Change Request Information
| Requested By | Michael Richards, ModusBox | | Change Request Status | In review ☒ / Approved ☐ / Rejected ☐ | | Approved/Rejected Date | |
1.2 Document Version Information
2. Problem Description
2.1 Background
The current structure of a 3PPI transfer request is as follows:
So, essentially, steps 1-2 correspond with the discovery phase, steps 3-5 with the agreement phase, and steps 7-10 with the execution phase. Failures in the execution phase, however, are recorded in a step that might be seen as properly belonging to the agreement phase.
Like many external APIs, the proposed Google Imali interface divides a transfer into the following phases:
So:
In mapping two-step transfer sequences like the Imali one onto our three-step sequence, we have tended to map the initial phase onto our discovery phase, and the second phase onto our agreement and execution phases. This thinking has given rise to the potential problem just described, where requests on either side can perfectly properly be ignored by the other side:
This mismatch contains the possibility that errors and misunderstandings will arise over the course of implementation, increasing the likelihood of failure and hence the cost of operation of a system which supports transfers initiated by 3PPIs. If possible, we should consider aligning our interface with Google's Imali interface as a representative of a common pattern in transfer initiation which is consistent with Level 1 principles, as described below.
2.2 Current Behaviour
See above
2.3 Requested Behaviour
At present, we map our Discovery phase onto the two-phase Request phase, and our Agreement and Execution phases onto the two-phase Execution phase. But in the 3PPI context, the point of agreement, and the conclusion of the Request phase, is the user's authorisation of the agreed terms of the transfer. Hence the Execution phase cannot begin until the 3PPI has responded with the signed challenge, which is a request to execute the agreed transfer. This meets the Level One requirement that a customer should always be able to consent to the exact terms of the transfer before confirming that the transfer should be executed.
A more correct mapping of the Mojaloop phases onto the two-phase model might rather be:
This approach would require a revision of our endpoint definitions, but, I think, no revision to the message content. It would also remove the need for a 3PPI to support the FSPIOP GET /parties endpoint.