Bot framework v4 Node.js: how to go to next waterf

2020-07-26 11:09发布

问题:

Short question: I need a way to go the next waterfall step based on an external trigger (a post request).

Long question I need to build an integration with a Payment Service Provider. I have most bits and peaces now, but am not able to tie them all together. The process I have in mind is straightforward and involves:

Component Dialog A

A waterfall dialog with three high level steps that take care of:

-1 Collecting of user details

-2 Waiting for payment -> start Component Dialog B

-3 Fulfillment of a digital product

Component Dialog B

Takes care of

-1 Creation of an invoice

-2 Payment of the invoice

-3 Back to Component Dialog A

Index.js

Contains a restify server to be called by the PSP with statusupdates of payment requests.

Happy Flow If the user hits Component Dialog A, we ask some questions, request a payment upfront (Component Dialog B) and as soon as the payment is in, we send the digital goodies he or she payed for (Component Dialog A)

To implement this, my idea is to combine proactive messages\events with an ActivityPrompt. I cannot get this to work however.

As soon as the webhook of the PSP sends a post request to webhook/payment, to let us know the payment is in, I would like to be able to send an event to be validated by the ActivyPrompt's validator. I got this idea by examining the ActivityPrompt testscenario's in Github (there is not much documentation about ActivityPrompt although it seems a powerful instrument)

// Listen for incoming payment status changes.
server.post('/webhook/payment', async (req, res) => {
    const conversationReference = conversationReferences[payment.metadata.id]; // conversationId is stored with payment transaction.
    await adapter.continueConversation(conversationReference, async turnContext => {
        adapter.send({ type: ActivityTypes.Event });  //adapter.send would be great but only works in test-environment?
        await turnContext.sendActivity('Payment is in :smile:');
    });
}
);

The event should result in ComponentDialogA to go to the next waterfall step and send the goodies the user ordered.

The waiting-for-payment prompt initialisation:

        this.addDialog(new ActivityPrompt(WAITING_FOR_PAYMENT_PROMPT, this.awaitingPaymentValidator));

the actual prompt

        return await stepContext.prompt(WAITING_FOR_PAYMENT_PROMPT, 'Waiting for payment ...');

the prompt validator

    async awaitingPaymentValidator(promptContext) {
        return (promptContext.context.activity.type === 'event');
    }

I tried multiple alternative approaches with validation prompts but I always end up in a situation where the user, after paying his invoice, has to do something to go the the next waterfall step. It works but is not what you would expect.

Is this even possible and if so, what am I missing? Or maybe an alternative approach? Ideas are appreciated

[Update] I have two more strategies to try:

  1. Creating a dialogcontext in proactive messages and hopefully I am able to end the waiting for payment prompt Dialog from there.
  2. Figure out how to leverage dialogContext.emitEvent in combication with an ActivityPrompt

Ad 1. Not working. dialogcontext created but DialogContext.endDialog does not end the prompt. -> https://stackoverflow.com/q/62940651/7095607

Ad 2. Tried it without success. I suspect this to be an adaptive dialog features that by accident found its way to the 'normal' dialog documentation.

Workaround: In stead of showing a proactive 'message', showing a button (contents based on status payment) for the user to click and move forward.

The workaround is ok for now but best option would be to go to next waterfall step.