The checkout page and Braintree integration

We are going to receive payments from two sources: PayPal and credit/debit cards. We are going to use the Braintree services to collect payments from both sources. For that, we are going to use braintree-angular. Let's install it:

bower install braintree-angular#1.3.1 --save

Then add it to our app dependencies:

angular.module('meanshopApp', [
  'ngCookies',
  'ngResource',
  'ngSanitize',
  'btford.socket-io',
  'ui.router',
  'ui.bootstrap',
  'ngFileUpload',
  'ngCart',
  'braintree-angular'
])

Now that we have the route, let's create the template and the controller. The following is the content for the template:

<!-- client/app/products/templates/products-checkout.html -->

<navbar></navbar>

<div class="container">
  <div class="row">
    <h1>Cart</h1>
    <ngcart-cart template-url="components/ngcart/cart.html"></ngcart-cart>
  </div>

  <div class="row">
    <h1>Choose a payment method</h1>
    <p class="help-block">{{ errors }}</p><br>
    <div class="col-md-6">
      <form>
        <braintree-dropin options="paymentOptions">Loading...</braintree-dropin>
        <input type="submit" value="Purchase" />
      </form>
    </div>
  </div>
</div>

<footer></footer>

We are using the braintree-dropin directive to render the default card forms and the PayPal button. This form is going to take care of the validations and security.

Braintree has a workflow different from the other payment platforms. This is how it is going to work in our app:

  1. Angular app will request a client token from our node backend.
  2. The node backend will use the Braintree SDK to generate a client token and reply with it.
  3. The Angular app will use the client token and the PayPal/card information to get authorization from the Braintree servers. The Braintree servers will generate a nonce, which is sent back to the Angular app.
  4. The Angular app will then send the nonce to the node backend to finish executing the payment operation.

All the Angular steps are going to be added in products.controller.js:

/* client/app/products/products.controller.js:35 */

.constant('clientTokenPath', '/api/braintree/client_token')

.controller('ProductCheckoutCtrl',
  function($scope, $http, $state, ngCart){
  $scope.errors = '';

  $scope.paymentOptions = {
    onPaymentMethodReceived: function(payload) {
      angular.merge(payload, ngCart.toObject());
      payload.total = payload.totalCost;
      console.error(payload);
      $http.post('/api/orders', payload)
      .then(function success () {
        ngCart.empty(true);
        $state.go('products');
      }, function error (res) {
        $scope.errors = res;
      });
    }
  };
});

We add a constant with the path to get the client token. We are going to create that controller in our backend later.

In the scope, we defined a couple of things that we are already using in the checkout page such as errors and paymentOptions. In paymentOptions, we are adding a callback that is going to be executed when the user provides his/her credit card number or PayPal authorization. If the authorization is successful, the payload parameter gets a nonce parameter, which will be used to execute the payment on the NodeJS side. Notice that we are also serializing the shopping cart, and adding/merging it to the payload. Finally, we create an order in our backend using the payload information. If we are able to collect the payment in the backend, we redirect the user to the marketplace and empty the cart; otherwise, we present an error message.

If you run the application (grunt serve), you will notice that we can add and remove items from the shopping cart. However, when we enter our card data, we are unable to complete the transaction, as the route /api/orders is not created yet. Let's move to the backend and work on that next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.142.248