DRF实操——支付宝的介绍与对接支付宝

1. 支付宝的介绍

实际上线环境:

  1. 在浏览器搜索“支付宝开放平台”,扫码登录。

在这里插入图片描述
2. 进入控制台
在这里插入图片描述
3. 网页移动应用——创建网页移动应用
在这里插入图片描述
4. 填写信息,会生成这个应用的appid,会绑定真实的账户,进行对接。
在这里插入图片描述

开发环境:

我们在开发过程中使用的是沙箱环境,进行调试和开发。
应用appid,商家信息,用户信息,都是模拟的

  1. 在控制台中找到“沙箱”
    在这里插入图片描述

  2. 沙箱中有一个appid,上线之后,直接改成在实际生成的ID即可
    在这里插入图片描述

  3. 沙箱应用——开发信息——接口加签方式——自定义秘钥——公钥模式,点击启用——支付宝秘钥生成器——秘钥工具下载
    在这里插入图片描述

  4. 打开下载的秘钥工具,点击生成秘钥

在这里插入图片描述
在这里插入图片描述
5. 新建两个记事本txt文件,分别保存生成的应用公钥应用私钥

  1. 将应用公钥填写到加签管理这个页面(即第3步的页面),点击保存显示加签完成,这时候会生成一个支付宝公钥
    在这里插入图片描述

2. DRF对接支付宝

1. 创建配置文件

这里要用公钥进行加密,用私钥进行解密。配置错误会导致无法核销。

  1. 在config文件夹下创建一个名为alipay_key的文件夹
    在这里插入图片描述
  2. 在该文件夹下创建一个alipay_public的文件用来存放支付宝公钥。开头要加上-----BEGIN PUBLKIKC KEY-----,结尾要加上-----END PUBLKIKC KEY-----
    在这里插入图片描述
  3. 再创建一个app_private_key的文件用来存放应用私钥。开头要加上-----BEGIN RSA PRIVATE KEY-----,结尾要加上-----END RSA PRIVATE KEY-----
    在这里插入图片描述
  4. 创建一个appid的文件,将沙箱环境中的appid复制过来
    在这里插入图片描述

2. 在setting文件中,做支付宝配置

#支付宝配置
APPID = open(f'{BASE_DIR}/config/alipay_key/appid').read()
APP_PRIVATE_KEY_STRING = open(f'{BASE_DIR}/config/alipay_key/app_private_key').read()
ALIPAY_PUBLIC_KEY_STRING = open(f'{BASE_DIR}/config/alipay_key/alipay_public').read()

在这里插入图片描述

3. 安装支付宝第三方库

pip install python-alipay-sdk -i https://pypi.douban.com/simple

在这里插入图片描述

4. 在setting文件中实例化支付宝对象

# 实例化支付宝对象
alipay = AliPay(
    appid=APPID,
    app_notify_url =None,
    app_private_key_string=APP_PRIVATE_KEY_STRING,
    alipay_public_key_string=ALIPAY_PUBLIC_KEY_STRING,
    sign_type='RSA2',
    # 如果是沙箱环境,要将debug设置为True
    debug=True
)

在这里插入图片描述

5.创建模型,保存订单的支付交易号

  1. 创建一个支付信息模型
class Payment(DateTimeModelMixin):
    trade_id = models.CharField(max_length=100,unique=True,verbose_name='支付宝交易号')
    order  = models.ForeignKey(Order,on_delete=models.CASCADE,verbose_name='订单')

    class Meta:
        ordering=['-create_time']
        db_table = 'payment'
        verbose_name = '支付信息'
        verbose_name_plural = verbose_name
  1. 创建序列化器
class PaymentSerializer(ModelSerializer):

    class Meta:
        model = Payment
        fields = '__all__'
  1. 创建视图,并实现支付接口。
    路由记得自己配置。
class OrderCartViewSet(ReadOnlyModelViewSet,CreateModelMixin):
    serializer_class = OrderCartSerializer
    permission_classes = [IsAuthenticated]

    # 返回当前登录用户的数据
    def get_queryset(self):
        # 使用管理器:源模型类小写_set
        return self.request.user.order_set.all()
    
    @action(methods=['put'],detail=False)
    def status(self,request):
        """
        支付成功后将订单状态从待支付改为待发货
        """
        # 得到支付宝回调过来的数据,在请求地址里卖弄
        query_dict = request.query_params #得到地址栏的参数 比如:https://www.baidu.com?sign=xxx
        data = query_dict.dict()
        # 不能无脑直接修改订单状态,核实身份
        try:
            #类似于token
            # pop 方法会从字典中删除指定的键(在这里是 'sign')
            # 如果键存在,它会返回该键的值;如果键不存在,则会引发 KeyError
            sign = data.pop('sign') #删除data里面的sign
        except KeyError:
            return Response(status=HTTP_400_BAD_REQUEST)
        # 验证sign。data的其他数据加密后会得到sign,这里把data传入alipay进行加密在跟sign进行比对校验
        res = alipay.verify(data,sign)
        if not res:
            return Response(status=HTTP_403_FORBIDDEN)
        
        #得到订单编号,支付宝交易号
        order_id = data.get('out_trade_no') #订单编号 out_trade_no固定参数
        trade_no = data.get('trade_no' ) #支付宝交易号 trade_no固定参数

        # 保存支付信息,修改订单状态
        # 这两个动作要一起完成,所以加入事务
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                Payment.objects.create(order_id=order_id,trade_id=trade_no)
                Order.objects.filter(order_id=order_id,status=1).update(status=2)
            except Exception as e:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError(e)
            else:
                transaction.savepoint_commit(save_point)

        return Response({'order_id':order_id,'trade_id':trade_no})


class PaymentViewSet(ReadOnlyModelViewSet):
    queryset = Payment.objects.all()
    serializer_class = PaymentSerializer
    permission_classes = [IsAuthenticated]
 
    @action(methods=['get'],detail=True)
    def pay(self,request,pk):
        """
        返回支付页面
        """
        #获取订单信息,必须是当前登录的用户的订单,并且是没有支付的
        try:
            order = Order.objects.get(order_id=pk,user=request.user,status=1)
        except Order.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        
        # 对接支付宝,返回支付页面
        # 通过支付宝对象处理订单信息
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_id, #订单号传过去
            total_amount = str(order.total_amount), #要支付的金额
            subject=f'PROMOTE系统{order.order_id}',#标题
            # 这里可以配置到配置文件中去,前端更新,方便我们同步更新
            return_url='http://localhost:8080/home/order/success', #回调地址,成功后就跳转到前端的支付成功的页面
        )
        # 将订单信息发送给支付宝
        #即沙箱环境中的支付宝网关地址
        pay_url = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?' + order_string

        # 返回支付页面,前端拿到这个地址后发起请求,就会跳转到支付宝的支付页面
        return Response({'pay_url':pay_url})
  1. 点击支付后,页面会跳转到支付宝的支付页面
    在这里插入图片描述
  2. 在支付宝开放平台找到买家账号密码进行登录
    在这里插入图片描述
  3. 支付成功后会根据回调地址跳转到我们前端的支付成功页面
    在这里插入图片描述
  4. 在加载这个页面时,前端就会拿到这个页面中的订单参数,去访问OrderCartViewSet中的status接口,修改订单状态为待发货。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值