Python payment under the Alipay app example

Source: Internet
Author: User
Tags base64 json openssl openssl sha1 sha1

The latest in tossing Alipay's mobile payment (Alipay.trade.app.pay), intuitively, is to let iOS or Android apps evoke Alipay, Alipay paid successfully before returning to application.

Alipay app payment did not provide Python SDK, backstage and iOS and Android docking inevitably encountered some problems, especially the SHA1WITHRSA signature part. This article will briefly introduce the payment of Alipay app some of the processes and principles, hoping to give later Pythoner some solutions.

Pay the Treasure App payment process

The service-side stitching order string, sha1withrsa the order string, and returns it to the app, noting that at this point the server does not initiate a request to Alipay.
App calls Alipay's SDK and passes in an order string for payment.
After the payment succeeds, the local app Alipay returns the result synchronously. The service side asynchronously receives the Alipay message.
Stitching of order string

Put the key,value of the dictionary together in alphabetical order. For example, originally a dictionary:

data = {
"Out_trade_no": "201601020304",
"Biz_content": {"product": "XXX", "title": "XXX"}
}
After sorting get biz_content={"product": "XXX", "title": "XXX"}&out_trade_no=201601020304. Please note that the value here does not have a URL encode.

The following code can help you generate an order String. Biz_content is a JSON string, so the contents of biz_content are theoretically not required to be sorted.

Import JSON
def ordered_data (data):
Complex_keys = []
For key, value in Data.items ():
If Isinstance (value, dict):
Complex_keys.append (Key)

# Sort the data of a dictionary type individually
For key in Complex_keys:
Data[key] = Json.dumps (Data[key], sort_keys=true). Replace ("", "")

return sorted ([(k, V) for K, V in Data.items ()])

Unsigned_items = ordered_data (data)
unsigned_string = "&". Join ("{}={}". Format (k, v) for K, V in Unsigned_items)
Signature

Generation of RSA private key

Alipay Official document gives a way to generate the private key, OpenSSL seems more convenient:

openssl> genrsa-out APP_PRIVATE_KEY.PEM 1024 #生成私钥
openssl> pkcs8-topk8-inform pem-in app_private_key.pem-outform pem-nocrypt-out App_private_key_pkcs8.pem #Java开发者 Need to convert private key to PKCS8 format
openssl> rsa-in app_private_key.pem-pubout-out App_public_key.pem #生成公钥
Openssl> Exit #退出OpenSSL程序
To run the above command, we will get three files:

APP_PRIVATE_KEY.PEM--This is the private key in the pkcs#1 format.
APP_PRIVATE_KEY_PKCS8.PEM--This is the private key in the pkcs#8 format.
APP_PUBLIC_KEY.PEM--This is the public key of the PKCS#8 format
Our following Python and OpenSSL use private key file, which supports both pkcs#1 and pkcs#8 two formats, so you can pass in any of the private keys in any format.

OpenSSL Sha1withrsa signature of a string

Alipay's rule is to RSAwithSHA1 the order string, to SHA1 the order string first and then to sign the digest. Before you continue to read this article, you need to understand the summary and what the signature means.

Run the following command to sign the abc\n (note that Echo will pass in an extra \ n) and then output Base64 encoded results.

echo "ABC" | OpenSSL sha1-sign Privatekey.file | OpenSSL base64
The Python implementation of Sha1withrsa

Run the following command to sign abc\n using Python:

From crypto.signature import pkcs1_v1_5
From Crypto.hash import SHA
From Crypto.publickey import RSA

def sign_string (Private_key_path, unsigned_string):
# Start Calculating signatures
Key = Rsa.importkey (open (Private_key_path). Read ())
Signer = pkcs1_v1_5.new (key)
Signature = Signer.sign (Sha.new (Unsigned_string.encode ("UTF8"))
# base64 encoding, converting to Unicode representation and removal of carriage returns
Sign = base64.encodebytes (signature). Decode ("UTF8"). replace ("\ n", "")
Return sign

signed_string = sign_string (Private_key_path, "abc\n")
Crypto is a python-brought library. By comparing the results of OpenSSL and Python computing abc\n, if the two are the same, the Python signature is true. You can then sign a more complex order String.

Signature Verification

We have previously obtained the base64 result of signing the abc\n. It is now possible to use the public key to verify that the resulting structure is correct, and that the following code, if your result is true, verifies that the signature function is correct.

def validate_sign (public_key_path, message, signature):
# Start Calculating signatures
Key = Rsa.importkey (open (Public_key_path). Read ())
Signer = pkcs1_v1_5.new (key)
Digest = Sha.new ()
Digest.update (Message.encode ("UTF8"))
If Signer.verify (Digest, Base64.decodestring (Signature.encode ("UTF8")):
Return True
Return False

result = Validate_sign (Your_public_key_path, "abc\n", signed_string)
Generate an order String again

First, we have previously generated an order string:biz_content={"product": "XXX", "title": "XXX"}&out_trade_no=201601020304. The generated signature also needs to be added to the inside: biz_content={"product": "XXX", "title": "XXX"}&out_trade_no=201601020304&sign=omxv7klz

Second, the order string that the server returns to the app requires a URL encode. That is, converting key=value into Key=quote_plus (value). It's like this: biz_content=%7b%22product%22%3a%22xxx%22%2c%22title%22%3a%22xxx%22%7d&out_trade_no=201601020304 &sign=omxv7klz.

Validation of asynchronous callback payment results

We have previously used our own public key to verify the signature of our private key. Verifying payment results callback requests are similar in principle, except that you need to use Alipay's public key.

Other

Alipay's message returns are very unfriendly, like evoking Alipay payments when you sometimes see errors ALI40247.

There are many reasons for this error, and signature errors are common. At this point you need to use the OpenSSL native command to compute SHA1WITHRSA and compare your results so that you can guarantee that the signature is right (again, Echo will pass in the extra \ OpenSSL, you'd better read the string from the file that needs to be OpenSSL encrypted).

Of course there are other reasons, such as I pass in the parameter AppID and actually should pass into app_id. Of course, Pit Dad's Alipay will not have such a detailed hint.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.