PayPal付款后如何提交地址和付款详情的数据
Posted
技术标签:
【中文标题】PayPal付款后如何提交地址和付款详情的数据【英文标题】:How to submit data for the address and payment details after PayPal payment is made 【发布时间】:2021-01-15 15:43:49 【问题描述】:我最近在我的项目中集成了一个 PayPal 付款选项,并且对于购物车中的物品数量而言一切正常,除了在付款后物品仍留在购物车中并且没有通知后端付款.
我的问题是如何设置地址的提交以及在签出模板中所做的所有详细信息以及支付的金额以反映在后端。
这里是views.py
class CheckoutView(View):
def get(self, *args, **kwargs):
try:
order = Order.objects.get(user=self.request.user, ordered=False)
form = CheckoutForm()
context =
'form': form,
'couponform': CouponForm(),
'order': order,
'DISPLAY_COUPON_FORM': True
shipping_address_qs = Address.objects.filter(
user=self.request.user,
address_type='S',
default='True'
)
if shipping_address_qs.exists():
context.update(
'default_shipping_address': shipping_address_qs[0])
billing_address_qs = Address.objects.filter(
user=self.request.user,
address_type='B',
default='True'
)
if billing_address_qs.exists():
context.update(
'default_billing_address': billing_address_qs[0])
return render(self.request, "checkout.html", context)
except ObjectDoesNotExist:
messages.info(self.request, "You do not have an active order")
return redirect("core:checkout")
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user=self.request.user, ordered=False)
if form.is_valid():
use_default_shipping = form.cleaned_data.get(
'use_default_shipping')
if use_default_shipping:
print("Using the defualt shipping address")
address_qs = Address.objects.filter(
user=self.request.user,
address_type='S',
default=True
)
if address_qs.exists():
shipping_address = address_qs[0]
order.shipping_address = shipping_address
order.save()
else:
messages.info(
self.request, "No default shipping address available")
return redirect('core:checkout')
else:
print("User is entering a new shipping address")
shipping_address1 = form.cleaned_data.get(
'shipping_address')
shipping_address2 = form.cleaned_data.get(
'shipping_address2')
shipping_province = form.cleaned_data.get(
'shipping_province')
shipping_country = form.cleaned_data.get(
'shipping_country')
shipping_postal_code = form.cleaned_data.get(
'shipping_postal_code')
shipping_phone_number = form.cleaned_data.get(
'shipping_phone_number')
if is_valid_form([shipping_address1, shipping_province, shipping_country, shipping_postal_code,
shipping_phone_number]):
shipping_address = Address(
user=self.request.user,
street_address=shipping_address1,
apartment_address=shipping_address2,
province=shipping_province,
country=shipping_country,
postal_code=shipping_postal_code,
phone_number=shipping_phone_number,
address_type='S'
)
shipping_address.save()
order.shipping_address = shipping_address
order.save()
set_default_shipping = form.cleaned_data.get(
'set_default_shipping')
if set_default_shipping:
shipping_address.default = True
shipping_address.save()
else:
messages.info(
self.request, "Please fill in the required shipping address fields")
use_default_billing = form.cleaned_data.get(
'use_default_billing')
same_billing_address = form.cleaned_data.get(
'same_billing_address')
if same_billing_address:
billing_address = shipping_address
billing_address.pk = None
billing_address.save()
billing_address.address_type = 'B'
billing_address.save()
order.billing_address = billing_address
order.save()
elif use_default_billing:
print("Using the default billing address")
address_qs = Address.objects.filter(
user=self.request.user,
address_type='B',
default='True'
)
if address_qs.exists():
billing_address = address_qs[0]
order.billing_address = billing_address
order.save()
else:
messages.info(
self.request, "No default billing address available")
return redirect('core:checkout')
else:
print("User is entering a new billing address")
billing_address1 = form.cleaned_data.get(
'billing_address')
billing_address2 = form.cleaned_data.get(
'billing_address2')
billing_province = form.cleaned_data.get(
'billing_province')
billing_country = form.cleaned_data.get(
'billing_country')
billing_postal_code = form.cleaned_data.get(
'billing_postal_code')
billing_phone_number = form.cleaned_data.get(
'billing_phone_number')
if is_valid_form([billing_address1, billing_province, billing_country, billing_postal_code,
billing_phone_number]):
billing_address = Address(
user=self.request.user,
street_address=billing_address1,
apartment_address=billing_address2,
province=billing_province,
country=billing_country,
postal_code=billing_postal_code,
phone_number=billing_phone_number,
address_type='B'
)
billing_address.save()
order.billing_address = billing_address
order.save()
set_default_billing = form.cleaned_data.get(
'set_default_billing')
if set_default_billing:
billing_address.default = True
billing_address.save()
else:
messages.info(
self.request, "Please fill in the required billing address fields")
return redirect('core:checkout')
payment_option = form.cleaned_data.get('payment_option')
if payment_option == 'S':
return redirect('core:payment', payment_option='stripe')
elif payment_option == 'P':
return redirect('core:payment', payment_option='paypal')
else:
messages.warning(
self.request, "Invalid payment option selected")
return redirect('core:checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect("core:order-summary")
class PaymentView(View):
def get(self, request, payment_option):
order = Order.objects.get(user=request.user, ordered=False)
if order.billing_address:
context =
'order': order,
'DISPLAY_COUPON_FORM': False,
'payment_method': payment_option,
return render(self.request, "payment.html", context)
else:
messages.warning(
self.request, "You have not added a billing address")
return redirect("core:checkout")
# `source` is obtained with Stripe.js; see https://stripe.com/docs/payments/accept-a-payment-charges#web-create
# -token
def post(self, *args, **kwargs):
order = Order.objects.get(user=self.request.user, ordered=False)
token = self.request.POST.get('stripeToken')
amount = int(order.grand_total() * 100)
try:
charge = stripe.Charge.create(
amount=amount, # cents
currency="usd",
source=token,
)
# create payment
payment = Payment()
payment.stripe_charge_id = charge['id']
payment.user = self.request.user
payment.amount = order.grand_total()
payment.save()
# assign the payment to the order
order_items = order.items.all()
order_items.update(ordered=True)
for item in order_items:
item.save()
order.ordered = True
order.payment = payment
order.ref_code = create_ref_code()
order.save()
messages.success(self.request, "Your Order was Successful ! ")
---------------error messages------------------------------------
这里是paypal支付页面
% if payment_method == 'stripe' %
-----------------stripe payment-------------------
% elif payment_method == 'paypal' %
<head>
<!-- Add meta tags for mobile and IE -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
</head>
<body>
<main class="mt-5 pt-4">
<div class="container wow fadeIn" style="margin-top: 54px; text-align: center">
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
<!-- Include the PayPal javascript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=sb¤cy=USD"></script>
<script>
var total=' order.grand_total|floatformat:2 '
// Render the PayPal button into #paypal-button-container
paypal.Buttons(
// Set up the transaction
createOrder: function(data, actions)
return actions.order.create(
purchase_units: [
amount:
value: parseFloat(total).toFixed(2)
]
);
,
// Finalize the transaction
onApprove: function(data, actions)
return actions.order.capture().then(function(details)
submitFormData()
);
).render('#paypal-button-container');
</script>
</div>
</main>
</body>
% endif %
【问题讨论】:
【参考方案1】:您应该使用django-paypal 包来执行此操作。 使用 Paypal IPN 时,paypal 会向 Django 发送一个信号,然后您需要处理该信号。使用它可以让您清空购物车等。
【讨论】:
【参考方案2】:正如其他答案提到的,您需要 IPN(即时付款通知)。付款确认在 paypal 中异步发生(他们有时间审查付款以进行欺诈检测并取消它)。
您需要将内部交易 ID 传递给贝宝。在您的系统上设置一个 ipn 路由端点,一旦付款确认,paypal 将 ping 并显示成功消息。
详情看这里https://developer.paypal.com/docs/api-basics/notifications/ipn/#
【讨论】:
【参考方案3】:遇到了类似的问题……我花了很长时间才弄明白(但仍然不完全确定)……
我相信您使用了错误的代码。对于服务器端实现,请改用: https://developer.paypal.com/demo/checkout/#/pattern/server
注意:post 路由(createOrder、onApprove)允许您添加一个带有表单数据的请求正文,您可以将其发送到您的服务器。此外,我更改了代码以使用 axios(非常简单)。包括这里的小片段..
// Call your server to finalize the transaction
onApprove: function(data, actions)
return axios.post('http://localhost:3900/api/paypal/orders/' + data.orderID + '/capture/',
firstName: 'Tom',
lastName: 'Smith',
email: 'test@test.com'
)
.then(fun……….
在服务器上,我将这个用于 createOrder 路由 https://developer.paypal.com/docs/checkout/reference/server-integration/set-up-transaction/
还有这个用于 onApprove 路线https://developer.paypal.com/docs/checkout/reference/server-integration/capture-transaction/
您还需要下载 paypals sdk 并为您的凭据设置一个小文件。这是复制/粘贴,只需将您的 clientId + clientSecret 放入。https://developer.paypal.com/docs/checkout/reference/server-integration/setup-sdk/
然后在服务器上,当您从 pp 获得订单已捕获的 ok 时,您可以将表单数据保存到您的数据库。
不完全确定这是否是正确的方法。很难弄清楚……
关于 IPN 的旁注,我知道上述方法不需要。请参阅 Preston PHX 的回答Paypal and digital downloads with woocommerce: PDT or IPN? Or is there a tutorial on how to implement both?
【讨论】:
以上是关于PayPal付款后如何提交地址和付款详情的数据的主要内容,如果未能解决你的问题,请参考以下文章