I am looking for a reusable solution for a problem where some actions performed by a user may need further confirmation from the user before completion.
I am developing an app using React frontend and WebAPI backend.
Lets say user is initiating fund transfer and assume we cannot check the available fund in his/her account client side before initiating the transfer. When user submits the request (via HTTP POST), the request should complete as normal if the user's account has enough fund whereas if the fund is not enough and the user is within overdraft limits then user should be prompted to use overdraft and only when the user confirms to use overdraft the request should complete.
Another scenario is, say user wants to delete one of the payee account (via HTTP DELETE). Delete should finish normal when there is no recurring payment setup to payee account. User should be prompted further when there is a recurring payment setup (checking the recurring account can only be done on server side and it will be done only when needed (so doing this in advance and feeding to client side is not an option).
I am sure this is a common scenario in any application but can't find reasonable solution to this problem in the internet.
thanks in advance
It's not so much that the scenario is not common - you put a weird requirement on it. In an ideal design - you'd ask the customer to turn-on the overdraft capability, which would be a separate API call to a api/settings
endpoint perhaps. You are combining that with the regular request payload, which makes things slightly more complex.
You just need a detailed enough response contract and a front-end that handles those cases, that's about it.
I've mocked one below.
Here's the description of what you have below for transferring the funds case. You could modify some of these response contracts to be a lot more descriptive so you can handle a lot more cases.
DirectTry
.DirectTry
fails due to account funds issue / but you validated that you can go overdraft. We add a guid and the transaction info, customer info to a dictionary, just in case if the customer wants to validate the overdraft. You probably should have expiry here as well.We need you to approve going into overdraft for this transaction
/ what's the follow-up state etc...We also transfer a guid, just to make sure it is in fact the same device, same transaction request that's going to enable the overdraft.
public enum State
{
// everything worked
Done,
// error - no retry needed.
CriticalError,
// additional prompt
Prompt,
}
public class ServiceResult
{
// some state.
public State State { get; set; }
... some other props...
}
/// Part of some api controller
[Route("api/funds")]
[HttpPost]
public async Task<ServiceResult> TransferFunds(FundTransferPayload payload)
{
// ... do some ops.
ValidationResult validationResult; = new ValidationResult();
if (payload.OperationType == OperationType.DirectTry)
{
validationResult = new ValidationResult();
}
// pass the guid we returned to front-end back to service to make sure
else if (payload.OperationType == OperationType.PromptProvided)
{
validationResult = ValidateOp(
ValidationDictionary[payload.promptGuid],
payload.customerId,
payload.operationType,
payload.operationId);
}
var transferResult = await SomeService.SomeOps(validationResult);
if (transferResult.Succeeded) {...}
else if (transferResult.NeedsOverdraft)
{
var someGuid = new Guid();
ValidationDictionary.Add(new Key(someGuid), new Value(payload.customerId, 'overdraft', transferResult.operationId));
return new ServiceResult() { State=Prompt, ...otherprops... };
}
else if (transferResult.Failed) {...}
}
and in your front-end something like this...
axios.post('/api/funds', {
operationType: 'DirectTry',
...some other props...
})
.then(function (response) {
if (response.data.state === 'Prompt') {
// save the guid or whatever token you're using - you'll call your API again with that.
// change the UX with the prompt. Upon prompt, fire the request appropriately.
}
});