支付宝支付接入流程
一、 接入准备
支付宝支付流程没有微信那么复杂,而且支付宝支持沙箱。登录支付宝开放平台控制台
点击开发工具中的沙箱
接口加密方式,我这里使用的是自定义密钥。生成密钥的方式
- 使用支付宝官方提供的密钥工具,唯一要注意的是支付宝密钥工具生成的是 txt 格式的,也就是不包含头部和尾部标识的
-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----
- 使用
openssl
命令自己生成。openssl OpenSSL> genrsa -out app_private_key.pem 2048 # 私钥 OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥 OpenSSL> exit
我们需要的东西基本都有了。调试的使用可以下载工具支付宝客户端沙箱版
,用沙箱账号进行支付。
开发
import logging
from enum import Enumfrom Cryptodome.PublicKey import RSA
from alipay import AliPay, AliPayConfig"""
支付宝支付接入
SDK 文档:https://gitee.com/yqmc/alipay/blob/master/README.zh-hans.md
pip install python-alipay-sdk --upgrade
"""class AlipayType(Enum):WEB = 'web' # 电脑网站支付WAP = 'wap' # 手机网站支付APP = 'app' # app支付MINI = 'mini' # 小程序支付class AliPayClient:def __init__(self, appid, app_private_key_path, alipay_public_key_path, is_sandbox=False, default_notify_url=None,return_url=None):"""初始化数据:param appid: APP ID:param app_private_key_path: 应用私钥路径:param alipay_public_key_path: 支付宝公钥路经:param is_sandbox: 是否是沙箱模式:param default_notify_url: 默认通知地址"""self.appid = appidself.default_notify_url = default_notify_urlself.return_url = return_urlself.sandbox = is_sandboxself.alipay_gateway_url = 'https://openapi.alipay.com/gateway.do?' if not self.sandbox else 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?'self.app_private_key_string = self.read_secret(app_private_key_path)self.alipay_public_key_string = self.read_secret(alipay_public_key_path)self.alipay = AliPay(appid=self.appid,app_notify_url=self.default_notify_url,app_private_key_string=self.app_private_key_string,alipay_public_key_string=self.alipay_public_key_string,sign_type="RSA2",debug=True,verbose=True, # 输出调试数据config=AliPayConfig(timeout=15) # 可选,请求超时时间)if self.sandbox:logging.debug('当前为沙箱环境')@staticmethoddef read_secret(secret_path, import_key=False):"""从文件加载秘钥:param secret_path::param import_key: 是否需要导入秘钥:return:"""with open(secret_path, "r") as fp:return RSA.importKey(fp.read()) if import_key else fp.read()def create_order(self, out_trade_no, amount, subject, notify_url=None, return_url=None,pay_type=AlipayType.WEB.value):"""创建支付订单:param out_trade_no: 订单号:param amount: 金额:param subject: 订单备注:param notify_url: 通知地址:param return_url: 回调地址:param pay_type: AlipayType支付类型:return: order_string"""trade_client = {AlipayType.WEB.value: self.alipay.api_alipay_trade_page_pay,AlipayType.WAP.value: self.alipay.api_alipay_trade_wap_pay,AlipayType.APP.value: self.alipay.api_alipay_trade_app_pay,AlipayType.MINI.value: self.alipay.api_alipay_trade_create}kwargs = dict(out_trade_no=out_trade_no,total_amount=amount,subject=subject,notify_url=notify_url)pay_type in [AlipayType.WEB.value, AlipayType.WAP.value] and kwargs.update(return_url=return_url)order_string = trade_client[pay_type](**kwargs)return self.alipay_gateway_url + order_stringdef create_pre_order(self, subject, out_trade_no, amount, notify_url=None):"""交易预创建(扫码支付):param subject: 订单备注:param out_trade_no: 订单号:param amount: 金额:param notify_url: 通知地址return {'code': '10000', 'msg': 'Success', 'out_trade_no': '2023102401', 'qr_code': 'https://qr.alipay.com/bax01636yklunuyxijpc002f'}"""resp = self.alipay.api_alipay_trade_precreate(subject=subject,out_trade_no=out_trade_no,total_amount=amount,notify_url=notify_url)return respdef refund(self, out_trade_no, refund_amount):result = self.alipay.api_alipay_trade_refund(out_trade_no=out_trade_no, refund_amount=refund_amount)return True if result.get("code") == "10000" else Falsedef notify_verify(self, data):"""验证回调通知:验证 alipay 的异步通知:param data: 来自支付宝回调 POST 给你的 data,字典格式。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","out_trade_no": "xxxx","buyer_logon_id": "xxxx","notify_id": "xxxx","seller_email": "xxxx","receipt_amount": "0.01","invoice_amount": "0.01","sign": "xxx"}"""signature = data.pop("sign")# verificationsuccess = self.alipay.verify(data, signature)return success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED")