アリペイpython SDK

12121 ワード

GUIDE
Installation
# installation
pip install python-alipay-sdk --upgrade
# For python2, use: pip install python-alipay-sdk==1.1

Cert generation
# 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
Initialization
from alipay import AliPay, DCAlipay, 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
)


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
)


# 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
)

Difference between AliPay, DCAliPay, and ISVAliPay
  • AliPay: sign request with your private key, several alipay apis are not available
  • DCAliPay: sign request with cert
  • ISVAliPay: used when you need to host multiple alipay services

  • DCAlipay is a must for certain Alipay APIs
    Naming convention
    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 into  kwargs :
    def api_alipay_xxx(self, out_trade, total_amount, **kwargs):
        ...
        biz_content.update(kwargs)
    

    alipay.trade.page.pay
    # 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
    )

    alipay.trade.wap.pay
    # 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
    )

    alipay.trade.app.pay
    # 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
    )

    Notification Validation
    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!'

    And also an example for Django
    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!'

    Here is a more general example for verification
    # gathering all parameters sent from alipay server, and put them into 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.trade.pay
    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.trade.precreate/alipay.trade.cancel/alipay.trade.query
    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
    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")

    alipay.trade.fastpay.refund.query
    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
    result = alipay.api_alipay_trade_order_settle(
        out_request_no,
        trade_no,
        royalty_parameters
    )

    alipay.trade.close
    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
    # 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="[email protected]",
        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
    result = alipay.api_alipay_fund_trans_order_query(
        out_biz_no="20170626152216"
    )
    print(result)

    ISV Integration
    Go through the details before you do anything, or it may pains.
    alipay.open.auth.token.app
    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
    }
    

    alipay.open.auth.token.app.query
    response = isv_alipay.alipay_open_auth_token_app_query()
    

    Test
    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)