支付宝支付

一. 官方sdk

1.下载

需要下载支付宝沙箱版,如图 1 所示:

地址:https://open.alipay.com/develop/sandbox/tool

登录此应用账号密码,如图 2 所示:

图一:
图二:

2.代码(部分代码)

代码地址:https://pypi.org/project/alipay-sdk-python/

# 依赖安装
pip install alipay-sdk-python

# 下面代码需要修改的字段 《在 1 中沙箱应用中可找到》
"""
    server_url
    app_id
    app_private_key
    alipay_public_key
    out_trade_no
    total_amount
    subject
"""
# -*- coding: utf-8 -*-

import logging
import traceback

from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest


logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(message)s",
    filemode="a",
)
logger = logging.getLogger("")


if __name__ == "__main__":

    alipay_client_config = AlipayClientConfig()

    # 支付宝网关地址
    alipay_client_config.server_url = (
        "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
    )
    # APPID
    alipay_client_config.app_id = ""
    # 应用私钥
    alipay_client_config.app_private_key = ""
    # 支付宝公钥
    alipay_client_config.alipay_public_key = ""

    """
    得到客户端对象。
    注意,一个alipay_client_config对象对应一个DefaultAlipayClient,
    定义DefaultAlipayClient对象后,alipay_client_config不得修改,
    如果想使用不同的配置,请定义不同的DefaultAlipayClient。
    logger参数用于打印日志,不传则不打印,建议传递。
    """
    client = DefaultAlipayClient(
        alipay_client_config=alipay_client_config, logger=logger
    )

    """
    页面接口示例:alipay.trade.page.pay
    """
    # 对照接口文档,构造请求对象
    model = AlipayTradePagePayModel()
    # out_trade_no 相当于一个订单号,每笔订单不一样
    model.out_trade_no = "221213213"
    # total_amount 订单价格
    model.total_amount = 51
    model.subject = "测试1"
    model.body = "支付宝测试1"
    model.product_code = "FAST_INSTANT_TRADE_PAY"

    request = AlipayTradePagePayRequest(biz_model=model)

    # 订单交易成功还回的地址
    request.return_url = "http://www.baidu.com"
    request.notify_url = "http://www.baidu.com/post"

    # 得到构造的请求,如果http_method是GET,则是一个带完成请求参数的url,如果http_method是POST,则是一段HTML表单片段
    response = client.page_execute(request, http_method="GET")
    print("alipay.trade.page.pay response:" + response)

二. 第三方sdk

1. 准备

地址:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md

如图一使用步骤

图一:

(1). 准备

1. 安装

pip install python-alipay-sdk

2. 生成密钥文件 《用支付宝已有的也行》

1. 本人已经生成,如果没有生成过,如图 1 ,第二步点进去生成,需要下载《支付宝开放平台密钥工具,或第三方》。

2. 用下载好的软件生成 公钥私钥,《打开文件位置,就是公私钥文件》

3. 将生成的 公钥 复制到 1 中的 自定义密钥中,保存后会生成 支付宝公钥

2.代码

(1)创建文件

创建两个文件,***《项目中下面不要有换行》***

app_private.pem 和 public_key_ali.pem

# ----------------------- app_private.pem 文件内容 -----------------------

-----BEGIN RSA PRIVATE KEY-----

  在中间放入你的私钥

-----END RSA PRIVATE KEY-----

# ----------------------- public_key_ali.pem 文件内容 -----------------------

-----BEGIN PUBLIC KEY-----

  在中间放入你的支付宝公钥

-----END PUBLIC KEY-----

(2)编写代码

# --------------------------------- 初始化-----------------------------------

from alipay import AliPay, DCAliPay, ISVAliPay
from alipay.utils import AliPayConfig

# open 中放入(1)中文件的地址
app_private_key_string = open("yourPrivateKey.key").read() # 私钥
alipay_public_key_string = open("alipayPublicCert.pem").read() # 支付宝公钥

alipay = 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="RSA",  # RSA 或者 RSA2
    debug=False,  # 默认 False
    verbose=False,  # 输出调试数据
    config=AliPayConfig(timeout=15)  # 可选,请求超时时间
)

# --------------------------------- 接口-----------------------------------

# 电脑网站支付,需要跳转到:https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay.api_alipay_trade_page_pay(
    out_trade_no="20161112",
    total_amount=0.01,
    subject=subject,
    return_url="https://example.com",
    notify_url="https://example.com/notify" # 可选,不填则使用默认 notify url
)

print("https://openapi-sandbox.dl.alipaydev.com/gateway.do?" + order_string)

三. 封装(第三方)

1. 目录结构

libs
    ├── iPay                                # aliapy二次封装包
    │   ├── __init__.py                     # 包文件
    │   ├── pem                             # 公钥私钥文件夹
    │   │   ├── alipay_public_key.pem       # 支付宝公钥文件
    │   │   ├── app_private_key.pem         # 应用私钥文件
    │   ├── pay.py                          # 支付文件
    └── └── settings.py                     # 应用配置

2. 代码

公钥私钥文件夹中的文件代码, 参考上面的即可。

(1)pay.py

from alipay import AliPay
from alipay.utils import AliPayConfig
from . import settings


alipay = AliPay(
    appid=settings.APP_ID,

    app_notify_url=None,  # 默认回调 url

    # 私钥
    app_private_key_string=settings.APP_PRIVATE_KEY_STRING,
    # 支付宝的公钥
    alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY_STRING,
    # RSA 或者 RSA2
    sign_type=settings.SIGN,
    # 默认 False
    debug=settings.DEBUG,

    verbose=False,  # 输出调试数据
    config=AliPayConfig(timeout=15),  # 可选,请求超时时间
)

(2)settings.py

真实上线环境替换 “应用私钥”, “支付宝公钥” 和 “应用ID” 即可

import os

# 应用私钥
APP_PRIVATE_KEY_STRING = open(
    os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "pem", "app_private_key.pem"
    )
).read()
# 支付宝公钥
ALIPAY_PUBLIC_KEY_STRING = open(
    os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "pem", "alipay_public_key.pem"
    )
).read()

# 应用ID
APP_ID = "87897989879879879"

# 加密方式
SIGN = "RSA2"

# 是否是支付宝测试环境(沙箱环境),如果采用真是支付宝环境,配置False
DEBUG = True

# 支付网关
GATEWAY = (
    "https://openapi-sandbox.dl.alipaydev.com/gateway.do"
    if DEBUG
    else "https://openapi.alipay.com/gateway.do"
)

3. 支付宝回调接口(两个)

(1)路由

urlpatterns = [
    path('success/', PaySuccess.as_view()),
]

(2)视图类

1. get 回调 (给咱们前端用)

2. post回调(给支付宝回调用)

(1)核验的时候需将 result_data 中的签名去除掉《下面代码中 post 请求》

class PaySuccess(APIView):
    # 肯定不能有登录认证
    def get(self, request, *args, **kwargs):
        out_trade_no = request.query_params.get('out_trade_no')
        # 去数据库查询
        res = Order.objects.filter(out_trade_no=out_trade_no, order_status=1).first()
        if res:
            # 收到支付宝付款成功,修改了订单状态,返回给前端成功
            return APIResponse(msg='恭喜您付款成功,快去学习吧')
        else:
            return APIResponse(code=101, msg='暂未收到您的付款,请稍后刷新再试')



    # 支付宝异步回调处理--》修改订单状态---》支付宝不可能带token
    # 这个接口测试不了:咱们需要有公网ip才行
    # http://127.0.0.1:8000/api/v1/order/success/   post请求
    def post(self, request, *args, **kwargs):
        try:
            # json编码 --> 是字典
            # urlencoded --> querydict ---> dict() ----> 纯字典
            # 把 request.data  ---> 转成字典格式
            result_data = request.data.dict()
            out_trade_no = result_data.get('out_trade_no')
            trade_no = result_data.get('trade_no')

            # 去除掉签名
            signature = result_data.pop('sign')

            # 核验的时候需将 result_data 中的签名去除掉
            result = alipay.verify(result_data, signature)

            if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
                # 完成订单修改:订单状态、流水号、支付时间
                Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1, trade_no=trade_no)
                # 完成日志记录
                logger.warning('%s订单支付成功' % out_trade_no)
                return Response('success')
            else:
                logger.error('%s订单支付失败' % out_trade_no)
        except:
            pass
        return Response('failed')


#### 支付宝post回调地址一定要准确 ###
NOTIFY_URL = BACKEND_URL + "/api/v1/order/success/"

(3)post 回调格式

#  回调数据格式
data = {
     "subject": "测试订单",
     "gmt_payment": "2016-11-16 11:42:19",
     "charset": "utf-8",
     "seller_id": "xxxx",
     "trade_status": "TRADE_SUCCESS",
     "buyer_id": "xxxx",
     "auth_app_id": "xxxx",
     "buyer_pay_amount": "0.01",
     "version": "1.0",
     "gmt_create": "2016-11-16 11:42:18",
     "trade_no": "xxxx",
     "fund_bill_list": "[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]",
     "app_id": "xxxx",
     "notify_time": "2016-11-16 11:42:19",
     "point_amount": "0.00",
     "total_amount": "0.01",
     "notify_type": "trade_status_sync",

     # 咱们的uuid
     "out_trade_no": "订单号",

     "buyer_logon_id": "xxxx",
     "notify_id": "xxxx",
     "seller_email": "xxxx",
     "receipt_amount": "0.01",
     "invoice_amount": "0.01",

     # 验证签名
     "sign": "签名" 
}
posted @ 2024-04-27 12:05  codegjj  阅读(3)  评论(0编辑  收藏  举报