【无标题】

第19次:支付

分析

  1. 因要用到支付宝沙箱模拟支付功能,所以要在支付宝开放平台完成创建应用、申请密钥的相关操作
  2. 需要用到支付宝和应用的两对密钥,并配置到项目和支付宝开放平台。
  3. 在商城订单提交页面,点击“去支付”按钮,向支付宝发送支付请求,浏览器会跳转到支付宝登录页面。在登录页面需要使用沙箱账号中的买家账号和密码登录至支付宝。登录成功后,进行支付页面,用户输入支付密码完成支付;支付成功后,支付宝将自动重定向到商城的“订单支付成功”页面。
  4. 支付成功后,支付宝将页面重定向到settings.py定义的ALIPAY_RETURN_URL指定的回调地址,将支付结果返回。

实现

在支付宝开放平台下载支付定密钥工具,用于生成公钥和私钥。
在这里插入图片描述
在这里插入图片描述
生成密钥,加签方式:密钥,加密算法:RSA2
在这里插入图片描述
生成的密钥会自动保存在本地
在这里插入图片描述
找到沙箱页面:https://open.alipay.com/develop/sandbox/app
在这里插入图片描述
将刚才生成的应用公钥复制到应用公钥栏,点击“保存”按钮,将会生成支付宝公钥,复制支付宝公钥,在商城项目的payment应用下新建keys目录,并在该文件夹中创建alipay_public_key.pem和app_private_key.pem。

将支付宝公钥复制alipay_public_key.pem中,并补充如下头部和尾部信息,注意要换行。

-----BEGIN RSA PUBLIC KEY-----
公钥
-----END RSA PUBLIC KEY-----

将应用私钥复制到app_private_key.pem中,并补充如下头部和尾部信息,注意要换行。

-----BEGIN RSA PRIVATE KEY-----
私钥
-----END RSA PRIVATE KEY-----

在这里插入图片描述
在settings.py中配置SDK参数

ALIPAY_APPID = '2021000122674572'
ALIPAY_DEBUG = True
ALIPAY_URL = 'https://openapi.alipaydev.com/gateway.do'
ALIPAY_RETURN_URL = 'http://127.0.0.1:8000/payment/status/'

安装支付宝sdk

 pip install python-alipay-sdk

在payment应用的views.py中定义PaymentView视图类,用于实现订单支付,接收页面点击“去支付”时发送的支付请求,根据order_id,创建支付对象,生成支付宝登录链接

import os

from alipay import AliPay
from django.conf import settings
from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View

from orders.models import OrderInfo
from payment.models import Payment
from xiaoyu_mall_new.utils.response_code import RETCODE
from xiaoyu_mall_new.utils.views import LoginRequiredJSONMixin

class PaymentView(LoginRequiredJSONMixin, View):

    def get(self, request, order_id):
        # 获取登录用户
        user = request.user
        # 查询待支付订单
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])
        except OrderInfo.DoesNotExist:
            return HttpResponseForbidden('订单信息错误')
        # 创建支付对象
        alipay = AliPay(
            appid=settings.ALIPAY_APPID, app_notify_url=None,
            app_private_key_string=open(os.path.join(os.path.dirname(__file__), 'keys/app_private_key.pem')).read(),
            alipay_public_key_string=open(os.path.join(os.path.dirname(__file__), 'keys/alipay_public_key.pem')).read(),
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG,
        )
        # 生成支付宝登录链接
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(order.total_amount),
            subject='小鱼商城%s' % order_id,
            return_url=settings.ALIPAY_RETURN_URL,
        )

        alipay_url = settings.ALIPAY_URL + '?' + order_string
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'alipay_url': alipay_url})

配置子路由,在payment应用下创建urls.py,并增加子路由

from django.urls import path

from payment.views import PaymentView

app_name = 'payment'
urlpatterns = [
    path(route='payment/<int:order_id>/', view=PaymentView.as_view()),
]

在项目urls.py中增加payment应用的子路由

path('', include('payment.urls', namespace='payment')),

支付成功后,支付宝会发起GET请求,将支付结果返回给return_url参数指定的回调地址,在payment应用中views中定义这个回调视图,完整的views.py代码为

import os

from alipay import AliPay
from django.conf import settings
from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View

from orders.models import OrderInfo
from payment.models import Payment
from xiaoyu_mall_new.utils.response_code import RETCODE
from xiaoyu_mall_new.utils.views import LoginRequiredJSONMixin

class PaymentView(LoginRequiredJSONMixin, View):

    def get(self, request, order_id):
        # 获取登录用户
        user = request.user
        # 查询待支付订单
        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])
        except OrderInfo.DoesNotExist:
            return HttpResponseForbidden('订单信息错误')
        # 创建支付对象
        alipay = AliPay(
            appid=settings.ALIPAY_APPID, app_notify_url=None,
            app_private_key_string=open(os.path.join(os.path.dirname(__file__), 'keys/app_private_key.pem')).read(),
            alipay_public_key_string=open(os.path.join(os.path.dirname(__file__), 'keys/alipay_public_key.pem')).read(),
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG,
        )
        # 生成支付宝登录链接
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(order.total_amount),
            subject='小鱼商城%s' % order_id,
            return_url=settings.ALIPAY_RETURN_URL,
        )

        alipay_url = settings.ALIPAY_URL + '?' + order_string
        return JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'alipay_url': alipay_url})


class PaymentStatusView(View):
    # 保存订单支付结果
    def get(self, request):
        # 获取到所有查询字符串参数
        query_dict = request.GET
        # 转换成字典类型
        data = query_dict.dict()
        # 移除sign
        signature = data.pop('sign')
        alipay = AliPay(
            appid=settings.ALIPAY_APPID, app_notify_url=None,
            app_private_key_string=open(
                os.path.join(os.path.dirname(__file__)), 'keys/app_private_key.pem').read(),
            alipay_public_key_string=open(
                os.path.join(os.path.dirname(__file__), 'keys/alipay_public_key.pem')).read(),
            sign_type='RSA2',
            debug=settings.ALIPAY_DEBUG,
        )

        success = alipay.verify(data, signature)
        if success:
            order_id = data.get('out_trade_no')
            trade_id = data.get('trade_no')
            Payment.objects.create(
                order_id=order_id, trade_id=trade_id,
            )
            OrderInfo.objects.filter(order_id=order_id, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID']).update(
                status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT']
            )

            context = {'trade_id': trade_id}

            return render(request, 'pay_success.html', context)
        else:
            return redirect(reverse('users:myorderinfo'))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值