Search code examples
braintree

Not able to setup up a quick test for braintree example


We tried to setup a monthly subscription plan, using braintree.

We look at https://developers.braintreepayments.com/start/hello-client/javascript/v3

I download the following code snippet, and save it as a local HTML file in my machine. (I know I need to use a backend server, to generate token and the below HTML code snippet for client browser. I just want to do a quick test without setuping the server first.)

<head>
  <meta charset="utf-8">
  <script src="https://js.braintreegateway.com/web/dropin/1.12.0/js/dropin.min.js"></script>
</head>
<body>
  <div id="dropin-container"></div>
  <button id="submit-button">Request payment method</button>
  <script>
    var button = document.querySelector('#submit-button');

    braintree.dropin.create({
      authorization: 'CLIENT_TOKEN_FROM_SERVER',
      container: '#dropin-container'
    }, function (createErr, instance) {
      button.addEventListener('click', function () {
        instance.requestPaymentMethod(function (err, payload) {
          // Submit payload.nonce to your server
        });
      });
    });
  </script>
</body>

We click on the button. instance.requestPaymentMethod is being executed.

I expect client browser will start to communicate with braintree server, as issulrated as step 3. But it doesn't.

enter image description here

May I know is there any step I had missed out?


Solution

  • You need to setup proper backend server, in order to get front end code work. As, without a correct client_token (Generated from backend server), front end code will not work.

    Front end code will not give any sort of warning regarding incorrect client_token.

    Note, you will have a difficult time to setup backend server, as Braintree documentation is poorly written

    After spending 2 days straight, I post my code snippet, regarding monthly recurring billing.

    views.py

    from django.views.generic import TemplateView
    import braintree
    import json
    from django.shortcuts import redirect
    
    from pprint import pprint
    
    gateway = braintree.BraintreeGateway(
        braintree.Configuration(
            braintree.Environment.Sandbox,
            merchant_id="???",
            public_key="???",
            private_key="???"
        )
    )
    
    class PaymentMethodView(TemplateView):
        template_name = 'payment_method.html'
    
        def get_context_data(self, **kwargs):        
            # Call the base implementation first to get a context
            context = super(PaymentMethodView, self).get_context_data(**kwargs)
    
            subscribe = self.request.GET.get('subscribe')
    
            client_token = gateway.client_token.generate()     
    
            context['client_token_from_server'] = client_token
            return context
    
    
    class SubscribeView(TemplateView):
        template_name = 'subscribe.html'
    
        def get_context_data(self, **kwargs):
            # Call the base implementation first to get a context
            context = super(SubscribeView, self).get_context_data(**kwargs)
    
            payload_nonce = self.request.GET.get('payload_nonce')
    
            user = self.request.user
    
            result = gateway.customer.create({
                "email": user.email,
                "id": str(user.id),
                "payment_method_nonce": payload_nonce
            })
    
            if result.is_success:
                customer_id = result.customer.id
    
                payment_method_token = result.customer.payment_methods[0].token
    
                result = gateway.subscription.create({
                    "payment_method_token": payment_method_token,
                    "plan_id": "individual",
                })
            else:
                result = gateway.payment_method.create({
                    "customer_id": str(user.id),
                    "payment_method_nonce": payload_nonce
                })
    
                #pprint(vars(result))
    
                payment_method_token = result.payment_method.token
    
                result = gateway.subscription.create({
                    "payment_method_token": payment_method_token,
                    "plan_id": "individual",
                })
    
            context['is_success'] = result.is_success
    
            if result.is_success:
                print('success')
            else:
                for error in result.errors.deep_errors:
                    print(error.attribute)
                    print(error.code)
                    print(error.message)
    
            return context
    

    payment_method.html

    <head>
      <meta charset="utf-8">
      <script src="https://js.braintreegateway.com/web/dropin/1.12.0/js/dropin.min.js"></script>
    </head>
    <body>
      <div id="dropin-container"></div>
      <button id="submit-button">Request payment method</button>
      <script>
        var button = document.querySelector('#submit-button');
    
        braintree.dropin.create({
          authorization: '{{ client_token_from_server }}',
          container: '#dropin-container'
        }, function (createErr, instance) {
          button.addEventListener('click', function () {
            instance.requestPaymentMethod(function (err, payload) {
              // Submit payload.nonce to your server
              url = '{% url 'subscribe' %}' + '?payload_nonce=' + payload.nonce;
              window.location.replace(url);
            });
          });
        });
      </script>
    </body>
    

    Side note

    1. Different API calls, will yield different Result object but with different attributes. How do I know I need to call payment_method_token = result.payment_method.token to retrieve payment_method_token. No way you can tell by reading documentation. You need to perform debug on the result object, by using pprint(vars(result)). I will be very happy, if someone from Braintree can let me know, how can I lookup for such information, by reading documentation.

    2. The naming is poor and confusing. For instance, Merchant Account and Merchant Account Id are 2 different things.