I can't find any official python alipay sdks so far, and it really pains a lot dealing with those sign methods. Hoping this library could do some help :).
So far, the following functions are supported:
- Pay via Web
- Pay via WAP
- Pay via App
- Verification
- Face to face trade
- Precreate trade
- Query trade
- Cancel trade
- Refund
- Query refund result
- Order Settlement
- Transfer money to alipay account
- Query money transfer result
- ISV integration/Get app_auth_code by app_auth_token
- ISV integration/Query authorized apps
Taking a look at this guide if you are interested at the details on signing your order requests. Or you may just follow this manual if not.
# installation
pip install python-alipay-sdk --upgrade
# openssl
OpenSSL> genrsa -out app_private_key.pem 2048 # the private key file
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # export public key
OpenSSL> exit
The public key we download from open.alipay.com is a string, which cannot be recognied by this lib directly, making sure it's surrounded with -----BEGIN PUBLIC KEY-----
and -----END PUBLIC KEY-----
There is also an example for your reference
from alipay import AliPay, ISVAliPay
# Making sure your key file is adhered to standards.
# you may find examples at tests/certs/ali/ali_private_key.pem
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, # the default notify path
app_private_key_string=app_private_key_string,
# alipay public key, do not use your own public key!
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA" # RSA or RSA2
debug=False # False by default
)
# Forget about what I mentioned below if you don't know what ISV is
# either app_auth_code or app_auth_token should not be None
isv_alipay = ISVAliPay(
appid="",
app_notify_url=None, # the default notify path
app_private_key_string="",
# alipay public key, do not use your own public key!
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA" # RSA or RSA2
debug=False # False by default,
app_auth_code=None,
app_auth_token=None
)
Given an alipay function, say alipay.trade.page.pay
, we will defind a corresponding function alipay.api_alipay_trade_page_pay()
Generally we will do such a translation:
function_name = "api_" + alipay_function_name.replace(".", "_")
According to alipay document, some paremeters in biz_content
are optional and some are not.
We defind functions in this way so that you can put those optional parameters in kwargs
:
def api_alipay_xxx(self, out_trade, total_amount, **kwargs):
...
biz_content.update(kwargs)
# For Python 2 users(you should really think about Python 3),
# making sure non-ascii strings are utf-8 encoded
subject = u"测试订单".encode("utf8")
# For Python 3 users, just use the default string
subject = "测试订单"
# Pay via Web,open this url in your browser: 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" # this is optional
)
# Pay via WAP, open this url in your browser: 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="http://example.com",
notify_url="https://example.com/notify" # this is optional
)
# Pay via App,just pass order_string to your Android or iOS client
order_string = alipay.api_alipay_trade_app_pay(
out_trade_no="20161112",
total_amount=0.01,
subject=subject,
notify_url="https://example.com/notify" # this is optional
)
Once an order is paid, a POST request will be sent to tell you the information
Here is a simple example for flask web server:
import json
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 must be poped out
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")
return 'Hello, World!'
Here is a more general example for verification
# gathering all parameters sent from alipay server, and put them in a dictionary called data
data = {
"subject": "testing order",
"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 = 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" # this is optional
)
if result["code"] == "10000":
print("Order is paid")
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)
If you want to know what parameters are accepted, take a look into the official document
result = alipay.api_alipay_trade_refund(out_trade_no="xxx", refund_amount="xxx", ...)
if result["code"] == "10000":
print("success")
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'
}
result = alipay.api_alipay_trade_order_settle(
out_request_no,
trade_no,
royalty_parameters
)
# 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'
}
result = alipay.api_alipay_fund_trans_order_query(
out_biz_no="20170626152216"
)
print(result)
Go through the details before you do anything, or it may pains.
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
Or you may do test manually in this way, debug=True
will direct your request to sandbox environment:
alipay = AliPay(..., debug=True)
- potential security issue fix
- alipay.trade.order.settle
- Do encryption/decryption with
pycryptodomex
,which has not conflict with Pycrypto (many thanks to fakepoet)
- initialize Alipay instance with key string
- bug fix for
ISVAlipay.build_body
.
alipay.trade.fastpay.refund.query
Query refund result.
- bug fix for
api_alipay_trade_precreate
, notify url is not included in request params.
- change dependence from pycrypto to pycryptodome. for users upgraded from 1.3.0, uninstall pycrypto first
- allow notify_url be overriden in hose 4 functions:
alipay.trade.wap.pay
alipay_trade_app_pay
alipay.trade.page.pay
alipay.trade.pay
- ISV integration
alipay.fund.trans.toaccount.transfer
andalipay.fund.trans.order.query
- return url missing for
alipay.trade.page.pay
- code refactoring, all functions are renamed
alipay.trade.page.pay
is used instead ofcreate_direct_pay_by_user
- load key into memory, local key file access is needed for the 1st time