# alipay **Repository Path**: fastsource/alipay ## Basic Information - **Project Name**: alipay - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2020-09-20 - **Last Updated**: 2024-10-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## python-alipay-sdk [![PyPI version](https://badge.fury.io/py/python-alipay-sdk.svg)](https://badge.fury.io/py/python-alipay-sdk) [![codecov](https://codecov.io/gh/fzlee/alipay/branch/master/graph/badge.svg)](https://codecov.io/gh/fzlee/alipay) ![travis-ci](https://travis-ci.org/fzlee/alipay.svg?branch=master) ## 非官方支付宝 Python SDK 我们支持的所有支付方式,其签名类型必须为RSA或者RSA2。目前实现了以下功能: * [电脑网站支付](#alipay.trade.page.pay) * [手机网站支付](#alipay.trade.wap.pay) * [APP支付](#alipay.trade.app.pay) * [小程序支付](#alipay.trade.create) * [通知验证](#verification) * [当面付](#alipay.trade.pay) * [交易预创建](#alipay.trade.precreate) * [交易查询](#alipay.trade.precreate) * [交易取消](#alipay.trade.precreate) * [退款](#alipay.trade.refund) * [统一退款查询](#alipay.trade.fastpay.refund.query) * [统一收单交易结算接口](#alipay.trade.order.settle) * [统一收单交易关闭接口](#alipay.trade.close) * [单笔转账到支付宝账户接口](#alipay.fund.trans.toaccount.transfer) * [查询转账订单接口](#alipay.fund.trans.order.query) * [ISV集成/生成app_auth_code](#alipay.open.auth.token.app) * [ISV集成/查询授权产品](#alipay.open.auth.token.app.query) 关于签名的详细实现细节参看[这篇教程](https://ifconfiger.com/page/python-alipay-sdk). 如果你不希望深入了解技术实现的细节,你可以直接阅读下面的使用教程。 ## 使用教程 #### 安装 ```bash # 安装python-alipay-sdk pip install python-alipay-sdk --upgrade # 对于python2, 请安装2.0以下版本: pip install python-alipay-sdk==1.1 ``` #### 生成密钥文件 ```bash openssl OpenSSL> genrsa -out app_private_key.pem 2048 # 私钥 OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥 OpenSSL> exit ``` 在支付宝上下载的公钥是一个字符串,你需要在文本的首尾添加标记位 ``` -----BEGIN PUBLIC KEY----- 和 -----END PUBLIC KEY----- ``` 才能正常使用, 证书的格式你可以参考[这里](https://github.com/fzlee/alipay/blob/master/tests/certs/ali/ali_public_key.pem) #### 初始化 ```python from alipay import AliPay, DCAliPay, ISVAliPay from alipay.utils import AliPayConfig app_private_key_string = open("/path/to/your/private/key.pem").read() alipay_public_key_string = open("/path/to/alipay/public/key.pem").read() app_private_key_string == """ -----BEGIN RSA PRIVATE KEY----- base64 encoded content -----END RSA PRIVATE KEY----- """ alipay_public_key_string == """ -----BEGIN PUBLIC KEY----- base64 encoded content -----END PUBLIC KEY----- """ 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 config=AliPayConfig(timeout=15) # 可选, 请求超时时间 ) dc_alipay = DCAliPay( appid="appid", app_notify_url="http://example.com/app_notify_url", app_private_key_string=app_private_key_string, app_public_key_cert_string=app_public_key_cert_string, alipay_public_key_cert_string=alipay_public_key_cert_string, alipay_root_cert_string=alipay_root_cert_string ) # 如果您没有听说过ISV, 那么以下部分不用看了 # app_auth_code或app_auth_token二者需要填入一个 isv_alipay = ISVAliPay( appid="", app_notify_url=None, # 默认回调url app_private_key_srting="", # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥, alipay_public_key_string="", sign_type="RSA" # RSA or RSA2 debug=False # False by default, app_auth_code=None, app_auth_token=None ) ``` ### AliPay, DCAliPay, ISVAliPay的区别 * AliPay: 使用应用公钥进行报文验签 * DCAliPay: 使用公钥证书进行验签 * ISVAliPay: 托管多个支付宝应用使用 [部分接口](https://opensupport.alipay.com/support/knowledge/20069/201602429395?ant_source=zsearch)必须使用DCAlipay #### 接口基本命名规则 对于一个支付宝的接口,比如`alipay.trade.page.pay`,则一般可以这么调用接口:`alipay.api_alipay_trade_page_pay()`. 也就是说,我们做了这么一个转换: 内部函数名 = api_ + 支付宝接口名.replace(".", "_") 支付宝对于请求的biz_content,里面有一些参数必选,有一些可选。对于必选的参数,他们一般被明确定义在函数的参数里面。对于可选参数,他们一般被放在kwargs里面,然后被添加到biz_content里面去。比如`alipay.trade.page.pay`可以这么调用: ```python alipay.api_alipay_trade_page_pay( subject="测试订单", out_trade_no="2017020101", total_amount=100 ) ``` 也可以这么调用: ```python alipay.api_alipay_trade_page_pay( subject="测试订单", out_trade_no="2017020101", total_amount=100, goods_type=0, # 可选 timeout_express="90m" # 可选 ... ) ``` #### 电脑网站支付 [alipay.trade.page.pay](https://docs.open.alipay.com/270/105900/) ```python # 如果你是Python 2用户(考虑考虑升级到Python 3吧),请确保非ascii的字符串为utf8编码: subject = u"测试订单".encode("utf8") # 如果你是 Python 3的用户,使用默认的字符串即可 subject = "测试订单" # 电脑网站支付,需要跳转到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 ) ``` #### 手机网站支付 [alipay.trade.wap.pay](https://docs.open.alipay.com/60/104790) ```python # 手机网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string order_string = alipay.api_alipay_trade_wap_pay( out_trade_no="20161112", total_amount=0.01, subject=subject, return_url="https://example.com", notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url ) ``` #### App支付 [alipay.trade.app.pay](https://docs.open.alipay.com/204/105465) ```python # App支付,将order_string返回给app即可 order_string = alipay.api_alipay_trade_app_pay( out_trade_no="20161112", total_amount=0.01, subject=subject, notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url ) ``` #### 小程序支付[alipay.trade.create](https://opendocs.alipay.com/mini/introduce/pay) ```python # 小程序支付 alipay.api_alipay_trade_create( out_trade_no="20161112", total_amount=0.01, subject=subject, buyer_id="", notify_url="https://example.com/notify" # 可选 ) ``` #### [通知验证](https://docs.open.alipay.com/58/103596/) 这里有一个简单的基于flask的验证: ```python from flask import Flask from flask import request app = Flask(__name__) @app.route('/', methods=["GET", "POST"]) def hello_world(): data = request.form.to_dict() # sign 不能参与签名验证 signature = data.pop("sign") print(json.dumps(data)) print(signature) # verify success = alipay.verify(data, signature) if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ): print("trade succeed") ``` Django版的 ```python def hello_world(request): # for django users data = request.dict() # for rest_framework users data = request.data signature = data.pop("sign") # verification success = alipay.verify(data, signature) if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ): print("trade succeed") return 'Hello, World!' ``` 一般而言,可以这样验证回调通知 ```python # 验证alipay的异步通知,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") success = alipay.verify(data, signature) if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ): print("trade succeed") ``` #### 当面付(条码支付) [alipay.trade.pay](https://docs.open.alipay.com/api_1/alipay.trade.pay) 以下是一个当面付的基本例子 ```python alipay = AliPay(appid="", ...) result = alipay.api_alipay_trade_pay( out_trade_no="out_trade_no", scene="bar_code/wave_code", auth_code="auth_code", subject="subject", discountable_amount=10, total_amount=20, notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url ) if result["code"] == "10000": print("Order is paid") ``` #### 交易预创建(扫码支付) [alipay.trade.precreate](https://docs.open.alipay.com/194/105203/) ```python alipay = AliPay(appid="", ...) # create an order alipay.api_alipay_trade_precreate ( subject="test subject", out_trade_no="out_trade_no", total_amount=100 ) # check order status paid = False for i in range(10): # check every 3s, and 10 times in all print("now sleep 3s") time.sleep(3) result = alipay.api_alipay_trade_query(out_trade_no="out_trade_no") if result.get("trade_status", "") == "TRADE_SUCCESS": paid = True break print("not paid...") # order is not paid in 30s , cancel this order if paid is False: alipay.api_alipay_trade_cancel(out_trade_no=out_trade_no) ``` #### 退款 [alipay.trade.refund](https://docs.open.alipay.com/api_1/alipay.trade.refund) refund 需要传入的参数参见官方文档 ```python result = alipay.api_alipay_trade_refund(out_trade_no="xxx", refund_amount="xxx", ...) if result["code"] == "10000": print("success") ``` #### 统一退款查询[alipay.trade.fastpay.refund.query](https://docs.open.alipay.com/api_1/alipay.trade.fastpay.refund.query) ```python result = alipay.api_alipay_trade_fastpay_refund_query("20171120", out_trade_no="20171120") result = { 'code': '10000', 'msg': 'Success', 'out_request_no': '20171120', 'out_trade_no': '20171120', 'refund_amount': '20.00', 'total_amount': '20.00', 'trade_no': '2017112021001004070200297107' } ``` #### 统一收单交易结算接口[alipay.trade.order.settle](https://docs.open.alipay.com/api_1/alipay.trade.order.settle/) ```python result = alipay.api_alipay_trade_order_settle( out_request_no, trade_no, royalty_parameters ) ``` #### [统一收单交易关闭接口](https://docs.open.alipay.com/api_1/alipay.trade.close) ```python result = alipay.api_alipay_trade_close( trace_no="xxx", out_trade_no="xxx", operator_id="this is optional" ) result = { "code": "10000", "msg": "Success", "trade_no": "2013112111001004500000675971", "out_trade_no": "YX_001" } ``` #### 单笔转账到支付宝账户接口 [alipay.fund.trans.toaccount.transfer](https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer) ```python # transfer money to alipay account result = alipay.api_alipay_fund_trans_toaccount_transfer( datetime.now().strftime("%Y%m%d%H%M%S"), payee_type="ALIPAY_LOGONID/ALIPAY_USERID", payee_account="csqnji8117@sandbox.com", amount=3.12 ) result = {'code': '10000', 'msg': 'Success', 'order_id': '', 'out_biz_no': '', 'pay_date': '2017-06-26 14:36:25'} ``` #### 查询转账订单接口 [alipay.fund.trans.order.query](https://docs.open.alipay.com/api_28/alipay.fund.trans.order.query) ```python result = alipay.api_alipay_fund_trans_order_query( out_biz_no="20170626152216" ) print(result) ``` ## [ISV 集成](https://doc.open.alipay.com/doc2/detail?treeId=216&articleId=105193&docType=1) 在开始前,请务必阅读[官方文档](https://docs.open.alipay.com/common/105193) #### 生成app_auth_code []() ``` isv_alipay = ISVAliPay( ... app_auth_code="app_auth_code" ) response = isv_alipay.api_alipay_open_auth_token_app() response = { "code": "10000", "msg": "Success", "app_auth_token": "201708xxx", "app_refresh_token": "201708xxx", "auth_app_id": "appid", "expires_in": 31536000, "re_expires_in": 32140800, "user_id": "2088xxxxx } ``` #### 查询授权产品 []() ``` response = isv_alipay.alipay_open_auth_token_app_query() ``` ## 测试 ``` python -m unittest discover ``` 或者你可以传入debug=True, 进行手动测试 ```python alipay = AliPay(..., debug=True) ``` ## [Changelog](https://github.com/fzlee/alipay/blob/master/CHANGELOG.md)