首页 > 解决方案 > 在支付系统中添加条件以包括 PayPal

问题描述

我正在尝试将 PayPal 集成到我的电子商务项目中,因此在将商品添加到购物车后,结帐流程如下:

现在,当用户在此模板中选择它指向的条纹时,core:payment我正在尝试添加一个条件,以便如果选择的付款选项是贝宝,则显示贝宝图标而不是条纹支付表单。

我的问题是如何添加一个条件,以便如果选择的付款选项是条纹,则会出现下面的模板,如果选择了 paypal 选项,则会出现 paypal 部分。

这是models.py

class Payment(models.Model):
    stripe_charge_id = models.CharField(max_length=50)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.SET_NULL, blank=True, null=True)
    amount = models.FloatField()
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user.username

这是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 codes-----------------------------

                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")

这是 url.py

urlpatterns = [
    path('payment/<payment_option>/', PaymentView.as_view(), name='payment'),

这是模板

  <!------------Add an if statmenet if the stripe option is selected the below shows------------------>
  <main class="mt-5 pt-4">
    <div class="container wow fadeIn">

      <h2 class="my-5 h2 text-center">Payment</h2>
      <div class="row">
        <div class="col-md-12 mb-4">
          <div class="card">
           <script src="https://js.stripe.com/v3/"></script>
            <form action="." method="post" id="stripe-form">
              {% csrf_token %}
              <div class="stripe-form-row">
                <label for="card-element" id="stripeBtnLabel">
                  Credit or debit card
                </label>
                <div id="card-element" class="StripeElement StripeElement--empty"><div 
                       class="__PrivateStripeElement" style="margin: 0px... </div></div>
                <div id="card-errors" role="alert"></div>
              </div>
              <button id="stripeBtn">Submit Payment</button>
            </form>
          </div>
        </div>
      </div>
    </div>
  </main>
  <!------------else the paypal options shows below------------------>
.....
  <!------------end if------------------>

我的付款视图.py

class PaymentView(View):
    def get(self, *args, **kwargs):
        # order
        order = Order.objects.get(user=self.request.user, ordered=False)
        if order.billing_address:
            context = {
                'order': order,
                'DISPLAY_COUPON_FORM': False
            }
            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 ! ")
            # Email when order is made
            template = render_to_string("payment_confirmation_email.html", {'first_name': self.request.user.first_name,
                                                                            'last_name': self.request.user.last_name,
                                                                            'order': order})

            msg = EmailMessage('Thanks for Purchasing', template,
                               settings.EMAIL_HOST_USER, [self.request.user.email])
            msg.content_subtype = "html"  # Main content is now text/html
            msg.fail_silently = False
            msg.send()

            # End of the email send
            return render(self.request, "order_completed.html", {'order': order})

        except stripe.error.CardError as e:
            body = e.json_body
            err = body.get('error', {})
            messages.warning(self.request, f"{err.get('message')}")
            # Since it's a decline, stripe.error.CardError will be caught
            return redirect("/")

        except stripe.error.RateLimitError as e:
            # Too many requests made to the API too quickly
            messages.warning(self.request, "Rate Limit Error")
            return redirect("/")

        except stripe.error.InvalidRequestError as e:
            # Invalid parameters were supplied to Stripe's API
            messages.warning(self.request, "Invalid Parameters")
            return redirect("/")

        except stripe.error.AuthenticationError as e:
            # Authentication with Stripe's API failed
            # (maybe you changed API keys recently)
            messages.warning(self.request, "Not Authenticated")
            return redirect("/")

        except stripe.error.APIConnectionError as e:
            # Network communication with Stripe failed
            messages.warning(self.request, "Network Error")
            return redirect("/")

        except stripe.error.StripeError as e:
            # Display a very generic error to the user, and maybe send
            # yourself an email
            messages.warning(
                self.request, "Something went wrong. You were not charged. Please Try Again.")
            return redirect("/")

        except Exception as e:
            # Something else happened, completely unrelated to Stripe
            # send an email to ourselves
            messages.warning(
                self.request, "A serious Error Occured. We have been notified.")
            return redirect("/")

标签: pythondjango

解决方案


首先,添加payment_option到您的模板上下文中:

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)
    

然后在您的模板中,您可以执行以下操作:

{% if payment_method == 'stripe' %}
    <script src="https://js.stripe.com/v3/"></script>
    <!-- rest of stripe code -->
{% elif payment_method == 'paypal' %}
    <!-- paypal code here -->
{% endif %}

编辑:

您可能需要在 中指定参数类型urlpatterns

urlpatterns = [
    path('payment/<str:payment_option>/', PaymentView.as_view(), name='payment'),
]

推荐阅读