本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习

https://www.bilibili.com/video/BV1vt41147K8?p=1

订单页面支付JS

1. 点击‘去支付’按钮,发送ajax请求,后台视图调用支付宝支付接口时,返回的是一个支付界面的url,需要通过window.open(data.pay_url),引导用户浏览器打开支付宝返回的支付url

2. 引导完url之后,继续发送查询ajax请求,后台视图调用支付宝查询接口,若查到支付成功,则alert(‘支付成功’)并刷新界面 location.reload()

  1. {% block endfiles %}
  2. <script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js'%}"></script>
  3. <script type="text/javascript">
  4. //根据订单状态显示下一步操作
  5. $('.oper_btn').each(function(){
  6. status = $(this).attr('order_status')
  7. if (status == '1'){
  8. oper_show = '去支付'
  9. }
  10. else if (status =='4'){
  11. oper_show = '去评价'
  12. }
  13. else{
  14. oper_show = $(this).attr('status_name')
  15. }
  16. $(this).text(oper_show)
  17. })
  18. //去支付按钮
  19. $('.oper_btn').click(function(){
  20. //获取订单ID
  21. order_id = $(this).attr('order_id')
  22. //若状态为待支付,则发送ajax支付请求
  23. if ($(this).attr('order_status') =='1'){
  24. pay_method = $(this).attr('pay_method')
  25. send_pay_ajax(order_id, pay_method)
  26. }
  27. //若状态为待评价,则跳转到评价界面
  28. else if($(this).attr('order_status') == '4'){
  29. //跳转到评价页面
  30. location.href = '/order/comment/'+order_id
  31. }
  32. })
  33. //支付发送ajax请求
  34. function send_pay_ajax(order_id, pay_method){
  35. csrf = $('input[name="csrfmiddlewaretoken"]').val()
  36. parameter = {
  37. 'order_id': order_id,
  38. 'csrfmiddlewaretoken': csrf,
  39. }
  40. if (pay_method == '3'){
  41. //支付宝支付
  42. $.post('/order/alipay/', parameter, function(data){
  43. //回调函数
  44. if (data.status == 'S'){
  45. //引导用户到支付界面
  46. window.open(data.pay_url)
  47. //发送ajax请求查询订单支付情况
  48. $.post('/order/check/', parameter, function(data){
  49. if (data.status == 'S'){
  50. alert('支付成功')
  51. location.reload()
  52. }
  53. else{
  54. alert(data.errmsg)
  55. }
  56. })
  57. }
  58. else{
  59. alert(data.errmsg)
  60. }
  61. })
  62. }
  63. else{
  64. //其他支付方式
  65. alert('其他支付方式暂不支持!')
  66. }
  67. }
  68. </script>
  69. {% endblock endfiles %}

调用支付宝接口

调用接口流程图

创建支付宝应用

登录支付宝开放平台,进入沙箱环境,沙箱环境即为支付宝给外接系统提供的虚拟开发环境,并默认分配了一个应用,因此不需要再创建应用,而正是支付宝环境需要创建应用并审核。

设置应用密钥

支付需要有三个密钥:

  应用的私钥:将发送给支付宝的数据用自己的私钥加密。

  应用的公钥:与应用的私钥配对使用,将加密后的数据发送给支付宝时,同时将公钥也发送给支付宝,让支付宝使用该公钥进行解密。

  支付宝的公钥:支付宝解密后,再用支付宝自己的私钥进行加密并发送给接口调用方(应用),应用再使用支付宝公钥进行解密。

生成密钥和私钥,可以使用‘支付宝开放平台开发助手’生成,下载路径为:https://opendocs.alipay.com/open/291/105971

密钥格式选择“PKCS1(非Java适用)”,点击生成密钥后,点击‘打开密钥文件路径’,可以查看到生成的公钥和私钥,保存好这两个文件。

进入沙箱环境,设置应用的密钥,将应用公钥添加进去,同时会返回一个支付宝公钥

沙箱账号

沙箱环境也提供了两个账号,分别是买方和卖方的账号,后续进行支付交易时可以使用买方账号

安装官方SDK

支付宝SDK路径:https://opendocs.alipay.com/open/54/103419#Alipay%20SDK, 支付宝官方也提供了支持python的SDK(alipay-sdk-python):https://pypi.org/project/alipay-sdk-python/3.3.398/,安装命令为

  1. pip install alipay-sdk-python==3.3.398

编写调用代码

支付宝接口所有API文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.pay,这里我们使用"alipay.trade.page.pay(统一收单下单并支付页面接口)",这个接口会返回一个支付界面的URL,引导用户进入该URL,并登录支付宝账号完成支付,注意不是"alipay.trade.page.pay(统一收单下单并支付页面接口)",这个下单并支付接口是直接将买方账户信息也放入发送数据中,返回的是支付的结果,而不是返回支付页面的链接让用户自己登陆。

编辑order/views.py文件,支付宝所有接口调用代码都分为4个部分:

1. 导入相关包

客户端相关包、模型相关包、请求相关包

  1. import logging
  2. from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
  3. from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
  4. from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
  5. from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest

2. 创建(实例化)客户端

这里将创建客户端需要的一些参数配置在了settings.py文件中

  1. # 记录日志
  2. logging.basicConfig(
  3. level=logging.INFO,
  4. format='%(asctime)s %(levelname)s %(message)s',
  5. filemode='a',)
  6. logger = logging.getLogger('')
  7. # 实例化客户端
  8. alipay_client_config = AlipayClientConfig()
  9. alipay_client_config.server_url = settings.ALIPAY_SERVER_URL
  10. alipay_client_config.app_id = settings.ALIPAY_APP_ID
  11. alipay_client_config.app_private_key = settings.ALIPAY_PRIVATE_KEY
  12. alipay_client_config.alipay_public_key = settings.ALIPAY_PUBLIC_KEY
  13. client = DefaultAlipayClient(alipay_client_config, logger)

settings.py配置

  1. # 支付宝支付设置-沙箱环境
  2. # 支付宝网关,正式环境网关去掉dev三个字母
  3. ALIPAY_SERVER_URL = 'https://openapi.alipaydev.com/gateway.do'
  4. # 应用ID
  5. ALIPAY_APP_ID = ''
  6. # 应用私钥
  7. ALIPAY_PRIVATE_KEY = 'XXXXXX'
  8. # 支付宝公钥
  9. ALIPAY_PUBLIC_KEY = 'XXXXXXX'
  10. # 订单超时时间:如果买家超过这个时间不付款,会关闭交易(最小1m分钟)
  11. ALIPAY_EXPRESS = '10m'

3. 创建支付模型

  1. # 构造请求参数对象
  2. model = AlipayTradePagePayModel()
  3. # 调用方系统生成的订单编号
  4. model.out_trade_no = order.order_num;
  5. # 支付金额
  6. model.total_amount = str(order.total_amount);
  7. # 支付标题
  8. model.subject = "天天生鲜";
    #与支付宝签约的产品码名称,目前只支持这一种。
  9. model.product_code = 'FAST_INSTANT_TRADE_PAY'
  10. # 订单过期关闭时长(分钟)
  11. model.timeout_express = settings.ALIPAY_EXPRESS

4. 调用业务API

  1. # 创建请求对象
  2. request = AlipayTradePagePayRequest(biz_model=model)
  3. # 设置回调通知地址(GET)
  4. request.return_url = settings.ALIPAY_RETURN_URL
  5. # 设置回调通知地址(POST)
  6. request.notify_url = settings.ALIPAY_NOTIFY_URL
  7. # 执行API调用,获取支付连接
  8. pay_url = client.page_execute(request, http_method='GET')
  9. return pay_url

完整支付类视图(OrderAlipayView)代码为:

  1. # 支付宝支付 start
  2. import logging
  3. from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
  4. from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
  5. from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
  6. from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
  7.  
  8. def alipay_init():
  9. '''支付宝初始化'''
  10. # 记录日志
  11. logging.basicConfig(
  12. level=logging.INFO,
  13. format='%(asctime)s %(levelname)s %(message)s',
  14. filemode='a',)
  15. logger = logging.getLogger('')
  16. # 实例化客户端
  17. alipay_client_config = AlipayClientConfig()
  18. alipay_client_config.server_url = settings.ALIPAY_SERVER_URL
  19. alipay_client_config.app_id = settings.ALIPAY_APP_ID
  20. alipay_client_config.app_private_key = settings.ALIPAY_PRIVATE_KEY
  21. alipay_client_config.alipay_public_key = settings.ALIPAY_PUBLIC_KEY
  22. client = DefaultAlipayClient(alipay_client_config, logger)
  23. return client
  24.  
  25. def alipay_pay(order):
  26. '''支付宝支付'''
  27. client = alipay_init()
  28. # 构造请求参数对象
  29. model = AlipayTradePagePayModel()
  30. # 调用方系统生成的订单编号
  31. model.out_trade_no = order.order_num;
  32. # 支付金额
  33. model.total_amount = str(order.total_amount);
  34. # 支付标题
  35. model.subject = "天天生鲜";
  36. #与支付宝签约的产品码名称,目前只支持这一种。
  37. model.product_code = 'FAST_INSTANT_TRADE_PAY'
  38. # 订单过期关闭时长(分钟)
  39. model.timeout_express = settings.ALIPAY_EXPRESS
  40. # 创建请求对象
  41. request = AlipayTradePagePayRequest(biz_model=model)
  42. # 设置回调通知地址(GET)
  43. request.return_url = settings.ALIPAY_RETURN_URL
  44. # 设置回调通知地址(POST)
  45. request.notify_url = settings.ALIPAY_NOTIFY_URL
  46. # 执行API调用,获取支付连接
  47. pay_url = client.page_execute(request, http_method='GET')
  48. return pay_url
  49.  
  50. class OrderAlipayView(View):
  51. '''支付视图'''
  52. def post(self, request):
  53. '''支付处理'''
  54. context = {
  55. 'status': 'E',
  56. 'errmsg': '',
  57. }
  58. user = request.user
  59. if not user.is_authenticated:
  60. context['errmsg'] = '用户未登录!'
  61. return JsonResponse(context)
  62. # 接收数据
  63. order_id = int(request.POST.get('order_id'))
  64.  
  65. # 校验数据
  66. try:
  67. order = OrderInfo.objects.get(id=order_id)
  68. except OrderInfo.DoesNotExist:
  69. context['errmsg'] = '订单不存在!'
  70. return JsonResponse(context)
  71.  
  72. # 业务处理
  73. pay_url = alipay_pay(order)
  74.  
  75. # 返回应答
  76. context['status'] = 'S'
  77. context['pay_url'] = pay_url
  78. return JsonResponse(context)

以上代码完成之后即可将返回的pay_url传递给前端,前端通过window.open(data.pay_url),引导用户浏览器打开支付宝返回的支付url,让用户进行登录支付。同时发送查询支付结果的请求,若监控到支付成功,则刷新订单页面

 

编写查询支付宝支付结果代码

完整查询类视图(OrderCheckView)代码为:

  1. from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel
  2. from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
  3.  
  4. def alipay_query(order, context):
  5. '''支付宝支付'''
  6. client = alipay_init()
  7. # 构造请求参数对象
  8. model = AlipayTradeQueryModel()
  9. model.out_trade_no = order.order_num;
  10. model.timeout_express = settings.ALIPAY_EXPRESS
  11. #与支付宝签约的产品码名称,目前只支持这一种。
  12. model.product_code = 'FAST_INSTANT_TRADE_PAY'
  13. request = AlipayTradeQueryRequest(biz_model=model)
  14.  
  15. while True:
  16. # 执行API调用
  17. response = client.execute(request)
  18. # str转换为字典
  19. response = eval(response)
  20. code = response.get('code')
  21. sub_code = response.get('sub_code')
  22. sub_msg = response.get('sub_msg')
  23. trade_status = response.get('trade_status')
  24. if sub_code == 'ACQ.TRADE_NOT_EXIST' or (code == '' and
  25. trade_status ==
  26. 'WAIT_BUYER_PAY'):
  27. # 交易不存在,或状态为等待买家付款则继续等待用户付款
  28. time.sleep(5)
  29. continue
  30. elif code == '' and trade_status == 'TRADE_SUCCESS':
  31. # 支付成功
  32. context['status'] = 'S'
  33. trade_no = response.get('trade_no')
  34. # 回写订单支付号
  35. order.trade_no = trade_no
  36. order.order_status = 4 # 待评价
  37. order.save()
  38. break
  39. else:
  40. context['errmsg'] = '支付失败:%s-%s' % (sub_code, sub_msg)
  41. break
  42.  
  43. class OrderCheckView(View):
  44. '''查询支付宝支付情况'''
  45. def post(self, request):
  46. context = {
  47. 'status': 'E',
  48. 'errmsg': ''
  49. }
  50. user = request.user
  51. if not user.is_authenticated:
  52. context['errmsg'] = '用户未登录!'
  53. return JsonResponse(context)
  54. # 接收数据
  55. order_id = int(request.POST.get('order_id'))
  56. try:
  57. order = OrderInfo.objects.get(id=order_id)
  58. except Exception as e:
  59. context['errmsg'] = '订单不存在!'
  60. return JsonResponse(context)
  61.  
  62. # 执行查询
  63. alipay_query(order, context)
  64. return JsonResponse(context)

1. 查询时,因为用户付款需要一定的时间,所以使用循环,每5秒查询一次

2. 查询换回的结果字符串‘str’,因此需要将其转换为字典

3. 返回的主要字段包括:code(返回码,如10000) 、sub_code(子返回码,如ACQ.TRADE_NOT_EXIST)、trade_status(交易状态,如:'WAIT_BUYER_PAY')

4. 当用户还未登陆支付宝时,code为40004、sub_code为ACQ.TRADE_NOT_EXIST(交易不存在),当用户登录后,code为10000,trade_status为WAIT_BUYER_PAY(等待用户付款),当付款成功后,trade_status为TRADE_SUCCESS

DJANGO-天天生鲜项目从0到1-013-订单-支付宝支付的更多相关文章

  1. django天天生鲜项目

    .后台admin管理天天生鲜商品信息 models里 from django.db import modelsfrom tinymce.models import HTMLField #需要pip安装 ...

  2. DJANGO-天天生鲜项目从0到1-011-订单-订单提交和创建

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  3. DJANGO-天天生鲜项目从0到1-014-订单-订单评论

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  4. DJANGO-天天生鲜项目从0到1-007-首页静态化与缓存

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  5. python 天天生鲜项目

    python 天天生鲜项目 django版:https://github.com/Ivy-1996/fresh flask版:https://github.com/Ivy-1996/flask-fre ...

  6. Django之天天生鲜项目

    准备工作 1.配置settings.py内置文件 注意: AUTH_USER_MODEL配置参数要在第一次迁移数据库之前配置,否则可能django的认证系统工作不正常 2.创建应用 3.配置主路由 一 ...

  7. DJANGO-天天生鲜项目从0到1-012-订单-用户订单页面

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  8. DJANGO-天天生鲜项目从0到1-010-购物车-购物车操作页面(勾选+删改)

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  9. DJANGO-天天生鲜项目从0到1-009-购物车-Ajax实现添加至购物车功能

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  10. DJANGO-天天生鲜项目从0到1-009-搜索功能实现(django-haystack+whoosh+jieba)

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

随机推荐

  1. Docker(三)Docker常用命令

    Docker常用命令 帮助命令 # 显示 Docker 版本信息 docker version # 显示系统信息,包括镜像和容器的数量 docker info # 查看帮助文档 帮助文档地址:http ...

  2. python从文件载入字典

    data = np.load('dict_.npy') data = data.item() 不加最后一句,data不是字典类型

  3. Auto-keras API详解

    在网上找到的Auto-keras API详解,非常全面,防止丢失记录在这! Auto-Keras API详解(1)——安装Auto-Keras https://blog.csdn.net/weixin ...

  4. Bash 脚本编程的一些高级用法

    概述 偶然间发现 man bash 上其实详细讲解了 shell 编程的语法,包括一些很少用却很实用的高级语法.就像发现了宝藏的孩子,兴奋莫名.于是参考man bash,结合自己的理解,整理出了这篇文 ...

  5. 深入理解JVM(③)Java模块化系统

    前言 JDK9引入的Java模块化系统(Java Platform Module System ,JPMS)是 对Java技术的一次重要升级,除了像之前JAR包哪有充当代码的容器之外,还包括: 依赖其 ...

  6. java语言基础(五)_Scanner类_Random类_ArrayList类

    API API(Application Programming Interface),应用程序编程接口.Java API是一本程序员的字典 ,是JDK中提供给程序员使用的类的说明文档.这些类将底层的代 ...

  7. CSS中的一些细节

    一.塌陷 1.当position设置为:absolute或者fixed时,元素的display会转换为block.(设置float也会产生这样的效应)2.正常情况下,div会被内容撑开,但是如果设置了 ...

  8. JAVA基础笔记15-16-17-18

    十五.今日内容介绍 1.Object 2.String 3.StringBuilder =第一节课开始======================= 01API概念 * A:API(Applicati ...

  9. Redis哨兵集群创建脚本--v1

    基础环境 操作系统版本  CentOS Linux release 7.6.1810 (Core) Docker 版本  19.03.11, build 42e35e61f3 Redis  版本  3 ...

  10. 常用js代码片段(一)

    1.如果数组所有元素都满足函数条件,则返回true.调用时,如果省略第二个参数,则默认传递布尔值. const all= (arr, fn=Boolean) => arr.every(fn); ...