最新文章更新见我的个人主页: https://xzajyjs.cn

我们在使用Django构建网站时常需要对接第三方支付平台的支付接口,这里就以支付宝为例(其他平台大同小异),使用支付宝开放平台的沙箱环境进行实验。

我们这里使用一个第三方的AliPay Python SDK(github)

下面看一下它的基本使用


调用流程

事实上需要我们网站服务端做的事并不多,只需要生成一个订单向支付宝发出支付请求,等用户支付完毕后向支付宝(通过同步和异步的方式)查询订单、交易信息即可。

在实际生产环境中,需要注意如下各种安全性问题:

  • 由于同步返回的不可靠性,支付结果必须以异步通知或查询接口返回为准,不能依赖同步跳转。

  • 商户系统接收到异步通知以后,必须通过验签(验证通知中的 sign 参数)来确保支付通知是由支付宝发送的。

  • 接收到异步通知并验签通过后,请务必核对通知中的 app_id、out_trade_no、total_amount 等参数值是否与请求中的一致,并根据 trade_status 进行后续业务处理。

  • 在支付宝端,partnerId 与 out_trade_no 唯一对应一笔单据,商户端保证不同次支付 out_trade_no 不可重复;若重复,支付宝会关联到原单据,基本信息一致的情况下会以原单据为准进行支付。


具体实践

1.准备工作

由于使用真实环境需要商户支付宝账号、上线应用需要审批等流程,我们这里使用支付宝开放平台的沙箱环境

沙箱环境中提供了后面需要的参数如APPIDAPP_PRIVATE_KEYALIPAY_PUBLIC_KEY支付宝网关等。

接下来安装AliPay Python SDK

pip3 install python-alipay-sdk --upgrade

由于是沙箱环境,平台已经提供给我们需要的公钥和私钥,如果是生产环境,则需要通过openssl生成

openssl
OpenSSL> genrsa -out app_private_key.pem   2048  # 私钥
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
OpenSSL> exit

在支付宝上下载的公钥是一个字符串,你需要在文本的首尾添加标记位:

-----BEGIN PUBLIC KEY----- 和 -----END PUBLIC KEY-----

2.创建订单

先在settings.py中设定一些关键参数

# 读取公钥和私钥为字符串
app_private_key_string = open("/path/to/your/private/key.pem").read()
alipay_public_key_string = open("/path/to/alipay/public/key.pem").read()
# 沙箱环境提供的APPID
ALIPAY_APP_ID = "202xxxxxx9"
# 同步回调url(这里需要一个公网ip)
RETURN_URL = "http://xxx.xxx.xxx.xxx/"
# 支付宝网关地址。注意:正式环境和沙箱环境的网关地址不同
GATEWAY = "https://openapi.alipaydev.com/gateway.do?"
from alipay import AliPay, AliPayConfig
from .settings import APP_PRIVATE_KEY, ALIPAY_PUBLIC_KEY, ALIPAY_APP_ID, RETURN_URL, GATEWAYdef create_alipay():# 使用应用公钥进行报文验签alipay = AliPay(appid=ALIPAY_APP_ID,app_notify_url=None,  # 默认异步回调 urlapp_private_key_string=APP_PRIVATE_KEY,alipay_public_key_string=ALIPAY_PUBLIC_KEY,sign_type="RSA2",debug=False,  # 默认 Falseverbose=False,  # 输出调试数据config=AliPayConfig(timeout=15)  # 可选,请求超时时间)return alipay

下面可以创建支付订单了(官方文档)

# 向支付宝提交订单信息
def alipay_pay(subject, total_amount, out_trade_no, return_url_view):alipay = create_alipay()  # 先实例化alipayreturn_url = RETURN_URL + return_url_view # 同步回调url,用于支付完后跳转回网站并对支付状态进行即时检验。这里的return_url_view是用于接收支付宝回调的状态检验的视图函数order_string = alipay.api_alipay_trade_page_pay(out_trade_no=out_trade_no,    # 商户订单号,这个需要商户自定义total_amount=total_amount,    # 支付总金额subject=subject,    # 订单标题return_url=return_url,   # 同步回调url,用于支付完后跳转回网站并对支付状态进行即时检验notify_url="https://example.com/notify"  # 可选,不填则使用默认 notify url)return order_string     # 返回订单字符串

调用

import string
import random
from .settings import GATEWAY# 随机生成32位商户交易号
out_trade_no = "".join(random.sample(string.ascii_letters+string.digits, 32))# 在视图函数对alipay_return进行绑定
# 同步回调url为:  http://xxx.xxx.xxx.xxx/alipay_return
order_string = alipay_pay(subject="测试商品",total_amount=100,out_trade_no=out_trade_no,return_url_view='alipay_return')return HttpResponseRedirect(GATEWAY+order_string)

调用后会跳转到支付宝平台,使用沙箱环境提供的买家账号即可完成支付

但是此时我们还不能回调跳转到我们自己的网站,也不能获得订单支付信息,下面还有最后一步。

3.同步回调

我们刚刚创建的订单信息中填写了return_url,我们需要一个视图函数来接收,并对其返回值进行分析

def alipay_return(request):processed_dict = {}# 回调时alipay会把一些公用信息通过GET方式传参回来,这里用字典去接收存储for key, value in request.GET.items():processed_dict[key] = value"""processed_dict = {'charset': 'utf-8', 'out_trade_no': 'xxxxxxx',     # 这个是我们之前创建订单时生成的商户交易号'method': 'alipay.trade.page.pay.return', 'total_amount': '100.00',   # 交易金额'trade_no': '20220xxxxxxxx24353',     # 支付宝交易号'auth_app_id': '2021xxxxxx609',         # 用户appid'version': '1.0', 'app_id': '2021xxxxxx7609',      # 沙箱提供的APPID 应用ID'sign_type': 'RSA2', 'seller_id': '2088xxxxx844',      # 收款支付宝账号对应的支付宝唯一用户号。
以2088开头的纯16位数字'timestamp': '2022-05-28 23:40:55'}"""sign = processed_dict.pop("sign", None)new_alipay = create_alipay()verify_re = new_alipay.verify(processed_dict, sign)if verify_re is True:print("支付成功")else:print("支付失败")

注意:同步回调往往不可靠,因此需要增加一个异步回调检验

另外,在订单创建后需要向数据库存储订单信息,包括订单金额、商户订单号、appid等,等待回调后与参数校验一致无误后再将订单支付信息进行更新。下面的完整示例不会包括该部分,请自行完成


完整示例

项目结构

# alipay.py
from alipay import AliPay, AliPayConfig
from .settings import APP_PRIVATE_KEY, ALIPAY_PUBLIC_KEY, ALIPAY_APP_ID, RETURN_URLdef create_alipay():alipay = AliPay(appid=ALIPAY_APP_ID,app_notify_url=None,  # 默认回调 urlapp_private_key_string=APP_PRIVATE_KEY,# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,alipay_public_key_string=ALIPAY_PUBLIC_KEY,sign_type="RSA2",  # RSA 或者 RSA2debug=False,  # 默认 Falseverbose=False,  # 输出调试数据config=AliPayConfig(timeout=15)  # 可选,请求超时时间)return alipaydef alipay_pay(subject, total_amount, out_trade_no, return_url_view):alipay = create_alipay()return_url = RETURN_URL + return_url_vieworder_string = alipay.api_alipay_trade_page_pay(out_trade_no=out_trade_no,total_amount=total_amount,subject=subject,return_url=return_url,notify_url="https://example.com/notify"  # 可选,不填则使用默认 notify url)return order_string
# settings.py
...
...ALIPAY_APP_ID = "xxxxxx"
APP_PRIVATE_KEY = open(os.path.join(BASE_DIR, 'alipay/app_private_key.pem'), 'r').read()
ALIPAY_PUBLIC_KEY = open(os.path.join(BASE_DIR, 'alipay/alipay_public_key.pem'), 'r').read()
RETURN_URL = "http://xxxxxx/"
GATEWAY = "https://openapi.alipaydev.com/gateway.do?"
# urls.py
from django.contrib import admin
from django.urls import path
from . import viewsurlpatterns = [path('admin/', admin.site.urls),path('', views.index),path('alipay_return/', views.alipay_return)
]
# views.py
import random
import string
from django.http import HttpResponseRedirect
from django.shortcuts import render
from ali_django.alipay import alipay_pay, create_alipay
from django.conf import settingsdef index(request):if request.method == "GET":return render(request, 'index.html')elif request.method == "POST":# 随机生成32位商户交易号out_trade_no = "".join(random.sample(string.ascii_letters + string.digits, 32))order_string = alipay_pay(subject="测试商品", total_amount=100, out_trade_no=out_trade_no,return_url_view='alipay_return')return HttpResponseRedirect(settings.GATEWAY + order_string)def alipay_return(request):processed_dict = {}# 回调时alipay会把一些公用信息通过GET方式传参回来,这里用字典去接收存储for key, value in request.GET.items():processed_dict[key] = valuesign = processed_dict.pop("sign", None)new_alipay = create_alipay()verify_re = new_alipay.verify(processed_dict, sign)if verify_re is True:print("支付成功")else:print("支付失败")
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>支付宝支付接口测试</title>
</head>
<body>
<form action="" method="post"><input type="submit" value="提交">
</form>
</body>
</html>

Django对接支付宝Alipay支付接口相关推荐

  1. 对接支付宝网站支付接口

    今天因为业务需要线上支付充值,所以需要对接支付宝的网站支付接口.首先去支付宝开发者中心看了一遍demo:网址如下:https://docs.open.alipay.com/270/106291/ 大致 ...

  2. [转]个人网站对接支付宝,微信支付接口史上最详细教程

    对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多像我一样的小白,第一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章,给我和我一样的同学,一点思路吧.三分钟就可以申请,支付宝个人即时 ...

  3. 网站对接支付宝,微信支付接口史上最详细教程

    联系qq:1104752746对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多像我一样的小白,第一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章,给我和我一样的同学,一点思路吧.三 ...

  4. Django对接支付宝实现支付宝充值金币功能示例

    很多网站里都有金币.积分之类的虚拟货币,获取这些往往需要充值.那么问题来了,如何在Django中对接支付宝实现支付宝充值金币的功能呢?网上很多资料都是电商的,那些都会带有订单系统之类比较复杂,而充值金 ...

  5. Django对接支付宝实现支付宝充值金币功能

    很多网站里都有金币.积分之类的虚拟货币,获取这些往往需要充值.那么问题来了,如何在Django中对接支付宝实现支付宝充值金币的功能呢?网上很多资料都是电商的,那些都会带有订单系统之类比较复杂,而充值金 ...

  6. java SpringBoot 对接支付宝 APP支付 证书模式及非证书模式

    一. 添加maven依赖 sdk <dependency><groupId>com.alipay.sdk</groupId><artifactId>al ...

  7. 网站对接支付宝进行支付

    本文介绍PC网页对接支付宝,完成批量向支付宝账户转账的功能(使用Java实现),首先我的水平是这样的:接到这个工作任务后,可以说我是大白,之前我做过银行的项目,懂签名和验签是怎么一回事,但是对接支付宝 ...

  8. 对接支付宝单笔转账接口

    对接支付宝单笔转账接口 功能介绍 接入准备 调用支付宝api需要以下参数: 项目引入 操作流程 创建小程序 配置小程序 集成配置 SDK 助手 详细操作流程 获取appId 获取证书 获取AES密钥 ...

  9. tp5 集成支付宝h5支付接口

    tp5 集成支付宝h5支付接口 前台支付的时候调取后台接口 function alipay(order_sn){$.ajax({url: '接口地址',type: "GET",da ...

最新文章

  1. 习题10-6 递归求Fabonacci数列 (10 分)
  2. mysql 之mvcc多版本控制
  3. SAP UI5 应用开发教程之四十一 - Chrome 扩展 UI5 Inspector 的离线安装和使用方法试读版
  4. from表单iframe原网页嵌入
  5. 有人抄袭微信红包和表情被罚了40万!这下“吹牛”可能牛不起来了
  6. 路由器信息备份还原指南
  7. [资料] GIS资料汇总(GIS+Envi+erdas视频教程)
  8. 李宏毅机器学习笔记【未完】
  9. 嵌入式常用通讯协议2(CAN协议)
  10. matlab 合成t检验,[zz]用MATLAB做T检验(ttest)
  11. Java一组数据,满足数量和求和的最优解
  12. 伽卡他卡学生端找不到计算机,伽卡他卡学生端
  13. Flutter 图片选取 image_picker
  14. C++OpenCV实现抠除(也可用于更换)证件照背景
  15. Webpack(打包工具)
  16. 一篇博客学会了坦克大战
  17. 推荐系统(十五)多任务学习:谷歌MMoE(Multi-gate Mixture-of-Experts )
  18. 越是见过世面的人,欲望越少
  19. 深度学习分布式训练框架 horovod (3)
  20. phonegap打包

热门文章

  1. python_爬虫 12 多线程爬虫
  2. md5加密工具类cookie登陆验证
  3. 抓娃娃机按钮按几下_揭秘娃娃机抓娃娃技巧全攻略
  4. 利用ajax实现织梦dedecms瀑布流无限加载功能
  5. 视频教程-JAVAEE真实课堂系列之javaScript全讲-云计算基础架构
  6. 重庆大学 计算机组成原理,计算机组成原理课程设计报告重庆大学
  7. mysql索引怎么设计,MySQL如何设计索引
  8. 下列关于python函数参数说法错误的是_以下关于函数说法错误的是
  9. 《淘宝网开店 拍摄 修图 设计 装修 实战150招》一一1.8 侧光拍摄增强轮廓感
  10. php获取目录下所有文件及目录(多种方法)