Skip to main content

Signature Specifications

Signature Generation

Merchants can generate request signatures according to the steps below. We will later provide demonstration code in various common programming languages for developers' reference.

MidasPay requires merchants to sign the request. MidasPay will verify the signature upon receiving the request. If the signature verification fails, MidasPay will reject the request and return a 401 Unauthorized response.

danger

The parameters used in this documentation (including merchant parameters, certificate parameters, etc.) are for demonstrating the signature/verification process only. In actual use, merchants should rely on the parameters allocated to them.

Preparation

Merchants can log in to the MidasPay management console to upload their merchant certificates and download the platform's public key certificate and certificate serial number.

Constructing the Signature String

We expect the merchant's technical team to construct the signature string according to the rules specified in this document. MidasPay will use the same method to construct the signature string. If the merchant constructs the signature string incorrectly, it will result in failed signature verification. Below is a detailed explanation of the signature string format.

The signature string consists of five lines, each containing one parameter. Each line ends with a newline character (\n, ASCII code value 0x0A), including the last line. If the parameter itself ends with \n, an additional \n must be added.

HTTP Request Method\n
URL\n
Request Timestamp\n
Request Random String\n
Request Body\n

By calling the "GET MidasPay platform certificate" interface in the command line, we introduce the developer step by step how to request and sign according to the interface document to get the merchant platform certificate, the request method is GET, no query parameter.

Step 1: Obtain the HTTP Request Method
GET
Step 2: Obtain the Absolute URL of the Request

Remove the domain part of the URL to get the URL used in the signature. If the request has query parameters, append ? and the corresponding query string at the end of the URL.

/v1/payment/orders
Step 3: Obtain the Request Timestamp

Get the current system time at the moment the request is made. The timestamp is the total number of seconds since the Unix epoch (January 1, 1970, 00:00:00 GMT). MidasPay may reject requests made more than 24 hours before the current time, so ensure your system's time is accurate.

$ date +%s
1554208460
Step 4: Generate a Request Random String

This is a random string that can be generated using algorithms like the one shown below. Here's how to generate one from the command line:

$ hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random
593BEC0C930BF1AFEB40B4A08C8FB242
Step 5: Obtain the Request Body

The request body will differ based on the HTTP method:

  • If the request method is GET, the request body is empty.
  • If the request method is POST or PUT, use the actual JSON message being sent.
Step 6: Construct the Signature String

Based on the rules mentioned above, the signature string is constructed as follows:

GET\n
/v1/payment/orders\n
1554208460\n
593BEC0C930BF1AFEB40B4A08C8FB242\n
\n
Step 7: Calculate the Signature Value

Most programming languages provide a function for signing data. It is strongly recommended that merchants use such functions to sign the data string using the merchant's private key with the SHA256 with RSA algorithm, and then base64 encode the signature result to obtain the final signature value.

Here's an example using the command line to generate a signature:

$ echo -n -e \
"GET\n/v1/payment/orders\n1554208460\n593BEC0C930BF1AFEB40B4A08C8FB242\n\n" \
| openssl dgst -sha256 -sign apiclient_key.pem \
| openssl base64 -A
uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==
Step 8: Set the HTTP Headers

MidasPay requires that the merchant's request include the signature in the Authorization HTTP header. The Authorization header consists of two parts: the authentication type and the signature information.

Authorization: <Authentication Type> <Signature Information>

This is composed of:

  1. Authentication Type: Currently TXGW-SHA256-RSA2048.
  2. Signature Information:
    • auth_id: The merchant's ID (length ≤ 64).
    • auth_id_type: The type of authentication ID, fixed as MERCHANT_ID.
    • serial_no: The API certificate serial number used to declare the certificate being used (length ≤ 64).
    • nonce_str: The random string generated earlier.
    • timestamp: The timestamp from step 3.
    • signature: The signature value obtained in step 7.

Note: The order of the signature information is not strict.

Example of the Authorization header (note that due to formatting, it may appear on multiple lines, but in practice, it should be a single line):

Authorization: TXGW-SHA256-RSA2048 auth_id="1900009191",auth_id_type=MERCHANT_ID,nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242",signature="uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==",timestamp="1554208460",serial_no="1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C"
Step 9: Make the HTTP Request

Now, you can construct a complete HTTP request that includes the signature.

$ curl https://${host}/v1/payment/orders -H 'Authorization: TXGW-SHA256-RSA2048 auth_id="1900009191",auth_id_type=MERCHANT_ID,nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242",signature="uOVRnA4qG/MNnYzdQxJanN+zU+lTgIcnU9BxGw5dKjK+VdEUz2FeIoC+D5sB/LN+nGzX3hfZg6r5wT1pl2ZobmIc6p0ldN7J6yDgUzbX8Uk3sD4a4eZVPTBvqNDoUqcYMlZ9uuDdCvNv4TM3c1WzsXUrExwVkI1XO5jCNbgDJ25nkT/c1gIFvqoogl7MdSFGc4W4xZsqCItnqbypR3RuGIlR9h9vlRsy7zJR9PBI83X8alLDIfR1ukt1P7tMnmogZ0cuDY8cZsd8ZlCgLadmvej58SLsIkVxFJ8XyUgx9FmutKSYTmYtWBZ0+tNvfGmbXU7cob8H/4nLBiCwIUFluw==",timestamp="1554208460",serial_no="1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C"'
info

If your request returns a 401 Unauthorized signature error, refer to the troubleshooting section on signature-related issues.

Signature Verification

MidasPay includes the signature of the event notification message in the HTTP header. Merchants must verify the signature of the event notification to ensure that it is sent by MidasPay.

Obtain the Platform Certificate

MidasPay uses its platform private key (not the merchant's private key) to sign notifications. Therefore, the merchant needs to use the MidasPay platform's public key to verify the signature. Log in to the MidasPay management console (or obtain it offline) to get the MidasPay platform's public key.

warning

Reminder: The signature verification of responses and callbacks uses the MidasPay platform certificate, not the merchant API certificate. Using the merchant API certificate will result in a verification failure.

Check the Platform Certificate Serial Number

The platform certificate serial number is included in the HTTP header Txgw-Serial. Before verifying the signature, merchants should check whether the serial number matches the MidasPay platform certificate serial number they currently hold. If they do not match, retrieve the correct certificate. Otherwise, the signature and certificate will not match, and the signature verification will fail.

warning

Important: For security reasons, the platform certificate may be rotated. During this period, merchants need to store both the old and new certificates. Therefore, merchants should store the certificate using a key-value format where the key is the serial number and the value is the certificate.

Construct the Signature Verification String

First, retrieve the following information from the response:

  • The response timestamp from the Txgw-Timestamp HTTP header.
  • The response random string from the Txgw-Nonce HTTP header.
  • The response body.

Then, construct the signature verification string according to the following rules. The signature string consists of three lines, each ending with a newline character \n (ASCII code 0x0A), including the last line. If the response body is empty (such as with an HTTP status code of 204 No Content), the last line should be just a newline character.

Response Timestamp\n
Response Random String\n
Response Body\n

For example, if the HTTP response is (ciphertext content abbreviated for clarity):

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 02 Apr 2019 12:59:40 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 2204
Connection: keep-alive
Keep-Alive: timeout=8
Content-Language: zh-CN
Request-ID: e2762b10-b6b9-5108-a42c-16fe2422fc8a
Txgw-Nonce: c5ac7061fccab6bf3e254dcf98995b8c
Txgw-Signature: CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==
Txgw-Timestamp: 1554209980
Txgw-Serial: 5157F09EFDC096DE15EBE81A47057A7232F1B8E1
Cache-Control: no-cache, must-revalidate

{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"4de73afd28b6","associated_data":"certificate","ciphertext":"..."}}]}

The signature verification string would be:

1554209980
c5ac7061fccab6bf3e254dcf98995b8c
{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"4de73afd28b6","associated_data":"certificate","ciphertext":"..."}}]}
Retrieve the Response Signature

The response signature is passed through the Txgw-Signature HTTP header. (Again, note that the example may appear on multiple lines due to formatting, but in practice, it should be a single line.)

Txgw-Signature: CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==

Decode the Txgw-Signature field value using Base64 to obtain the response signature.

warning

Some proxy servers or CDN service providers may filter out MidasPay's custom HTTP headers when forwarding requests, leading to missing signature information in the application layer. If you encounter this situation, we recommend adjusting the proxy server configuration or directly connecting to MidasPay's server to receive notifications.

Verify the Signature Steps

Many programming languages provide signature verification functions to check the signature string and signature. It is strongly recommended that merchants use these functions to verify the signature string and signature using the MidasPay platform public key with the SHA256 with RSA algorithm.

Here's an example of how to verify the signature using the command line. Assume we have already obtained the platform certificate and saved it as 1900009191_mpp_cert.pem.

First, export the MidasPay platform public key from the platform certificate:

$ openssl x509 -in 1900009191_mpp_cert.pem -pubkey -noout > 1900009191_mpp_pub.pem
$ cat 1900009191_mpp_pub.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4zej1cqugGQtVSY2Ah8R
MCKcr2UpZ8Npo+5Ja9xpFPYkWHaF1Gjrn3d5kcwAFuHHcfdc3yxDYx6+9grvJnCA
2zQzWjzVRa3BJ5LTMj6yqvhEmtvjO9D1xbFTA2m3kyjxlaIar/RYHZSslT4VmjIa
tW9KJCDKkwpM6x/RIWL8wwfFwgz2q3Zcrff1y72nB8p8P12ndH7GSLoY6d2Tv0OB
2+We2Kyy2+QzfGXOmLp7UK/pFQjJjzhSf9jxaWJXYKIBxpGlddbRZj9PqvFPTiep
8rvfKGNZF9Q6QaMYTpTp/uKQ3YvpDlyeQlYe4rRFauH3mOE6j56QlYQWivknDX9V
rwIDAQAB
-----END PUBLIC KEY-----
info

Java supports using the certificate to initialize the signature object directly, without needing to export the public key first. See initVerify(Certificate) for details.

Next, decode the signature from Base64 and save it to a file named signature.txt:

$ openssl base64 -d -A <<< 'CtcbzwtQjN8rnOXItEBJ5aQFSnIXESeV28Pr2YEmf9wsDQ8Nx25ytW6FXBCAFdrr0mgqngX3AD9gNzjnNHzSGTPBSsaEkIfhPF4b8YRRTpny88tNLyprXA0GU5ID3DkZHpjFkX1hAp/D0fva2GKjGRLtvYbtUk/OLYqFuzbjt3yOBzJSKQqJsvbXILffgAmX4pKql+Ln+6UPvSCeKwznvtPaEx+9nMBmKu7Wpbqm/+2ksc0XwjD+xlvlECkCxfD/OJ4gN3IurE0fpjxIkvHDiinQmk51BI7zQD8k1znU7r/spPqB+vZjc5ep6DC5wZUpFu5vJ8MoNKjCu8wnzyCFdA==' > signature.txt

Finally, verify the signature:

$ openssl dgst -sha256 -verify 1900009191_mpp_pub.pem -signature signature.txt << EOF
1554209980
c5ac7061fccab6bf3e254dcf98995b8c
{"data":[{"serial_no":"5157F09EFDC096DE15EBE81A47057A7232F1B8E1","effective_time":"2018-03-26T11:39:50+08:00","expire_time":"2023-03-25T11:39:50+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","nonce":"4de73afd28b6","associated_data":"certificate","ciphertext":"..."}}]}
EOF
Verified OK

If the signature verification is successful, Verified OK will be printed, indicating that the response is indeed from MidasPay and has not been tampered with.

note

you can verify you signature here SigTool