Django实现支付宝支付(沙箱环境)

python编程快速上手(持续更新中…)

python实战项目(Django技术点)


1. 创建应用和沙箱环境

沙箱应用:https://openhome.alipay.com/platform/appDaily.htm?tab=info

扫码注册
Django实现支付宝支付(沙箱环境)_第1张图片
Django实现支付宝支付(沙箱环境)_第2张图片

沙箱账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account

额度可以自行修改
Django实现支付宝支付(沙箱环境)_第3张图片

2. 支付宝开发文档

文档主页: https://openhome.alipay.com/developmentDocument.htm
电脑网站支付产品介绍: https://docs.open.alipay.com/270
电脑网站支付快速接入: https://docs.open.alipay.com/270/105899/
API列表: https://docs.open.alipay.com/270/105900/
SDK文档: https://docs.open.alipay.com/270/106291/
Python支付宝SDK: https://github.com/fzlee/alipay/blob/master/README.zh-hans.md

3. 电脑网站支付流程

Django实现支付宝支付(沙箱环境)_第4张图片

4. 配置RSA2公私钥

提示:

美多商城私钥加密数据,美多商城公钥解密数据。
支付宝私钥加密数据,支付宝公钥解密数据。
Django实现支付宝支付(沙箱环境)_第5张图片

生成RSA2密钥

1.Linux中生成公私钥

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

$ OpenSSL> exit

2.配置美多商城公私钥

配置美多商城私钥

a.新建子应用pay,在该子应用下新建文件夹keys用于存储公私钥
将制作的美多商城私钥app_private_key.pem拷贝到keys文件夹中。
Django实现支付宝支付(沙箱环境)_第6张图片

b.将payment.keys.app_public_key.pem文件中内容上传到支付宝。
Django实现支付宝支付(沙箱环境)_第7张图片
Django实现支付宝支付(沙箱环境)_第8张图片
3.配置支付宝公钥
将支付宝公钥内容拷贝到应用key文件夹下:payment.keys.alipay_public_key.pem文件中。

-----BEGIN PUBLIC KEY-----
支付宝公钥内容
-----END PUBLIC KEY-----

Django实现支付宝支付(沙箱环境)_第9张图片

5.订单支付功能

提示:

订单支付触发页面:《order_success.html》 和 《user_center_order.html》

我们实现订单支付功能时,只需要向支付宝获取登录链接即可,进入到支付宝系统后就是用户向支付宝进行支付的行为。

1.请求方式

选项 方案
请求方法 GET
请求地址 /payment/(?P\d+)/

2.请求参数:路径参数

参数名 类型 是否必传 说明
order_id int 订单编号

3.响应结果:JSON

字段 说明
code 状态码
errmsg 错误信息
alipay_url 支付宝登录链接

4.后端接口定义和实现

A.创建子应用

django-admin startapp pay

B.添加模块

INSTALLED_APPS = [
‘apps.pay’,
]

C.配置路由

urlpatterns = [
path(‘payment//’,PayUrlView.as_view()),
]

urlpatterns = [
path(’’,include(‘apps.pay.urls’)),
]

D.业务逻辑

"""
需求:
    当用户点击去支付按钮的时候,要后端生成一个跳转的连接

前端:
        axios 请求. 携带 订单id
后端:

    请求:             获取订单id
    业务逻辑:          生成支付宝链接(读取文档)
                    读取应用私钥和支付宝公钥
                    创建支付宝实例,调用支付宝的方法
                    拼接连接
    响应:
    路由:     GET    payment/order_id/ 
    步骤:
        1. 获取订单id
        2. 验证订单id (根据订单id查询订单信息)
        3. 读取应用私钥和支付宝公钥
        4. 创建支付宝实例
        5. 调用支付宝的支付方法
        6.  拼接连接
        7. 返回响应

"""
from django.views import View
from apps.orders.models import OrderInfo
from utils.views import LoginRequiredJSONMixin
from django.http import JsonResponse
from meiduo_mall import settings
from alipay import AliPay, AliPayConfig


class PayUrlView(LoginRequiredJSONMixin, View):

    def get(self, request, order_id):
        user = request.user
        # 1. 获取订单id
        # 2. 验证订单id (根据订单id查询订单信息)
        try:
            # 为了业务逻辑的准确性,
            # 查询待支付的订单
            order = OrderInfo.objects.get(order_id=order_id,
                                          status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'],
                                          user=user)
        except OrderInfo.DoesNotExist:
            return JsonResponse({
     'code': 400, 'errmsg': '没有此订单'})
        # 3. 读取应用私钥和支付宝公钥

        app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read()
        alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read()
        # 4. 创建支付宝实例
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key_string,
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_string=alipay_public_key_string,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=settings.ALIPAY_DEBUG,  # 默认False
            config=AliPayConfig(timeout=15)  # 可选, 请求超时时间
        )
        # 5. 调用支付宝的支付方法
        # 如果你是 Python 3的用户,使用默认的字符串即可
        subject = "多多商城测试订单"

        # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
        # https://openapi.alipay.com/gateway.do 这个是线上的
        # 'https://openapi.alipaydev.com/gateway.do' 这个是沙箱的
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(order.total_amount),  # 一定要进行类型转换,因为decimal不是基本数据类型
            subject=subject,
            return_url=settings.ALIPAY_RETURN_URL,  # 支付成功之后,跳转的页面
            notify_url="https://example.com/notify"  # 可选, 不填则使用默认notify url
        )
        # 6.  拼接连接
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        # 7. 返回响应
        return JsonResponse({
     'code': 0, 'errmsg': 'ok', 'alipay_url': pay_url})

E.我的测试
Django实现支付宝支付(沙箱环境)_第10张图片
Django实现支付宝支付(沙箱环境)_第11张图片

异常:Crtl+Shift+delete,清空浏览器缓存
Django实现支付宝支付(沙箱环境)_第12张图片

5.添加交易记录

添加模型

# Create your models here.
from django.db import models
from apps.orders.models import OrderInfo
from utils.models import BaseModel

class Payment(BaseModel):
    """支付信息"""
    order = models.ForeignKey(OrderInfo, on_delete=models.CASCADE, verbose_name='订单')
    trade_id = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name="支付编号")

    class Meta:
        db_table = 'tb_payment'
        verbose_name = '支付信息'
        verbose_name_plural = verbose_name

代码实现

"""
前端:
        当用户支付完成之后,会跳转到 指定商品页面
        页面中的请求 查询字符串中有 支付相关信息
        前端把这些数据提交给后端就可以了
后端:
    请求:         接收数据
    业务逻辑:       查询字符串转换为字典,验证数据,验证没有问题获取支付宝交易流水号
                  改变订单状态
    响应: 
    路由:     PUT     payment/status/
    步骤:
        1. 接收数据
        2. 查询字符串转换为字典 验证数据
        3. 验证没有问题获取支付宝交易流水号
        4. 改变订单状态
        5. 返回响应


买家账号[email protected]
登录密码111111
支付密码111111
"""
from apps.pay.models import Payment


class PaymentStatusView(View):

    def put(self, request):
        # 1. 接收数据
        data = request.GET
        # 2. 查询字符串转换为字典 验证数据
        data = data.dict()

        # 3. 验证没有问题获取支付宝交易流水号
        signature = data.pop("sign")

        app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read()
        alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read()
        # 创建支付宝实例
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key_string,
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_string=alipay_public_key_string,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=settings.ALIPAY_DEBUG,  # 默认False
            config=AliPayConfig(timeout=15)  # 可选, 请求超时时间
        )
        success = alipay.verify(data, signature)
        if success:
            # 获取 trade_no	String	必填	64	支付宝交易号
            trade_no = data.get('trade_no')
            order_id = data.get('out_trade_no')
            Payment.objects.create(
                trade_id=trade_no,
                order_id=order_id
            )
            # 4. 改变订单状态

            OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'])

            return JsonResponse({
     'code': 0, 'errmsg': 'ok', 'trade_id': trade_no})
        else:

            return JsonResponse({
     'code': 400, 'errmsg': '请到个人中心的订单中查询订单状态'})

展示鲜果

Django实现支付宝支付(沙箱环境)_第13张图片

你可能感兴趣的:(python,django,python,后端)