Braintree多个设置调用在多个onPaymentMethodReceived事件中产生

时间:2015-05-18 22:26:43

标签: javascript angularjs braintree

我正在使用角度,在angularUI模式窗口中,我想显示Braintree的Drop In表单以获取付款方式。因此,我创建了通常的表单(partial.html):

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

然后我用这个显示模态:

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

ModalController包含对Braintree设置的调用:

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

这将很好地显示braintree的Drop In表单(设置生成表单)并接受信用卡和到期日期,到目前为止一切正常。

问题是,每次调用模态时,都会执行ModalController,因此也会执行braintree.setup()。然后,当我输入信用卡号码和到期日期并点击付款时,每次设置执行都会触发onPaymentMethodReceived()事件!也就是说,如果我第一次调用模态,它将触发事件一次,第二次触发它两次,依此类推。就像每次调用setup时一样,会创建一个新的事件挂钩。

有关如何避免这种情况的任何想法?有没有办法“解除绑定”onPaymentMethodReceived()事件处理程序?我需要多次调用设置,因为每次调用模态时,clientToken可能已经更改。

感谢您提供任何帮助或指示帮助。

3 个答案:

答案 0 :(得分:2)

以角度多次调用braintree.setup似乎是不可避免的,无论是出于提问者的原因,还是仅仅因为在可能在浏览会话中多次实例化的控制器中调用setup - 如购物车或结账控制器。

您可以这样做:

$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
           });
       }
   }
});

我发现我无法避免多次回调发射(每次重新访问视图时,次数似乎都会爆炸 - 但是我可以测试我是否已经执行了我的操作以响应打回来。 由于$scope将在我离开视图时被销毁,$scope.success会在我需要时被有效重置。因为每个新控制器都有自己的$scope },在success上设置$scope标志可能只会暂停$scope上的其他执行(即使控制器已被“销毁”,这似乎仍然可用于回调) ,所以我发现使用$rootScope只意味着一个执行总数,即使我多次重新实例化控制器。在控制器中设置$rootScope.success = false意味着一旦加载控制器,回调将重新成功 - 一次。

答案 1 :(得分:1)

我认为它是由API处理掉的,然后是拆解:

  

在某些情况下,您可能需要删除braintree.js集成。这在单页面应用程序,模态流程以及其中状态管理是关键因素的其他情况下很常见。 [...]   调用拆解将清除由集成创建的任何DOM节点,事件处理程序,弹出窗口和/或iframe。

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

(我还没试过)

答案 2 :(得分:1)

Arpad Tamas提供的链接不再包含该信息。所以我发布了BrainTree为后人提供的信息;)特别是因为我花了几次尝试用谷歌搜索找到它。

  

在某些情况下,您可能需要删除Braintree.js集成。这在单页面应用程序,模态流程以及其中状态管理是关键因素的其他情况下很常见。调用braintree.setup时,可以将回调附加到onReady,它将提供包含拆卸方法的对象。

     

调用拆除将清除由集成创建的所有DOM节点,事件处理程序,弹出窗口和/或iframe。此外,拆解接受回调,您可以使用回调来确定何时可以安全继续。

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!
});
  

每次.setup调用只能调用一次拆解。如果您在正在进行另一次拆解时碰巧调用此方法,则会收到错误消息,指出在进行中无法调用拆卸。完成后,后续的拆解调用将在此消息中引发错误:无法多次拆除集成。

我已将此代码包装在每次输入相关结帐离子视图时调用的函数中。

$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!
        });
    }
};