(91) 350-9520 support@omarine.org M-F: 7 AM - 7 PM; Weekends: 9 AM - 5 PM

Lập trình Web: Python: Django: Xây dựng cửa hàng trực tuyến với Oscar-Paypal, phần 4

10. Cài đặt paypal

pip install django-oscar-paypal

Gói paypal có một số lỗi, bạn chạy lệnh dưới đây để sửa lỗi trước khi sử dụng

paypaldir=~/python-env/myshop/lib/python3.6/site-packages/paypal &&
sed -i 's,ppe\.message,six.text_type(ppe),' $paypaldir/express/views.py &&
sed -i '/import patterns/s/patterns,//;/urlpatterns =/s/patterns(.*$/[/;/^\s*)$/s/)/]/' \
    $paypaldir/{payflow/dashboard/app,express/dashboard/app,express/urls}.py &&
sed -i '/load url/d' \
    $paypaldir/templates/paypal/payflow/{transaction_detail,transaction_list}.html &&
sed -i '/load url/d' $paypaldir/templates/paypal/express/preview.html &&
sed -i '/load url/d' \
    $paypaldir/templates/paypal/express/dashboard/{transaction_detail,transaction_list}.html

11. Fork chương trình Oscar

Oscar mặc định không cung cấp tích hợp thanh toán. Nhưng nó có các lớp lõi để chúng ta tùy biến, kế thừa. Tạo hai chương trình checkoutshipping cho dự án. Chương trình checkout tích hợp thanh toán và chương trình shipping tạo thêm phương thức vận chuyển. Chúng được sử dụng thay cho các chương trình tương ứng của Oscar. Việc này được gọi là fork chương trình hay tùy biến module.

mkdir apps &&
touch apps/__init__.py

python manage.py oscar_fork_app checkout apps
python manage.py oscar_fork_app shipping apps

Tạo tệp apps/app.py:

from oscar.app import Shop
from apps.checkout.app import application as checkout_app

class PayPalShop(Shop):
    checkout_app = checkout_app

application = PayPalShop()

Tạo tệp apps/checkout/app.py:

from oscar.apps.checkout import app
from apps.checkout import views

class CheckoutApplication(app.CheckoutApplication):
    payment_details_view = views.PaymentDetailsView

application = CheckoutApplication()

Tạo tệp apps/checkout/views.py:

from django.contrib import messages
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from oscar.apps.checkout import views
from oscar.apps.payment import forms, models

from paypal.payflow import facade

class PaymentDetailsView(views.PaymentDetailsView):
    """
    An example view that shows how to integrate BOTH Paypal Express
    (see get_context_data method)and Payppal Flow (the other methods).
    Naturally, you will only want to use one of the two.
    """

    def get_context_data(self, **kwargs):
        """
        Add data for Paypal Express flow.
        """
        # Override method so the bankcard and billing address forms can be
        # added to the context.
        ctx = super(PaymentDetailsView, self).get_context_data(**kwargs)
        ctx['bankcard_form'] = kwargs.get(
            'bankcard_form', forms.BankcardForm())
        ctx['billing_address_form'] = kwargs.get(
            'billing_address_form', forms.BillingAddressForm())
        return ctx

    def post(self, request, *args, **kwargs):
        # Override so we can validate the bankcard/billingaddress submission.
        # If it is valid, we render the preview screen with the forms hidden
        # within it. When the preview is submitted, we pick up the 'action'
        # parameters and actually place the order.
        if request.POST.get('action', '') == 'place_order':
            return self.do_place_order(request)

        bankcard_form = forms.BankcardForm(request.POST)
        billing_address_form = forms.BillingAddressForm(request.POST)
        if not all([bankcard_form.is_valid(),
                    billing_address_form.is_valid()]):
            # Form validation failed, render page again with errors
            self.preview = False
            ctx = self.get_context_data(
                bankcard_form=bankcard_form,
                billing_address_form=billing_address_form)
            return self.render_to_response(ctx)

        # Render preview with bankcard and billing address details hidden
        return self.render_preview(request,
                                   bankcard_form=bankcard_form,
                                   billing_address_form=billing_address_form)

    def do_place_order(self, request):
        # Helper method to check that the hidden forms wasn't tinkered with.
        bankcard_form = forms.BankcardForm(request.POST)
        billing_address_form = forms.BillingAddressForm(request.POST)
        if not all([bankcard_form.is_valid(),
                    billing_address_form.is_valid()]):
            messages.error(request, "Invalid submission")
            return HttpResponseRedirect(reverse('checkout:payment-details'))

        # Attempt to submit the order, passing the bankcard object so that it
        # gets passed back to the 'handle_payment' method below.
        submission = self.build_submission()
        submission['payment_kwargs']['bankcard'] = bankcard_form.bankcard
        submission['payment_kwargs']['billing_address'] = billing_address_form.cleaned_data
        return self.submit(**submission)

    def handle_payment(self, order_number, total, **kwargs):
        """
        Make submission to PayPal
        """
        # Using authorization here (two-stage model). You could use sale to
        # perform the auth and capture in one step. The choice is dependent
        # on your business model.
        facade.authorize(
            order_number, total.incl_tax,
            kwargs['bankcard'], kwargs['billing_address'])

        # Record payment source and event
        source_type, is_created = models.SourceType.objects.get_or_create(
            name='PayPal')
        source = source_type.sources.model(
            source_type=source_type,
            amount_allocated=total.incl_tax, currency=total.currency)
        self.add_payment_source(source)
        self.add_payment_event('Authorised', total.incl_tax)

Nếu chỉ có 1 phương thức vận chuyển thì phương thức đó được chọn tự động và không trình bày trang lựa chọn phương thức vận chuyển trong chuỗi phân trang khi bắt đầu quá trình thanh toán. Các phương thức vận chuyển có thể tùy biến bằng cách viết đè lớp Repository. Bạn tạo tệp apps/shipping/repository.py:

from decimal import Decimal as D

from oscar.apps.shipping.methods import Free, FixedPrice
from oscar.apps.shipping.repository import Repository as CoreRepository

class Repository(CoreRepository):
    """
    This class is included so that there is a choice of shipping methods.
    Oscar's default behaviour is to only have one which means you can't test
    the shipping features of PayPal.
    """
    methods = [Free(), FixedPrice(D('5.00'), D('5.00'))]

Trong lớp Repository mới, methods bao gồm 2 phương thức vận chuyển: phương thức miễn phí và phương thức giá cố định. Do đó khuôn mẫu ‘checkout/shipping_methods.html’ sẽ được trình bày.

12. Cập nhật settings.py

Thay

INSTALLED_APPS += get_core_apps()

Với

INSTALLED_APPS += [ 'paypal' ] + get_core_apps([
    'apps.shipping',
    'apps.checkout',])

Bổ sung trạng thái tuyến khi một trạng thái đơn hàng thay đổi:

OSCAR_ORDER_STATUS_CASCADE = {
    'Being processed': 'Being processed',
    'Cancelled': 'Cancelled',
    'Complete': 'Shipped',
}

Thêm menu PayPal vào Dashboard:

from django.utils.translation import gettext_lazy as _
OSCAR_DASHBOARD_NAVIGATION.append(
    {
        'label': _('PayPal'),
        'icon': 'icon-globe',
        'children': [
            {
                'label': _('PayFlow transactions'),
                'url_name': 'paypal-payflow-list',
            },
            {
                'label': _('Express transactions'),
                'url_name': 'paypal-express-list',
            },
        ]
    })

Chúng ta sẽ giao dịch mua bán và trả tiền thực sự qua các tài khoản PayPal sandbox để test. Bạn cần tạo hai tài khoản PayPal sandbox: tài khoản loại kinh doanh cho chủ cửa hàng và tài khoản loại cá nhân cho người mua. Nhập thông tin tài khoản chủ cửa hàng như dưới đây. Nó là tài khoản có thật nhưng chỉ là ví dụ đối với bạn. Sau khi bạn đã xây dựng cửa hàng theo hướng dẫn, chỉ cần một bước duy nhất để tích hợp PayPal Express hoạt động:

PAYPAL_API_USERNAME = 'pham_api1.gmail.com'
PAYPAL_API_PASSWORD = 'Z563RYZHEE6MAHT7'
PAYPAL_API_SIGNATURE = 'A.CSYz4u5IILQm5wM0J0JbJiIcEuAj-2gwErolARWB-mVnzn.ISevDVm'

Thêm dòng cấu hình dưới đây để người mua có thể về được tới cửa hàng sau khi đã trả tiền tại PayPal, dù server phát triển đang sử dụng giao thức http. Cửa hàng sau đó sẽ trình bày chi tiết thanh toán:

PAYPAL_CALLBACK_HTTPS = False

Advertisements

Gửi phản hồi

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: