Django对接支付宝Alipay支付接口

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

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

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

下面看一下它的基本使用


调用流程

0ba3e82ad37ecf8649ee4219cfe9d16b

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

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

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

  • 商户系统接收到异步通知以后,必须通过验签(验证通知中的 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中设定一些关键参数

302882E3-C077-4B1C-8D51-BE26357A2F56

333D5B0A-4B1B-413F-B924-83CD9CB7097C

# 读取公钥和私钥为字符串
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, GATEWAY

def create_alipay():
  	# 使用应用公钥进行报文验签
    alipay = AliPay(
        appid=ALIPAY_APP_ID,
        app_notify_url=None,  # 默认异步回调 url
        app_private_key_string=APP_PRIVATE_KEY,
        alipay_public_key_string=ALIPAY_PUBLIC_KEY,
        sign_type="RSA2",
        debug=False,  # 默认 False
        verbose=False,  # 输出调试数据
        config=AliPayConfig(timeout=15)  # 可选,请求超时时间
    )
    return alipay

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

# 向支付宝提交订单信息
def alipay_pay(subject, total_amount, out_trade_no, return_url_view):
    alipay = create_alipay()	# 先实例化alipay
    return_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)

image-20220530114916011

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

image-20220530115037133

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

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等,等待回调后与参数校验一致无误后再将订单支付信息进行更新。下面的完整示例不会包括该部分,请自行完成


完整示例

项目结构

image-20220530124639727

# alipay.py
from alipay import AliPay, AliPayConfig
from .settings import APP_PRIVATE_KEY, ALIPAY_PUBLIC_KEY, ALIPAY_APP_ID, RETURN_URL


def create_alipay():
    alipay = AliPay(
        appid=ALIPAY_APP_ID,
        app_notify_url=None,  # 默认回调 url
        app_private_key_string=APP_PRIVATE_KEY,
        # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
        alipay_public_key_string=ALIPAY_PUBLIC_KEY,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=False,  # 默认 False
        verbose=False,  # 输出调试数据
        config=AliPayConfig(timeout=15)  # 可选,请求超时时间
    )
    return alipay


def alipay_pay(subject, total_amount, out_trade_no, return_url_view):
    alipay = create_alipay()
    return_url = RETURN_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,
        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 views

urlpatterns = [
    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 settings


def 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] = value
    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("支付失败")
<!-- 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>
  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django是一个基于Python的开源Web框架,它提供了一套完整的开发工具和库,用于快速构建高效的Web应用程序。支付宝支付是指在Django中集成支付宝支付功能,使用户可以通过支付宝进行在线支付。 要在Django中实现支付宝支付,可以按照以下步骤进行操作: 1. 注册支付宝开发者账号并创建应用:首先,你需要在支付宝开放平台注册一个开发者账号,并创建一个应用。在创建应用时,你会获得一些必要的信息,如App ID、App Key等。 2. 安装支付宝SDK:使用pip命令安装支付宝SDK,可以在Django项目的虚拟环境中执行以下命令: ``` pip install alipay-sdk-python ``` 3. 配置支付宝参数:在Django项目的配置文件中,添加支付宝相关的配置参数,包括App ID、App Key、支付宝公钥、私钥等。 4. 创建支付视图:在Django项目中创建一个视图函数,用于处理用户发起支付请求的逻辑。在该视图函数中,你需要构建支付宝支付接口所需的参数,并将其传递给支付宝SDK进行处理。 5. 处理支付结果回调:支付宝支付完成后,会向你预先设置的回调URL发送异步通知,通知你支付结果。你需要在Django项目中创建一个接收支付结果回调的视图函数,用于处理支付宝发送的异步通知,并校验支付结果的有效性。 以上是实现Django支付宝支付的基本步骤。当然,具体的实现方式还会根据你的需求和业务逻辑有所不同。你可以参考支付宝开放平台提供的文档和示例代码,以及Django官方文档中关于视图函数和URL配置的内容,来更详细地了解和实现支付宝支付功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值