【发布时间】:2021-07-15 19:06:28
【问题描述】:
我有一张由各种元素组成的付款表格。
我的问题是,新的条纹用户的卡直到提交表单后才注册。
我知道如果我的表单有一个新添加的地址,我可以使用 form.is_valid() 但如果我的地址是已经保存的地址,则不适用。但是有没有一种方法可以在表单提交后使用stripe.PaymentMethod.list 设置卡片,而不管 Django 表单是否是其中的一部分?
表格
<form method="POST" id="subscription-form" data-secret="{{client_secret}}">
{% csrf_token %}
<label class="block uppercase text-gray-600 text-xs font-bold mb-2">Payment Details</label>
{% if payment_methods %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="add-new-card"
value="add-new-card" onclick="addCard()" {%if payment_methods %} {%else%}checked="checked" {%endif%}
required>
<label class="form-check-label" for="add-new-card">
Add new payment method
</label>
<div id="new-card" style="display: none;">
<label class="block uppercase text-gray-600 text-xs mb-2" for="cardholder-name">
Name on Card
</label>
<input id="cardholder-name"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
value="{{customer.name}}" detype="text">
<!-- placeholder for Elements -->
<label class="block uppercase text-gray-600 text-xs mb-2" for="card-element">
Card Details
</label>
<div id="card-element"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-result"></div>
<div id="card-errors" class="my-2" role="alert"></div>
</div>
</div>
{% if saved_customer %}
{% for method in payment_methods %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="{{method.card}}"
value="{{method.id}}" onclick="hideCard()" {% if forloop.first %} checked="checked" {%endif%}>
<label class="form-check-label" for="{{method.card}}">
{{method.card.brand}} ending in {{method.card.last4}}
</label>
</div>
{% endfor %}
{% endif %}
{% else %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="add-new-card"
value="add-new-card" checked="checked"
required>
<label class="form-check-label" for="add-new-card">
Add new payment method
</label>
<div id="new-card">
<label class="block uppercase text-gray-600 text-xs mb-2" for="cardholder-name">
Name on Card
</label>
<input id="cardholder-name"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
value="{{customer.name}}" detype="text">
<!-- placeholder for Elements -->
<label class="block uppercase text-gray-600 text-xs mb-2" for="card-element">
Card Details
</label>
<div id="card-element"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-result"></div>
<div id="card-errors" class="my-2" role="alert"></div>
</div>
</div>
{% endif %}
<label class="block uppercase text-gray-600 text-xs font-bold mb-2">Address</label>
<div id="address-list">
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="addresses" id="new-address" value="new-address"
onclick="showAddress()" {%if addresses%} {%else%}checked="checked" {%endif%}>
<label class="form-check-label" for="new-address">
New Address
</label>
<span id="address-form"></span>
</div>
{% for address in addresses %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="addresses" id="{{address.id}}"
value="{{address.id}}" onclick="hideAddress()" {% if forloop.first %} checked="checked"
{%endif%} required>
<label class="form-check-label" for="{{address.id}}">
{{address.name}} - {{address.line_1}}
</label>
</div>
{% endfor %}
</div>
<input type="hidden" id="email" name='email' value='{{customer.email}}'>
<div>
<p class="text-xs">By confirming, you agree that you will be charged immediately, and then monthly for
this product until cancelled</p>
<button id="submit" type="submit"
class="w-full mt-2 bg-blue-300 text-blue-900 font-medium rounded p-3">Confirm
and Pay</button>
</div>
</form>
查看
@login_required
def subscription_new(request, product):
stripe.api_key = STRIPE_SECRET_KEY
title = "New Subscription for " + product
product = Product.objects.get(slug=product)
customer = Customer.objects.get(user=request.user.id)
addresses = Address.objects.filter(customer=customer)
current_day = datetime.date.today().day
# maintain order day in short months
if current_day > 28:
current_day = 1
stripe_amount = str(int(round(product.price, 2) * 100))
context = {
'title' : title,
'product' : product,
'customer' : customer,
'addresses' : addresses,
'current_day' : current_day,
'STRIPE_PUBLIC_KEY' : STRIPE_PUBLIC_KEY,
}
card = request.POST.get('payment-methods')
if customer.stripe_id:
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
context['saved_customer'] = True
context['payment_methods'] = payment_methods
else:
print('no stripe id ')
new_customer = stripe.Customer.create(name=customer.name, email=customer.email)
customer.stripe_id = new_customer.id
customer.save()
context['saved_customer'] = False
intent = stripe.SetupIntent.create(customer=customer.stripe_id)
client_secret = intent.client_secret
context['client_secret'] = client_secret
if request.method == 'POST':
print("method is post")
address = request.POST.get('addresses')
if address == 'new-address':
form = AddressForm(request.POST)
address = form.save(commit=False)
address.customer = customer
address.save()
else:
address = Address.objects.get(id=address)
if customer.stripe_id:
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
print("customer has id")
if card == "add-new-card":
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
new_card = payment_methods.data[0]
# context['client_secret'] = client_secret
subscription = Subscription.objects.create(customer=customer, product=product, address=address, renewal_day=current_day, payment_method=new_card.id)
msg = 'Subscription created'
else:
subscription = Subscription.objects.create(customer=customer, product=product, address=address, renewal_day=current_day, payment_method=card)
msg = 'Subscription created'
messages.success(request, msg)
# If method is not post
else:
form = AddressForm()
context['form'] = form
return render(request, 'accounts/subscription_new.html', context)
【问题讨论】:
标签: django django-views django-forms