2015-05-18 18 views
10

Sto usando angolare, e in una finestra modale UI angolare voglio mostrare il modulo Drop In da Braintree per ottenere un metodo di pagamento. Così, creo la forma usuale (partial.html):Le chiamate multiple a Braintree si traducono in più eventi onPaymentMethodRicevuti

<form id="creditCard" > 
    <div id="dropin"></div> 
    <button type="submit" id="btnPay" >Pay</button> 
</form> 

e poi mostro il modal con questo:

var modalInstance = $modal.open({ 
    templateUrl: 'partial.html', 
    controller: 'ModalController' 
}); 

Dove ModalController contiene la chiamata al setup Braintree:

braintree.setup($scope.clientToken, 'dropin', { 
    container: 'dropin', 
    onPaymentMethodReceived: function (result) { 
     $scope.$apply(function() { 
      $scope.success = true; 
      // Do something else with result 
     }); 
    } 
}); 

Questo mostrerà il modulo Drop In da braintree graziosamente (l'installazione genera il modulo) e accetta la carta di credito e la data di scadenza, tutte funzionanti fino ad ora.

Il problema è che, ogni volta che si chiama il modale, viene eseguito il ModalController, quindi viene eseguito anche il braintree.setup(). Quindi, quando inserisco il numero della carta di credito e la data di scadenza e paghi il pagamento, l'evento onPaymentMethodReceived() viene attivato una volta per l'esecuzione della configurazione! Cioè, se la prima volta chiamo il modale, innescherà l'evento una volta, la seconda lo attiverà due volte e così via. Come se ogni volta che chiamo setup, viene creato un nuovo hook per l'evento.

Qualche idea su come evitare questo? C'è un modo per "dissipare" il gestore di eventi onPaymentMethodReceived()? Ho bisogno di chiamare l'installazione più volte poiché ogni volta che chiamo il modale, il clientToken potrebbe essere cambiato.

Grazie per qualsiasi aiuto o puntatore per aiutare.

+0

Lavoro a Braintree. Stiamo lavorando per migliorare questo; al momento non esiste una soluzione semplice e completa. Se [entri in contatto con il nostro team di supporto] (https://support.braintreepayments.com/) dovrebbe essere in grado di aiutarti. – agf

+1

Qualsiasi aggiornamento su questo, @agf? –

risposta

2

Chiamare braintree.setup più volte in angolare sembra inevitabile, sia per ragioni del richiedente, o semplicemente perché setup viene chiamato in un controller che può essere istanziato più volte in una sessione di navigazione - come un carrello o un controller di checkout.

Si può fare qualcosa di simile:

$rootScope.success = false; 
braintree.setup($scope.clientToken, 'dropin', { 
    container: 'dropin', 
    onPaymentMethodReceived: function (result) { 
     if(!$rootScope.success) { 
      $scope.$apply(function() { 
       $rootScope.success = true; 
       // Do something else with result 
      }); 
     } 
    } 
}); 

ho scoperto che non ero in grado di evitare che i callback di fuoco più volte (il numero di volte sembra esplodere ogni volta che rivisitare la vista - yikes) , ma potrei verificare se avevo eseguito le mie azioni in risposta al callback. Poiché il $scope verrà distrutto se lascio la vista, $scope.success viene ripristinato in modo efficace quando ne ho bisogno. Poiché ogni nuovo controller avrà il proprio $scope, l'impostazione di un flag success su $scope potrebbe interrompere solo le esecuzioni aggiuntive su quello $scope (che sembra essere ancora disponibile per la richiamata, anche se il controller è stato "distrutto"), quindi trovato che usare $rootScope significava solo un totale di esecuzione, anche se avessi riattivato il controller più volte. L'impostazione di $rootScope.success = false nel controller significa che una volta che il controller è stato caricato, il callback avrà esito positivo - una volta.

+0

Il modo corretto per farlo ora è con il [metodo '' teardown'] (https://developers.braintreepayments.com/reference/client-reference/javascript/v2/best-practices#teardown), aggiunto dopo questa discussione. –

1

Penso che sia gestita dalle API da allora con teardown:

In alcuni scenari potrebbe essere necessario rimuovere l'integrazione braintree.js. Questo è comune nelle applicazioni a pagina singola, nei flussi modali e in altre situazioni in cui la gestione dello stato è un fattore chiave. [...] L'invocazione di teardown ripulirà qualsiasi nodo DOM, gestore di eventi, popup e/o ifram creati dall'integrazione.

https://developers.braintreepayments.com/guides/client-sdk/javascript/v2#teardown

(non ho ancora provato)

1

Il legame data dal Arpad Tamas non contiene più le informazioni. Quindi sto postando le informazioni fornite da BrainTree per i posteri;) Soprattutto perché mi ci sono voluti alcuni tentativi per trovarlo con una ricerca su Google.

In alcuni scenari potrebbe essere necessario rimuovere l'integrazione con Braintree.js. Questo è comune nelle applicazioni a pagina singola, nei flussi modali e in altre situazioni in cui la gestione dello stato è un fattore chiave. Quando si chiama braintree.setup, è possibile associare un callback a onReady che fornirà un oggetto contenente un metodo di rimozione.

L'invocazione di teardown elimina tutti i nodi DOM, i gestori di eventi, i popup e/o gli ifram creati dall'integrazione. Inoltre, teardown accetta una callback che puoi usare per sapere quando è sicuro procedere.

var checkout; 

braintree.setup('CLIENT_TOKEN_FROM_SERVER', 'dropin', { 
    onReady: function (integration) { 
    checkout = integration; 
    } 
}); 

// When you are ready to tear down your integration 
checkout.teardown(function() { 
    checkout = null; 
    // braintree.setup can safely be run again! 
}); 

È possibile richiamare solo teardown una volta per chiamata .setup. Se ti capita di chiamare questo metodo mentre è in corso un altro teardown, riceverai un messaggio di errore Impossibile chiamare teardown mentre sei in corso. Una volta completato, le successive chiamate a teardown genereranno un errore con questo messaggio: Impossibile eseguire l'integrazione di Teardown più di una volta.

Ho avvolto questo codice in una funzione che chiamo ogni volta che viene immessa la vista ionica di checkout correlata.

$scope.$on('$ionicView.enter', function() { 
    ctrl.setBraintree(CLIENT_TOKEN_FROM_SERVER); 
}); 

var checkout; 

ctrl.setBrainTree = function (token) { 
    braintree.setup(token, "dropin", { 
     container: "dropin-container", 

     onReady: function (integration) { 
      checkout = integration; 
      $scope.$emit('BTReady'); 
     }, 

     onPaymentMethodReceived: function(result) { 
      ... 
     }, 

     onError: function(type) { 
      ... 
     } 
    }); 

    // Prevents a call to checkout when entering the view for the first time (not initialized yet). 
    if (checkout) { 
    // When you are ready to tear down your integration 
     checkout.teardown(function() { 
      checkout = null; // braintree.setup can safely be run again! 
     }); 
    } 
}; 
Problemi correlati