Я новичок в Stripe, поэтому просто следуйте документам stripe, чтобы настроить функцию подписки для моего веб-сайта. Я столкнулся с серьезными препятствиями и не могу найти никаких ресурсов или аналогичных вопросов для их решения. Любая помощь приветствуется.
Внешняя часть кода выглядит так, как будто выборка отправляет данные, но ее состояние остается «ожидающим». Таким образом, либо форма не отправляется, либо форма отправлена, но не получена на стороне сервера. Вот мой код внешнего интерфейса
<!-- HTML Form -->
{####################### CREDIT CARD (STRIPE) #######################}
{% if credit_card %}
<div class="credit-card">
<h3>Your Credit Card Information</h3>
<form id="subscription-form">{% csrf_token %}
<div id="card-element" class="MyCardElement">
<!-- Elements will create input elements here -->
</div>
<!-- We'll put the error messages in this element -->
<div id="card-errors" role="alert"></div>
<button type="submit" class="btn btn-primary btn-block mt-3">Subscribe</button>
</form>
</div>
{% endif %}
Затем в моей кассе. js файл:
var stripe = Stripe('<testPublishableKey>');
var elements = stripe.elements();
var submissionURL = document.querySelector("[data-redirect]").getAttribute('data-redirect');
var customerEmail = document.querySelector("[data-email]").getAttribute('data-email');
var style = {
base:
{
color: "#32325d",
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder":
{
color: "#aab7c4"
}
},
invalid:
{
color: "#fa755a",
iconColor: "#fa755a"
}
};
var cardElement = elements.create("card", { style: style });
cardElement.mount("#card-element");
cardElement.addEventListener('change', function(event)
{
var displayError = document.getElementById('card-errors');
if (event.error)
{
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
//********************************* SAVING THE CARD DATA *********************************//
var form = document.getElementById('subscription-form');
form.addEventListener('submit', function(event){
event.preventDefault();
stripe.createPaymentMethod( { type : 'card',
card : cardElement,
billing_details : { email : customerEmail, }
},
).then(stripePaymentMethodHandler);
});
function stripePaymentMethodHandler(result, email)
{
if (result.error)
{
console.log( Error(result.error) )
}
else
{
// Otherwise send paymentMethod.id to your server
fetch(submissionURL,
{
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(
{
email: customerEmail,
payment_method: result.paymentMethod.id,
}),
}).then(function(result)
{
console.log('Fetch sending to: ', submissionURL)
console.log('Fetch sent the data: ', result.json());
return result.json();
}).then(function(customer) {
console.log('customer: ', customer)
// The customer has been created
});
}
}
});
и в моем коде на стороне сервера Django:
class Checkout(View):
''' This does all the actual checkout. It renders a subscription form to choose the subsciption plan, automatic renewal, and monthly-annaully options.
It also renders the card form to process the payment
stripe publishable key for test API: pk_test_5SGXGVNC3T6gdoUw9qFoWrja00EsxxxiF2
'''
template_name = 'checkout.html'
MainForm = SubscriptionForm
def dispatch(self, *args, **kwargs):
return super(Checkout, self).dispatch(*args, **kwargs)
def get(self, request, *args, *kwargs):
...
def post(self, request, *args, **kwargs):
''' Receives the subscription form '''
stripe.api_key = stripe_publishable_key
plan = request.POST.get('plan', 'm')
automatic = request.POST.get('automatic', 'on')
payment_method = request.POST.get('payment_method', 'card')
data = json.loads(request.data)
## Creating a customer in stripe
customer_stripe = stripe.Customer.create( payment_method = intent.payment_method,
email = intent.email,
invoice_settings = { 'default_payment_method': intent.payment_method, },
)
## plan_id = <comes from the plan_id of the Stripe's dashboard>
subscription = stripe.Subscription.create( customer = customer.id, items = [{'plan': plan_id, }],
expand = ['latest_invoice.payment_intent'] )
## Creating the same customer for ourselves
user = request.user
user_company = user.company
customer, created = Customer.objects.get_or_create(company = user_company,
defaults = {
'company': user_company,
'membership': True,
'cancel_at_period_end': False,
})
return render(request, reverse('dashboard') )
Мне кажется, что в документации отсутствует много деталей:
- Я решил, что мне нужно использовать
data = json.loads(request.data)
, Документы Stripe не упоминают, как чтобы фактически загрузить данные или распаковать их в бэкэнд. intent.payment_method
упоминается, но нигде не определено намерение. Откуда в документации исходит намерение? - Я не могу определить сумму, которая будет снята с карты, кроме как на панели инструментов. Как я могу это сделать?
- Даже когда я вставляю
assert False
в свою первую строку обработчика сообщений, ничего не происходит, что может быть связано с извлечением. - И, наконец, когда я вхожу в console. log в части
.then()
, хотя я не получаю никаких ошибок, я также не получаю ничего, кроме Promise {<state>: "pending"}
. Заранее благодарим за вашу помощь
Edit 1: Я должен упомянуть, что, глядя на XHR в моем браузере, я вижу их при отправке формы:
Edit 2: Прочитав больше о fetch, я обнаружил, что, поскольку моя форма использует csrf-token, основанный на cook ie, мне нужно добавить 'X-CSRF-TOKEN': csrfToken
в заголовок моего вызова fetch внутри stripePaymentMethodHandler. Теперь это отражено в приведенном выше коде. StripePaymentMethodHandler теперь выдает ошибку, в которой написано if (result.error)
. При печати ошибки на консоли она отображается как Error: "[object Object]"
POSThttps://api.stripe.com/v1/payment_methods
[HTTP/2 200 OK 435ms]
XHRPOSThttp://localhost:8000/checkout
[HTTP/1.0 403 Forbidden 225ms]