Пытаюсь настроить Braintree Drop в пользовательском интерфейсе в моем приложении Symfony 4. (https://developers.braintreepayments.com/start/hello-client/javascript/v3, https://developers.braintreepayments.com/start/hello-server/php)
Я создал сервис:
namespace App\Services;
use Braintree\ClientToken;
use Braintree\Configuration;
class Braintree
{
// environment variables:
const ENVIRONMENT = 'BRAINTREE_ENVIRONMENT';
const MERCHANT_ID = 'BRAINTREE_MERCHANT_ID';
const PUBLIC_KEY = 'BRAINTREE_PUBLIC_KEY';
const PRIVATE_KEY = 'BRAINTREE_PRIVATE_KEY';
function __construct() {
Configuration::environment(getenv(self::ENVIRONMENT));
Configuration::merchantId(getenv(self::MERCHANT_ID));
Configuration::publicKey(getenv(self::PUBLIC_KEY));
Configuration::privateKey(getenv(self::PRIVATE_KEY));
}
//
public function generateNonce() {
return ClientToken::generate();
}
}
и я добавил форму и некоторый javascript в свой шаблон веточки:
{% block body %}
{{ parent() }}
<div class = "container">
<div class = "card">
<div class = "row">
<div class = "col-12">
<h3>Booking New</h3>
<div id = "datepicker"></div>
{{ form_start(bookingForm) }}
{{ form_widget(bookingForm) }}
<button type = "submit" class = "btn btn-primary">Create</button>
{{ form_end(bookingForm) }}
</div>
</div>
<div class = "row">
<div class = "col-12">
<form method = "post" id = "payment-form">
<section>
<label for = "amount">
<span class = "input-label">Amount</span>
<div class = "input-wrapper amount-wrapper">
<input id = "amount" name = "amount" type = "tel" min = "1" placeholder = "Amount" value = "10">
</div>
</label>
<div class = "bt-drop-in-wrapper">
<div id = "bt-dropin"></div>
</div>
</section>
<input id = "nonce" name = "payment_method_nonce" type = "hidden" />
<button class = "button" type = "submit"><span>Test Transaction</span></button>
</form>
<button id = "submit-button">Request payment method</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src = "https://js.braintreegateway.com/web/dropin/1.14.1/js/dropin.min.js"></script>
<script src = "https://code.jquery.com/jquery-1.12.4.js"></script>
<script src = "https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
var form = document.querySelector('#payment-form');
var client_token = "<?php echo($gateway->ClientToken()->generate()); ?>";
braintree.dropin.create({
authorization: client_token,
selector: '#bt-dropin',
paypal: {
flow: 'vault'
}
}, function (createErr, instance) {
if (createErr) {
console.info('Create Error', createErr);
return;
}
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.info('Request Payment Method Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
</script>
<script>
$( function() {
$( "#datepicker" ).datepicker();
} );
</script>
{% endblock %}
Когда я загружаю страницу, она не отображает форму Braintree, как я ожидал от braintree.dropin.create. Когда я нажимаю "Отправить", тоже ничего не происходит.
Как мне правильно настроить этот код?
Редактировать:
Проверил консоль:
Create Error
r
message: "There was an error creating Drop-in."
name: "DropinError"
_braintreeWebError: n {name: "BraintreeError", code: "CLIENT_INVALID_AUTHORIZATION", message: "Authorization is invalid. Make sure your client token or tokenization key is valid.", type: "MERCHANT", details: undefined}
__proto__: Error
Да, я добавил ошибку из консоли в OP.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Из вашей ошибки консоли я могу сделать вывод, что эта строка неверна:
var client_token = "<?php echo($gateway->ClientToken()->generate()); ?>";
Вместо использования блока php внутри вашего javascript вы должны сделать AJAX-запрос к своему бэкэнду, который вернет клиентский токен, который вы затем можете использовать в своей форме.
Рассмотрим этот пример:
// Set up our HTTP request
var xhr = new XMLHttpRequest();
// Setup our listener to process completed requests
xhr.onload = function () {
// Process our return data
if (xhr.status >= 200 && xhr.status < 300) {
var client_token = xhr.response.client_token; // Set your client token and use it later
} else {
// What do when the request fails
console.info('The request failed!');
}
// Code that should run regardless of the request status
console.info('This always runs...');
};
// Create and send a GET request
// The first argument is the post type (GET, POST, PUT, DELETE, etc.)
// The second argument is the endpoint URL
xhr.open('GET', '/route/to/braintree/controller'); // Create a Symfony route which will use `BraintreeService` and return generated client token.
xhr.send();
Это скорее псевдокод, но он должен дать вам общее представление о том, что вам следует делать. Судя по вашему коду, вы должны сначала получить этот client_token, а затем отрендерить форму.
Если проблема не в этом, продолжайте изучать эту ошибку консоли, это определенно причина, по которой вы не можете отобразить форму. Возможно, посетите документацию Braintree еще раз, у них есть отличные фреймворки и независимые от фреймворков примеры.
Спасибо. Итак, я должен создать маршрут в ProfileController пользователя (скажем, profile / braintree / generate_token) и передать ему мою службу Braintree, которую я создал, указав его в методе действия? Затем используйте свой js-код, чтобы получить client_token из этого маршрута? Звук в порядке?
Да что-то подобное. Общая идея правильная, как вы ее реализуете, зависит только от вас.
Есть ли что-нибудь в вашей консоли javascript, когда вы пытаетесь отобразить форму?