《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
2017-03-19 03:01
676 查看
第八章
管理付款和订单
在上一章,你创建了一个基础的在线商店包含一个产品列表以及订单系统。你还学习了如何执行异步的任务通过使用Celery。在这一章中,你会学习到如何集成一个支付网关(译者注:支付网关(Payment Gateway)是银行金融网络系统和Internet网络之间的接口,是由银行操作的将Internet上传输的数据转换为金融机构内部数据的一组服务器设备,或由指派的第三方处理商家支付信息和顾客的支付指令。以上是我百度的。)到你的站点中。你还会扩展管理平台站点来管理订单和用不同的格式导出它们。在这一章中,我们会覆盖以下几点:
集成一个支付网关到你的站点中
管理支付通知
导出订单为CSV格式
创建定制视图给管理页面
动态的生成PDF支票
集成一个支付网关
一个支付网关允许你在线处理支付。通过使用一个支付网关,你可以管理顾客的订单以及委托一个可靠的,安全的第三方处理支付。这意味着你无需担心存储信用卡信息到你的系统中。PayPal 提供了多种方法来集成它的网管到你的站点中。标准的集成由一个Buy now按钮组成,这个按钮你可以已经在别的网站见到过(译者注:国内还是支付宝和微信比较多)。这个按钮会重定向购买者到PayPal去处理支付。我们将要集成PayPal支付标准包含一个定制的Buy now按钮到我们的站点中。PayPal将会处理支付并且发送一个消息通知给我们的服务指明该笔支付的状态。
创建一个PayPal账户
你需要有一个PayPal商业账户来集成支付网关到你的站点中。如果你还没有一个PayPal账户,去https://www.paypal.com/signup/account 注册。确保你选择了一个BussinessAccount并且注册成为PayPal支付标准解决方案,如下图所示:
填写你的详情在注册表单中并且完成注册流程。PayPal会发送给你一封e-mail来核对你的账户。
安装django-paypal
Django-paypal是一个第三方django应用,它可以简化集成PayPal到Django项目中。我们将要使用它来集成PayPal支付标准解决方案到我们的商店中。你可以找到django-paypal的文档,访问 http://django-paypal.readthedocs.org/。安装django-paypal在shell中通过以下命令:
pip install django-paypal==0.2.5
(译者注:现在应该有最新版本,书上使用的是0.2.5版本)
编辑你的项目中的settings.py文件,添加'paypal.standard.ipn'到INSTALLED_APPS设置中,如下所示:
INSTALLED_APPS = ( # ... 'paypal.standard.ipn', )
这个应用提供自django-paypal来集成PayPal支付标准通过Instant Payment Notification(IPN)。我们之后会操作支付通知。
添加以下设置到myshop的settings.py文件来配置django-paypal:
# django-paypal settings PAYPAL_RECEIVER_EMAIL = 'mypaypalemail@myshop.com' PAYPAL_TEST = True
以上两个设置含义如下:
PAYPAL_RECEIVER_EMAIL:你的PayPal账户e-mail。使用你创建的PayPal账户e-mail替换*mypaypalemail@myshop.com*。
PAYPAL_TEST:一个布尔类型指示是否PayPal的沙箱环境,该环境可以用来处理支付。这个沙箱允许你测试你的PayPal集成在迁移到一个正式生产的环境之前。
打开shell运行如下命令来同步django-paypal的模型(models)到数据库中:
python manage.py migrate
你会看到如下类似的输出:
Running migrations: Rendering model states... DONE Applying ipn.0001_initial... OK Applying ipn.0002_paypalipn_mp_id... OK Applying ipn.0003_auto_20141117_1647... OK
django-paypal的模型(models)如今已经同步到了数据库中。你还需要添加django-paypal的URL模式到你的项目中。编辑主的urls.py文件,该文件位于myshop目录,然后添加以下的URL模式。记住粘贴该URL模式要在shop.urls模式之前为了避免错误的模式匹配:
url(r'^paypal/', include('paypal.standard.ipn.urls')),
让我们添加支付网关到结账流程中。
添加支付网关
结账流程工作如下:1.用户添加物品到他们的购物车中
2.用户结账他们的购物车
3.用户被重定向到PayPal进行支付
4.PayPal发送一个支付通知给我们的站点
5.PayPal重定向用户回到我们的网站
创建一个新的应用到你的项目中使用如下命令:
python manage.py startapp payment
我们将要使用这个应用去管理结账过程和用户支付。
编辑你的项目的settings.py文件,添加'payment'到INSTALLED_APPS设置中,如下所示:
INSTALLED_APPS = ( # ... 'paypal.standard.ipn', 'payment', )
payment应用现在已经在项目中激活。编辑orders应用的views.py文件并且确保包含以下导入:
from django.shortcuts import render, redirect from django.core.urlresolvers import reverse
替换以下order_create视图(view)的内容:
# launch asynchronous task order_created.delay(order.id) return render(request, 'orders/order/created.html', locals())
新的内容为:
# launch asynchronous task order_created.delay(order.id) # set the order in the session request.session['order_id'] = order.id # redirect to the payment return redirect(reverse('payment:process'))
在成功的创建一个新的订单之后,我们设置这个订单ID到当前的会话中使用order_id会话键(session key)。之后,我们重定向用户到
payment:processURL,这个我们下一步就是创建。
编辑payment应用的views.py文件然后添加如下代码:
from decimal import Decimal from django.conf import settings from django.core.urlresolvers import reverse from django.shortcuts import render, get_object_or_404 from paypal.standard.forms import PayPalPaymentsForm from orders.models import Order def payment_process(request): order_id = request.session.get('order_id') order = get_object_or_404(Order, id=order_id) host = request.get_host() paypal_dict = { 'business': settings.PAYPAL_RECEIVER_EMAIL, 'amount': '%.2f' % order.get_total_cost().quantize( Decimal('.01')), 'item_name': 'Order {}'.format(order.id), 'invoice': str(order.id), 'currency_code': 'USD', 'notify_url': 'http://{}{}'.format(host, reverse('paypal-ipn')), 'return_url': 'http://{}{}'.format(host, reverse('payment:done')), 'cancel_return': 'http://{}{}'.format(host, reverse('payment:canceled')), } form = PayPalPaymentsForm(initial=paypal_dict) return render(request, 'payment/process.html', {'order': order, 'form':form})
在
payment_process视图(view)中,我们生成了一个PayPal的Buy
now按钮用来支付一个订单。首先,我们拿到当前的订单从
order_id会话键中,这个键值被之前的
order_create视图(view)设置。我们拿到这个
order对象通过给予的ID并且构建一个新的
PayPalPaymentsForm,该表单表单包含以下字段:
business:PayPal商业账户用来处理支付。我们使用e-mail账户,该账户定义在
PAYPAL_RECEIVER_EMAIL设置那里。
amount:向顾客索要的总价。
item_name:正在出售的商品名。我们使用订单ID,因为订单可能包含很多产品。
currency_code:本次支付的货币。我们设置这里为USD使用U.S. Dollar(译者注:传说中的美金)。需要使用相同的货币,该货币被设置在你的PayPal账户中(例如:EUR 对应欧元)。
notify_url:这个URL PayPal将会发送IPN请求过去。我们使用django-paypal提供的
paypal-ipnURL。这个视图(view)与这个URL关联来操作支付通知以及存储它们到数据库中。
return_url:这个URL用来重定向用户当他的支付成功之后。我们使用URL
payment:done,这个我们接下来会创建。
cancel_return:这个URL用来重定向用户如果这个支付被取消或者有其他问题。我们使用URL
payment:canceled,这个我们接下来会创建。
PayPalpaymentsForm将会被渲染成一个标准表单带有隐藏的字段,并且用户将来只能看到Buy
now按钮。当用户点击该按钮,这个表单将会提交到PayPal通过POST渠道。
让我们创建简单的视图(views)给PayPal用来重定向用户当支付成功,或者当支付被取消因为某些原因。添加以下代码到相同的views.py文件:
from django.views.decorators.csrf import csrf_exempt @csrf_exempt def payment_done(request): return render(request, 'payment/done.html') @csrf_exempt def payment_canceled(request): return render(request, 'payment/canceled.html')
我们使用
csrf_exempt装饰器来避免Django期待一个CSRF标记,因为PayPal能重定向用户到以上两个视图(views)通过POST渠道。创建新的文件在payment应用目录下并且命名为urls.py。添加以下代码:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^process/$', views.payment_process, name='process'), url(r'^done/$', views.payment_done, name='done'), url(r'^canceled/$', views.payment_canceled, name='canceled'), ]
这些URL是给支付工作流的。我们已经包含了以下URL模式:
process:给这个视图(view)用来生成PayPal表单给Buy now按钮。
done:给PayPal用来重定向用户当支付成功的时候。
canceled:给PayPal用来重定向用户当支付取消的时候。
编辑主的myshop项目的urls.py文件,包含URL模式给payment应用:
url(r'^payment/', include('payment.urls',namespace='payment')),
记住粘贴以上内容在
shop.urls模式之前用来避免错误的模式匹配。
创建以下文件建构在payment应用目录下:
templates/ payment/ process.html done.html canceled.html
编辑payment/process.html模板(template)并且添加以下代码:
{% extends "shop/base.html" %} {% block title %}Pay using PayPal{% endblock %} {% block content %} <h1>Pay using PayPal</h1> {{ form.render }} {% endblock %}
这个模板(template)会渲染
PayPalPaymentsForm并且展示Buy
now按钮。
编辑payment/done.html模板(template)并且添加如下代码:
{% extends "shop/base.html" %} {% block content %} <h1>Your payment was successful</h1> <p>Your payment has been successfully received.</p> {% endblock %}
这个模板(template)的页面给用户重定向当成功支付之后。
编辑payment/canceled.html模板(template)并且添加以下代码:
{% extends "shop/base.html" %} {% block content %} <h1>Your payment has not been processed</h1> <p>There was a problem processing your payment.</p> {% endblock %}
这个模板(template)的页面给用户重定向当有这个支付过程出现问题或者用户取消了这次支付。
让我们尝试完成的支付过程。
使用PayPal的沙箱
打开 http://developer.paypal.com 在你的浏览器中然后进行登录使用你的PayPal商业账户。点击Dashboard菜单项,在左方菜单点击Accounts选项在Sandbox下方。你会看到你的沙箱测试账户列,如下所示:一开始,你将会看到一个商业以及一个个人测试账户由PayPal动态创建。你可以创建新的沙箱测试账户通过使用Create Account按钮。
点击Personal Account在列中扩大它,之后点击Profile链接。你会看到一些信息关于这个测试账户包含e-mail和profile信息,如下所示:
在Funding tab中,你会找到银行账户,信用卡日期,以及PayPal信用余额。
这些测试账户能够被用来做支付在你的网站中当使用沙箱环境。跳转到Profile tab然后点击Change password链接。创建一个定制密码给这个测试账户。
打开shell并且启动开发服务器使用命令
python manage.py runserver。打开 http://127.0.0.1:8000 在你的浏览器中,添加一些产品到购物车中,并且填写结账表单。当你点击Place order按钮,这个订单会被保存在数据库中,这个订单ID会被保存在当前的会话中,并且你会被重定向到支付处理页面。这个页面从会话中获取订单并且渲染PayPal表单显示一个Buy
now按钮,如下所示:
你可以看下HTML源码来看下生成的表单字段。
点击Buy now按钮。你会被重定向到PayPal,并且你会看到如下页面:
输入购买者测试账户e-mail和密码然后点击Log In按钮。你会被重定向到以下页面:
现在,点击Pay now按钮。最后,你会看到批准页面该页面包含你的交易ID。这个页面看上去如下所示:
点击**Return to e-mail@domain.com**按钮。你会被重定向到的URL是你之前在
PayPalPaymentsForm中的
return_url字段中定义的。这个URL对应
payment_done视图(view)。这个页面看上去如下所示:
这个支付已经成功了。然而,PayPal并没有发送一个支付状态通知给我们的应用,因为我们运行我们的项目在我们本地主机,IP是 127.0.0.1 这并不是一个公开地址。我们将要学习如何使我们的站点可以从Internet访问并且接收IPN通知。
<h2 id="获取支付通知" s
相关文章推荐
- 《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第八章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第六章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第九章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第七章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第七章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第十章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第十二章(终章) 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第十一章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第七章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)
- 《Django By Example》翻译
- Django 2.0官方文档中文 渣翻 总索引(个人学习,欢迎指正)
- [个人]加入了ruby hacking guide的中文翻译团队
- [个人]加入了ruby hacking guide的中文翻译团队
- (翻译)Django 1.0 中文文档-----指导 第一部分
- (翻译)Django 1.0 中文文档 ----- 第一步
- [个人]加入了ruby hacking guide的中文翻译团队