Comment gérer DIRECT_LINE / POST_ACTIVITY_REJECTED

Nov 12 2020

J'implémente le chat Web avec un jeton basé sur la persistance du chat, tout fonctionne bien lorsque l'utilisateur est en ligne, mais après un certain temps d'inactivité si l'utilisateur est hors ligne sans connexion Internet, pendant environ 30 à 45 minutes, puis plus tard, il se reconnecte envoyer un SMS à tout bot est passé à l'état DIRECT_LINE / POST_ACTIVITY_REJECTED et l'utilisateur n'a pas pu discuter avec le bot, il a donné une nouvelle tentative sur ma bulle de message. Y a-t-il un moyen possible de gérer ?.

 (async function() {
    'use strict';
    const {
            hooks: { usePostActivity },
            hooks: { useDirection },
            ReactWebChat
    } = window.WebChat;
    
     let { token, conversation_Id } = sessionStorage;
    if ( !token ) {
                    const res = await fetch( 'https:/localhost/api/generateToken', { method: 'POST' } );
                    const { token: directLineToken, conversationId: conversationId } = await res.json();
                    sessionStorage[ 'token' ] = directLineToken;
                    sessionStorage[ 'conversation_Id' ] = conversationId;
                    token = directLineToken;
                    conversation_Id = conversationId;
                    }
                    
    if (token) {
        await setInterval(async () => {
        var myHeaders = new Headers();
        myHeaders.append("Authorization","Bearer "+ sessionStorage[ 'token' ]);
        let res = await fetch( 'https://directline.botframework.com/v3/directline/tokens/refresh', {
                                method: 'POST', 
                                headers: myHeaders,
                                });
        const { token: directLineToken, conversationId } = await res.json();
            sessionStorage[ 'token' ] = directLineToken;
            sessionStorage[ 'conversation_Id' ] = conversationId;
            token = directLineToken;
            conversation_Id = conversationId;
        }, 1000*60*15)}
        
                        
    
    
    const  store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
    if(action.payload && action.payload.directLine) {
        const subscription = action.payload.directLine.connectionStatus$.subscribe({
                error: error => console.log( error ),
                next: value => {
                        if ( value === 0 ) {console.log('Uninitialized')} 
                        else if ( value === 1 ) {console.log('Connecting')} 
                        else if ( value === 2 ) {console.log('Online')}
                        else if  ( value === 3 ) {console.log('Expire Token')}
                        else if ( value === 4 ) {console.log('FailedToConnect')}
                        else if ( value === 5 ) {console.log('Ended')}
                }
            });
        }
     if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
        dispatch({
                type: 'WEB_CHAT/SEND_EVENT',
                payload: {
                    name: 'Welcome',
                    value: { language: window.navigator.language }
                    }
                });
            }
            
    
    if (action.type === 'DIRECT_LINE/POST_ACTIVITY') {
                action = window.simpleUpdateIn(action, ['payload', 'activity', 'channelData', 'CustomChannel'], () =>"webchat");
                }
    
        return next(action);
    });
    
    
   const  botconnection = createDirectLine( {token,webSockets: true,watermark: "0" });
    
    window.ReactDOM.render(
    <ReactWebChat directLine={botconnection}
                  store={store}
        />,
        document.getElementById('webchat'));
        document.querySelector('#webchat > *').focus();
        })().catch(err => console.error(err));

Remarque: le jeton n'est pas expiré et si j'actualise, le robot de page commence à repondre.

Réponses

1 StevenKanberg Nov 17 2020 at 15:02

J'ai apporté quelques ajustements au code que vous avez fourni. Je crois que votre tokenvaleur était écrasée ou corrompue, j'ai donc séparé l'attribution du jeton dans l'appel API ( token) et l'attribution de variable dans le script ( dl_token).

J'obtenais également une erreur sur l'appel du jeton d'actualisation enveloppé dans la setInterval()fonction, c'est pourquoi j'utilise Babel, comme indiqué ci-dessous. (Pour les tests, cela aide à identifier les erreurs qui auraient autrement été manquées.). La suppression de l'appel d'API réel setInterval()et son appel en tant que fonction distincte semblait résoudre ce problème.

Après ces changements, tout semble bien fonctionner. Je n'ai testé que quelques fois en attendant les 45 à 50 minutes, mais je n'ai rencontré aucun problème avec le jeton, ni besoin d'être actualisé, ni de recevoir DIRECT_LINE/POST_ACTIVITY_REJECTED.

(Notez que j'ai passé des appels à mon propre serveur 'token' pour générer et actualiser le token.)

<script crossorigin="anonymous" src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>

<script type="text/babel" data-presets="es2015,react,stage-3">
  ( async function () {
    'use strict';
    const {
      ReactWebChat
    } = window.WebChat;

    let { dl_token, conversation_Id } = sessionStorage;
    
    if ( !dl_token ) {
      const res = await fetch( 'http://localhost:3500/directline/conversations', { method: 'POST' } );
      const { token, conversationId } = await res.json();
      sessionStorage[ 'dl_token' ] = token;
      sessionStorage[ 'conversation_Id' ] = conversationId;
      dl_token = token;
      conversation_Id = conversationId;
    }

    if ( dl_token === sessionStorage['dl_token'] ) {
      setInterval( () => {
        refreshToken()
      }, 1000 * 60 * 1 )
    }
    
    const refreshToken = async () => {
      const res = await fetch( 'http://localhost:3500/directline/refresh', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          token: dl_token
        })
      } );
      const { token, conversationId } = await res.json();
      sessionStorage[ 'dl_token' ] = token;
      sessionStorage[ 'conversation_Id' ] = conversationId;
      dl_token = token;
      conversation_Id = conversationId;
    }


    const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => action => {
      if ( action.payload && action.payload.directLine ) {
        const subscription = action.payload.directLine.connectionStatus$.subscribe( {
          error: error => console.log( error ),
          next: value => {
            if ( value === 0 ) { console.log( 'Uninitialized' ) }
            else if ( value === 1 ) { console.log( 'Connecting' ) }
            else if ( value === 2 ) { console.log( 'Online' ) }
            else if ( value === 3 ) { console.log( 'Expire Token' ) }
            else if ( value === 4 ) { console.log( 'FailedToConnect' ) }
            else if ( value === 5 ) { console.log( 'Ended' ) }
          }
        } );
      }
      if ( action.type === 'DIRECT_LINE/CONNECT_FULFILLED' ) {
        dispatch( {
          type: 'WEB_CHAT/SEND_EVENT',
          payload: {
            name: 'Welcome',
            value: { language: window.navigator.language }
          }
        } );
      }


      if ( action.type === 'DIRECT_LINE/POST_ACTIVITY' ) {
        action = window.simpleUpdateIn( action, [ 'payload', 'activity', 'channelData', 'CustomChannel' ], () => "webchat" );
      }

      return next( action );
    } );


    const botconnection = await createDirectLine( { token: dl_token } );

    window.ReactDOM.render(
      <ReactWebChat directLine={botconnection}
        store={store}
      />,
      document.getElementById( 'webchat' ) );
    document.querySelector( '#webchat > *' ).focus();
  } )().catch( err => console.error( err ) );
</script>

J'espère de l'aide!