开源web框架django知识总结(二十二)

Posted 主打Python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开源web框架django知识总结(二十二)相关的知识,希望对你有一定的参考价值。

开源web框架django知识总结(二十二)

支付

提示:

  • 如果用户选择的支付方式是 “支付宝” ,在点击《去支付》时对接支付宝的支付系统。

支付宝介绍

支付宝开放平台入口

  • https://open.alipay.com/platform/home.htm

1.使用手机上的支付宝扫码登录

2. 创建应用和沙箱环境

1.创建应用

2.沙箱环境

支付宝提供给开发者的模拟支付的环境。跟真实环境是分开的。

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



配置支付宝“应用公钥”,“支付宝公钥”

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

买家账号sdkywg1362@sandbox.com
登录密码111111
支付密码111111
用户名称沙箱环境
证件类型身份证(IDENTITY_CARD)
证件号码847038195010111148
账户余额
2016215.53充值取现

3. 支付宝开发文档

  • 文档主页: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

    • SDK安装:pip install python-alipay-sdk==2.0.1
  1. 电脑网站支付流程

5.新建apps --> payment,注册,添加主路由,添加子urls.py

6.配置RSA2公/私钥

提示:

  • 阿尔法商城私钥加密数据,阿尔法商城公钥解密数据。
  • 支付宝私钥加密数据,支付宝公钥解密数据。

1.生成 阿尔法商城公/私钥

========================================================

对接支付宝系统

订单支付功能

提示:

  • 订单支付触发页面:《order_success.html》 和 《user_center_order.html》
  • 我们实现订单支付功能时,只需要向支付宝获取登录链接即可,进入到支付宝系统后就是用户向支付宝进行支付的行为。

1.请求方式

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

2.请求参数:路径参数

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

3.响应结果:JSON

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

4.后端接口定义和实现

payment.views.py

from django.views import View
from django.http import JsonResponse
from django.conf import settings
from orders.models import OrderInfo
from .models import Payment
from alipay import AliPay
import os


class PaymentView(View):

    # 接口1、获取支付页面链接
    def get(self, request, order_id):
        # 1、提取参数
        # 2、校验参数
        try:
            order = OrderInfo.objects.get(pk=order_id)
        except OrderInfo.DoesNotExist as e:
            print(e)
            return JsonResponse('code': 400, 'errmsg': '订单不存在!', status=404)

        # 3、获取支付页面链接  默认回调url
        alipay_url = None

        with open(os.path.join(settings.BASE_DIR, 'apps/payment/keys/app_private_key.pem'), "r") as f:
            app_private_key = f.read()
        with open(os.path.join(settings.BASE_DIR, 'apps/payment/keys/app_public_key.pem'), "r") as f:
            alipay_public_key = f.read()

        # 3.1 构建一个Alipay对象
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            # 异步回调,支付成功之后,阿里后台主动请求阿尔法
            app_notify_url=None,
            # 阿尔法私钥
            app_private_key_string=app_private_key,
            # 阿里公钥
            alipay_public_key_string=alipay_public_key,
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG
        )

        # 3.2 调用对象的方法
        # 扫码页面完整的链接是:
        # https://openapi.alipaydev.com/gateway.do?<查询字符串参数>
        # order_string = alipay.api_alipay_trade_app_pay() # 移动端
        # 网页端
        order_string = alipay.api_alipay_trade_page_pay(
            subject='阿尔法商城%s'%order_id,
            out_trade_no=order_id,
            total_amount=float(order.total_amount),
            # 支付成功之后,用户页面跳转地址
            return_url=settings.ALIPAY_RETURN_URL
        )

        # 4、构建响应返回
        alipay_url = settings.ALIPAY_URL + '?' + order_string

        return JsonResponse(
            'code': 0,
            'errmsg': 'ok',
            'alipay_url': alipay_url
        )

5.支付宝SDK配置参数

dev.py

# 阿里支付配置参数
ALIPAY_APPID = '2016102500755751'
ALIPAY_DEBUG = True
ALIPAY_URL = 'https://openapi.alipaydev.com/gateway.do'
ALIPAY_RETURN_URL = "http://127.0.0.1/pay_success.html"

=================================

保存订单支付结果

1. 支付结果数据说明

  • 用户订单支付成功后,支付宝会将用户重定向到 http://127.0.0.1:8000/payment/status/,并携带支付结果数据。
  • 参考统一收单下单并支付页面接口:https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay?scene=API002020081300013629
  1. 定义支付结果模型类
from django.db import models
from aerf_mall.utils.BaseModel import BaseModel
from orders.models import OrderInfo


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

3. 保存订单支付结果

1.请求方式

选项方案
请求方法GET
请求地址/payment/status/

2.请求参数:路径参数

参考统一收单下单并支付页面接口中的《页面回跳参数》

3.响应结果:HTML

pay_success.html

4.后端接口定义和实现

注意:保存订单支付结果的同时,还需要修改订单的状态为待评价

class PaymentStatusView(View):

    def put(self, request):
        # 用户支付成功之后,跳转回阿尔法页面的请求
        # 校验是否支付成功

        # 1、提取查询字符串参数
        data = request.GET # QueryDict类型
        data = data.dict() # QueryDict.dict()转化成普通字典
        # 提取签名(token值)
        sign = data.pop('sign')

        with open(os.path.join(settings.BASE_DIR, 'apps/payment/keys/app_private_key.pem'), "r") as f:
            app_private_key = f.read()
        with open(os.path.join(settings.BASE_DIR, 'apps/payment/keys/app_public_key.pem'), "r") as f:
            alipay_public_key = f.read()

        # 2、根据签名验证数据是否完整
        alipay = AliPay(
            appid=settings.ALIPAY_APPID,
            # 异步回调,支付成功之后,阿里后台主动请求阿尔法
            app_notify_url=None,
            # 阿尔法私钥
            app_private_key_string=app_private_key,
            # 阿里公钥
            alipay_public_key_string=alipay_public_key,
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG
        )
        if not alipay.verify(
            data,
            signature=sign
        ):
            return JsonResponse('code': 400, 'errmsg': '支付失败!', status=400)

        # 3、阿尔法订单号和支付宝流水号关联
        order_id = data.get('out_trade_no')
        trade_id = data.get('trade_no')

        try:
            Payment.objects.create(
                order_id=order_id,
                trade_id=trade_id,
            )
        except Exception as e:
            print(e)
            return JsonResponse(
                'code': 400,
                'errmsg': '支付订单保存失败!'
            )

        # 修改订单状态
        OrderInfo.objects.filter(
            order_id=order_id
        ).update(
            status=OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        )

        return JsonResponse(
            'code': 0,
            'errmsg': 'ok',
            'trade_id': trade_id
        )

payment.urls.py

from django.urls import re_path
from . import views

urlpatterns = [
# 订单支付
    re_path(r'^payment/(?P<order_id>\\d+)/$', views.PaymentView.as_view()),
# 订单支付状态
    re_path(r'^payment/status/$', views.PaymentStatusView.as_view()),
]

以上是关于开源web框架django知识总结(二十二)的主要内容,如果未能解决你的问题,请参考以下文章

开源web框架django知识总结(二十二)

开源web框架django知识总结(二十)

开源web框架django知识总结(二十)

开源web框架django知识总结(二十)

开源web框架django知识总结(二十一)

开源web框架django知识总结(二十一)