支付宝支付接口

支付宝支付接口

支付宝支付

# 1、在沙箱环境下实名认证:https://openhome.alipay.com/platform/appDaily.htm?tab=info
?
# 2、电脑网站支付API:https://docs.open.alipay.com/270/105898/
?
# 3、完成RSA密钥生成:https://docs.open.alipay.com/291/105971
?
# 4、在开发中心的沙箱应用下设置应用公钥:
    拿着在支付宝平台开发助手生成的公钥到沙箱应用下换取支付宝公钥
?
# 5、Python支付宝开源框架:https://github.com/fzlee/alipay
# >: pip install python-alipay-sdk --upgrade
?
# 7、公钥私钥设置
"""
# alipay_public_key.pem
-----BEGIN PUBLIC KEY-----
支付宝公钥
-----END PUBLIC KEY-----
?
# app_private_key.pem
-----BEGIN RSA PRIVATE KEY-----
用户私钥
-----END RSA PRIVATE KEY-----
"""
?
# 8、支付宝链接
"""
开发:https://openapi.alipay.com/gateway.do
沙箱:https://openapi.alipaydev.com/gateway.do
"""

支付流程

 支付宝支付接口

aliapy二次封装包

依赖
>: pip install python-alipay-sdk --upgrade
结构
libs
    ├── iPay                            # aliapy二次封装包
    │   ├── __init__.py                 # 包文件
    │   ├── keys                        # 密钥文件夹
    │   │   ├── alipay_public_key.pem   # 支付宝公钥
    │   │   └── app_private_key.pem     # 应用私钥
    └── └── settings.py                 # 应用配置
setting.py
import os
# 支付宝应用APPID
APP_ID = ‘2016093000631831‘
# 默认异步回调的地址,通常设置None就行
APP_NOTIFY_URL = None
# 应用私钥文件路径
APP_PRIVATE_KEY_PATH = os.path.join(os.path.dirname(__file__), ‘keys‘, ‘app_private_key.pem‘)
# 支付宝公钥文件路径
ALIPAY_PUBLIC_KEY_PATH = os.path.join(os.path.dirname(__file__), ‘keys‘, ‘alipay_public_key.pem‘)
# 签名方式
SIGN_TYPE = ‘RSA2‘
# 是否是测试环境 - 是否是支付宝沙箱
DEBUG = True
# 支付连接
DEV_PAY_URL = ‘https://openapi.alipaydev.com/gateway.do?‘  # 沙盒
PROD_PAY_URL = ‘https://openapi.alipay.com/gateway.do?‘
__init__.py
from alipay import AliPay
from .settings import *
# 对外提供支付对象
alipay = AliPay(
    appid=APP_ID,
    app_notify_url=APP_NOTIFY_URL,
    app_private_key_path=APP_PRIVATE_KEY_PATH,
    alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,
    sign_type=SIGN_TYPE,
    debug=DEBUG
)
?
# 对外提供的支付链接前缀
pay_url = DEV_PAY_URL if DEBUG else PROD_PAY_URL
alipay_public_key.pem
-----BEGIN PUBLIC KEY-----
支付宝公钥
-----END PUBLIC KEY-----
app_private_key.pem
-----BEGIN RSA PRIVATE KEY-----
应用私钥
-----END RSA PRIVATE KEY-----
补充:dev.py
# 前后台base_url
UP_BASE_URL = ‘http://127.0.0.1:8080‘
END_BASE_URL = ‘http://127.0.0.1:8000‘
?
# alipay回调接口配置
# 上线后必须换成官网地址
# 同步回调的接口(get),前后台分离时一般设置前台页面url
RETURN_URL = UP_BASE_URL + ‘/pay/success‘
# 异步回调的接口(post),一定设置为后台服务器接口
NOTIFY_URL = END_BASE_URL + ‘/order/success/‘

 案例

# 前后台base_url
UP_BASE_URL = ‘http://127.0.0.1:8080‘
END_BASE_URL = ‘http://127.0.0.1:8000‘
# alipay回调接口配置
# 上线后必须换成官网地址
# 同步回调的接口(get),前后台分离时一般设置前台页面url
RETURN_URL = UP_BASE_URL + ‘/pay/success‘
# 异步回调的接口(post),一定设置为后台服务器接口
NOTIFY_URL = END_BASE_URL + ‘/order/success/‘

项目/dev.py

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView

from libs.ipay import alipay, pay_url
import time
from . import models
from django.conf import settings
from utils.response import APIResponse
from utils.logging import logger
from rest_framework.response import Response

from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
# 支付接口需要登录认证
class PayAPIView(APIView):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        # 1)获取前台信息:商品、价格、支付方式
        request_data = request.data
        subject = request_data.get(‘subject‘)
        total_amount = request_data.get(‘total_amount‘)
        pay_type = request_data.get(‘pay_type‘)
        if not (subject and total_amount and pay_type):
            return APIResponse(2, ‘数据有误‘)

        # 2)生成订单(订单号,订单表的订单记录)
        out_trade_no = str(time.time())
        user = request.user  # 当前登录用户
        try:
            models.Order.objects.create(subject=subject, total_amount=total_amount, pay_type=pay_type, out_trade_no=out_trade_no, user=user)
        except:
            return APIResponse(1, ‘订单生成失败‘)
        # 3)生成支付链接,并返回
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=total_amount,
            subject=subject,
            return_url=settings.RETURN_URL,
            notify_url=settings.NOTIFY_URL
        )
        order_url = pay_url + order_string
        return APIResponse(order_url=order_url)


# 支付成功的回调不需要登录认证 - 支付宝回调不会携带jwt-token,但是支付回调参数需要自己做校验
class SuccessAPIView(APIView):
    # 同步回调
    def patch(self, request, *args, **kwargs):
        # request.query_params是QueryDict类型,不能调用pop方法
        request_data = request.query_params.dict()
        signature = request_data.pop("sign")
        success = alipay.verify(request_data, signature)
        if success:  # 校验通过
            print("通过")
            # 一般不在该处修改订单状态
            return APIResponse()
        return APIResponse(1, ‘校验失败‘)

    # 支付宝异步回调
    def post(self, request, *args, **kwargs):
        # 默认是QueryDict类型,不能使用pop方法
        request_data = request.data.dict()
        # 必须将 sign、sign_type(内部有安全处理) 从数据中取出,拿sign与剩下的数据进行校验
        sign = request_data.pop(‘sign‘)
        result = alipay.verify(request_data, sign)
        # 异步回调:修改订单状态
        if result and request_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
            out_trade_no = request_data.get(‘out_trade_no‘)
            logger.critical(‘%s支付成功‘ % out_trade_no)
            try:
                order = models.Order.objects.get(out_trade_no=out_trade_no)
                if order.order_status != 1:
                    order.order_status = 1
                    order.save()
                    return Response(‘success‘)  # 必须返回success字符串,8次异步回调机制
            except:
                pass
        return Response(‘failed‘)

view.py

from django.urls import path, re_path
from . import views
urlpatterns = [
    # 支付接口 - 订单信息换支付链接
    path(‘pay/‘, views.PayAPIView.as_view()),
    # 支付成功结果 - 修改订单状态
    path(‘success/‘, views.SuccessAPIView.as_view())
]

urls.py