Integrace Braintree

Nejdříve se musíte zaregistrovat. Registrace je provedena na testovacím prostředí, které je zdarma. Pro produkční účely se musíte zaregistrovat na produkčním prostředí.

Jakmile dokončíte registraci, vytvořte soubor index.html a zkopírujte do něj kompletní kód ukázky v sekci níže.
Celý soubor interaktivní ukázky naleznete v repozitáři  Apicart Payments na Githubu.

Jak to funguje

První část kódu obsahuje 3 bloky. První viditelný blok je blok s formulářem. Druhý blok obsahuje kontejner pro Braintree UI. Třetí blok obsahuje signalizaci probíhající platby.

První forulář s cenou, jménem a příjmením zde slouží pouze jako interaktivní prvek. Data do platebních requestů můžete použít odkudkoliv.

<div class="my-5">
  <form class="order-form">
    <p class="form-group">
      <label for="price" class="">Price:</label>
      <input type="number" name="price" value="100" min="0" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="firstName" class="">First name:</label>
      <input type="text" name="firstName" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="lastName" class="">Last name:</label>
      <input type="text" name="lastName" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="email" class="">Email:</label>
      <input type="email" name="email" class="form-control" required>
    </p>
    <p><input type="submit" value="Finish order" class="btn btn-primary"></p>
  </form>

  <div class="braintree-container-wrapper d-none">
    <div class="braintree-container"></div>
    <p>
      <button class="braintree-submit-payment btn btn-primary btn-lg">Submit payment</button>
    </p>
  </div>

  <div class="payment-progress-wrapper d-none">
    <div class="d-flex flex-column align-items-center">
      <h1>Processing payment</h1>
      <div class="loader"></div>
    </div>
  </div>
</div>

Abyste mohli začít používat Apicart Payment společně s Braintree UI, je potřeba načíst závislosti.

<script src="https://js.braintreegateway.com/web/dropin/1.22.1/js/dropin.min.js"></script>
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<script src="https://cdn.jsdelivr.net/gh/apicart/packages-js@master/packages/core-sdk/dist/core.js"></script>
<script src="https://cdn.jsdelivr.net/gh/apicart/packages-js@master/packages/payments-sdk/dist/payments.js"></script>

Jakmile jsou závisloti načteny, můžeme inicializovat Apicart Payments a přidat posluchače na  formulář s údaji o zákazníkovi a ceně.

Při odeslání formuláře je odeslán request pro získání klíče pro zákazníka a jeho platbu. Pokud request skončí úspěšně, provede se inicializace Braintree UI.

Braintree UI je inicializováno s callbackem, ve kterém je posluchač, která čeká na odeslání formuláře s informacemi o platební metodě. Jakmile je odeslán, zavolá se funkce sendPayment.

Uvnitř funkce se získají data z formuláře a předají se jako hodnoty do parametrů platebního požadavku, který bude odeslán k nám na API (pro zjednodušení ukázka obsahuje pouze několik potřebných parametrů). Jako další krok je odeslán požadavek s platbou. Pokud požadavek proběhne úspěšně, okno s ukázkou se přenačte. Jinak se zobrazí výchozí formulář abyste mohli zkusit provést platbu znovu.

<script>
  Apicart.setDevEnv();
  const payments = new Apicart.Payments({ token: 'Q84lNQyLl?nBGvKxxbcdc!nWFKEZrK?L_Is2r9IaOJo14ONbXw1SMlPIeptcaFza' });
  const orderForm = document.querySelector('.order-form');
  const braintreeContainerWrapper = document.querySelector('.braintree-container-wrapper');
  const braintreeFormSubmitButton = document.querySelector('.braintree-submit-payment');
  const paymentProgressForm = document.querySelector('.payment-progress-wrapper');

  const processForm = async (e) => {
    e.preventDefault();
    const response = await payments.gatewayAction('braintree', 'clientToken');

    if (response.status === 'DONE') {
      initBraintree(response.data);
    } else {
      alert('Error during the payment: ' + response.description);
    }
  };

  const initBraintree = async (data) => {
    orderForm.classList.add('d-none');
    braintreeContainerWrapper.classList.remove('d-none');

    braintree.dropin.create({
      authorization: data.clientToken,
      container: '.braintree-container',
      paypal: {
        flow: 'vault'
      }
    }, function (createErr, instance) {
      braintreeFormSubmitButton.addEventListener('click', () => {
        instance.requestPaymentMethod((requestPaymentMethodErr, payload) => {
          if (requestPaymentMethodErr) {
            alert('Payment failed. Error "' + requestPaymentMethodErr + '"');
            return;
          }

          sendPayment(payload.nonce);
        });
      });
    });
  };

  const sendPayment = async (paymentNonce) => {
    braintreeContainerWrapper.classList.add('d-none');
    paymentProgressForm.classList.remove('d-none');
    const formData = new FormData(orderForm);
    const currency = 'EUR';
    const variableSymbol = '123';
    const amount = formData.get('price') * 100; // Every price must be mulitplied by 100

    const response = await payments.pay('braintree', 'nonce', variableSymbol, {
      amount: amount,
      nonce: paymentNonce,
      customer: {
        email: formData.get('email'),
        firstName: formData.get('firstName'),
        lastName: formData.get('lastName')
      }
    });

    if (response.status === 'DONE') {
      alert('Your order was successfully paid.');
      window.location.href = window.location.href;
    } else {
      alert('Error during the payment: ' + response.description);
      paymentProgressForm.classList.add('d-none');
      orderForm.classList.remove('d-none');
    }
  };

  orderForm.addEventListener('submit', processForm);
</script>

Kompletní kód

Níže je uveden celý kód jehož části byly popsány výše.

<div class="my-5">
  <form class="order-form">
    <p class="form-group">
      <label for="price" class="">Price:</label>
      <input type="number" name="price" value="100" min="0" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="firstName" class="">First name:</label>
      <input type="text" name="firstName" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="lastName" class="">Last name:</label>
      <input type="text" name="lastName" class="form-control" required>
    </p>
    <p class="form-group">
      <label for="email" class="">Email:</label>
      <input type="email" name="email" class="form-control" required>
    </p>
    <p><input type="submit" value="Finish order" class="btn btn-primary"></p>
  </form>

  <div class="braintree-container-wrapper d-none">
    <div class="braintree-container"></div>
    <p>
      <button class="braintree-submit-payment btn btn-primary btn-lg">Submit payment</button>
    </p>
  </div>

  <div class="payment-progress-wrapper d-none">
    <div class="d-flex flex-column align-items-center">
      <h1>Processing payment</h1>
      <div class="loader"></div>
    </div>
  </div>
</div>

<script src="https://js.braintreegateway.com/web/dropin/1.22.1/js/dropin.min.js"></script>
<script src="https://www.paypalobjects.com/api/checkout.js" data-version-4></script>
<script src="https://cdn.jsdelivr.net/gh/apicart/packages-js@master/packages/core-sdk/dist/core.js"></script>
<script src="https://cdn.jsdelivr.net/gh/apicart/packages-js@master/packages/payments-sdk/dist/payments.js"></script>
<script>
  Apicart.setDevEnv();
  const paymentsToken = 'Q84lNQyLl?nBGvKxxbcdc!nWFKEZrK?L_Is2r9IaOJo14ONbXw1SMlPIeptcaFza';
  const payments = new Apicart.Payments({ token: paymentsToken });
  const orderForm = document.querySelector('.order-form');
  const braintreeContainerWrapper = document.querySelector('.braintree-container-wrapper');
  const braintreeFormSubmitButton = document.querySelector('.braintree-submit-payment');
  const paymentProgressForm = document.querySelector('.payment-progress-wrapper');

  const processForm = async (e) => {
    e.preventDefault();
    const response = await payments.gatewayAction('braintree', 'clientToken');

    if (response.status === 'DONE') {
      initBraintree(response.data);
    } else {
      alert('Error during the payment: ' + response.description);
    }
  };

  const initBraintree = async (data) => {
    orderForm.classList.add('d-none');
    braintreeContainerWrapper.classList.remove('d-none');

    braintree.dropin.create({
      authorization: data.clientToken,
      container: '.braintree-container',
      paypal: {
        flow: 'vault'
      }
    }, function (createErr, instance) {
      braintreeFormSubmitButton.addEventListener('click', () => {
        instance.requestPaymentMethod((requestPaymentMethodErr, payload) => {
          if (requestPaymentMethodErr) {
            alert('Payment failed. Error "' + requestPaymentMethodErr + '"');
            return;
          }

          sendPayment(payload.nonce);
        });
      });
    });
  };

  const sendPayment = async (paymentNonce) => {
    braintreeContainerWrapper.classList.add('d-none');
    paymentProgressForm.classList.remove('d-none');
    const formData = new FormData(orderForm);
    const currency = 'EUR';
    const variableSymbol = '123';
    const amount = formData.get('price') * 100; // Every price must be mulitplied by 100

    const response = await payments.pay('braintree', 'nonce', variableSymbol, {
      amount: amount,
      nonce: paymentNonce,
      customer: {
        email: formData.get('email'),
        firstName: formData.get('firstName'),
        lastName: formData.get('lastName')
      }
    });

    if (response.status === 'DONE') {
      alert('Your order was successfully paid.');
      window.location.href = window.location.href;
    } else {
      alert('Error during the payment: ' + response.description);
      paymentProgressForm.classList.add('d-none');
      orderForm.classList.remove('d-none');
    }
  };

  orderForm.addEventListener('submit', processForm);
</script>

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<style>
  /* https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_loader */
  .loader {
    border: 16px solid #f3f3f3;
    border-radius: 50%;
    border-top: 16px solid #3498db;
    width: 120px;
    height: 120px;
    -webkit-animation: spin 2s linear infinite;
    /* Safari */
    animation: spin 2s linear infinite;
  }

  @-webkit-keyframes spin {
    0% {
      -webkit-transform: rotate(0deg);
    }
    100% {
      -webkit-transform: rotate(360deg);
    }
  }

  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  }
</style>

Konfigurace platební brány Braintree

Pokud si zkopírujete kompletní kód výše do souboru index.html mezi tagy <body></body> a otevřete ho v prohlížeči (musíte být alespo na http://localhost, jinak PayU vaše requesty zablokuje) měli byste vidět platební formulář.

Veškeré odeslané platby z tohoto formuláře používají Apicart Sandbox tokeny. Abyste mohli používat svoje tokeny a vidět své statistiky v administraci Braintree, je potřeba si nastavit platební metody u nás v adminu.

Takže si pojďme přidat platební metodu Braintree.

Vytvořte si e-shop do 5 minut

Zkuste to. Je to zdarma.