# Sign a request and validate the signature

To ensure message transmission security, the Mobile Payment Provider (MPP) must properly perform message signing and signature validation：

-   When calling an Alipay+ API, the MPP must sign the API request and validate the response signature accordingly. For more information, see [Direction: MPP > Alipay+](#KGODk).
-   When receiving an API call from Alipay+, the MPP must validate the request signature and sign the API response accordingly. For more information, see [Direction: Alipay+ > MPP](#vfSk7).

# Before you begin

Create your private key and public key pair, and obtain the Alipay+ public key through the following steps:

1.  Create an application in [Alipay+ Developer Center](https://developers.alipayplus.com/open/console/developer/app/list?_route=SG). For more information, see [Create an application](../developer_center_mpp/create_application).
2.  Create your private key and public key pair with the provided tool, and submit your public key. Obtain the Alipay+ public key, which is generated automatically.
    The keys in the sandbox environment must differ from the ones in the production environment. Therefore, you must get the Alipay+ public keys for the sandbox environment and the production environment separately. For step-by-step instructions, see [Set a sandbox public key](../developer_center_mpp/develop_in_sandbox#YabQV) and [Set a production public key](../developer_center_mpp/launch_into_production#a7mDb) separately.

# Direction: Mobile Payment Provider > Alipay+

This section introduces the MPP to Alipay+ API workflow.

## Sign a request

The following steps demonstrate how to sign a request message:

### 1\. Create your private key

Create your private key with the provided tool. For more information, see [Before you begin](#oCGWG).

In this topic, `privateKey` is used to represent the private key.

### 2\. Construct the content to be signed

Take a request as an example, which includes the following properties:

-   `Request-URI`: /aps/api/v1/payments/pay
-   `Client-Id`: SANDBOX\_5YC47N2ZQHJ004124
-   `Request-Time`: 2025-02-20T08:51:49.09Z
-   `Request-Body`: The following code sample describes the body format. For example:

```json
{
 "order":{
    "orderId":"OrderID_0101010101",
    "orderDescription":"sample_order",
    "orderAmount":{
       "value":"100",
       "currency":"JPY"
    }
 },
 "paymentAmount":{
    "value":"100",
    "currency":"JPY"
 },
 "paymentFactor": {
     "isInStorePayment": "true"
 }
}
```

By complying with the [Syntax of Content\_To\_Be\_Signed](#vvkE6), the content to be signed (`Content_To_Be_Signed`) is created as follows:

```plaintext
POST /aps/api/v1/payments/pay
SANDBOX_5YC47N2ZQHJ004124.2025-02-20T08:51:49.09Z.{"order":{"orderId":"OrderID_0101010101","orderDescription":"sample_order","orderAmount":{"value":"100","currency":"JPY"}},"paymentAmount":{"value":"100","currency":"JPY"},"paymentFactor":{"isInStorePayment":"true"}}
```

#### Syntax of `Content_To_Be_Signed`

```plaintext
<HTTP-METHOD> <Request-URI>
<Client-Id>.<Request-Time>.<Request-Body>
```

-   `HTTP-METHOD`: POST
-   `Request-URI`: The `{endpoint}` part of the whole URL `https://{host}{endpoint}`. For example, if the HTTP URL is `https://www.example.com/aps/api/v1/payments/pay`, this property is `/aps/api/v1/payments/pay`.
-   `Client-Id`: A unique ID that is assigned by Alipay+ to identify a Partner. For example, `SANDBOX_5YC47N2ZQHJ004124`.
-   `Request-Time`: Specifies the time when a request is sent, as defined by [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). This field must be accurate to at least seconds. For example, `2019-05-28T12:12:12+08:00` and `2025-02-20T08:51:49.09Z`.
-   `Request-Body`: The body of the request.

### 3\. Calculate and generate the signature

Use the `base64UrlEncode` and `sha256withrsa` methods that involve the proper algorithm and private key to calculate and generate the signature.

```plaintext
generatedSignature=base64UrlEncode(sha256withrsa(<Content_To_Be_Signed>, <privateKey>))
```

Methods that are used:

-   `sha256withrsa`: The method to generate a digital signature for the content provided.
-   `base64UrlEncode`: The method to encode the generated digital signature.

Input parameters:

-   `Content_To_Be_Signed`: The content to be signed that is obtained in [Step 2](#vCgO7).
-   `privateKey`: The private key value that is obtained in [Step 1](#wAd81). For example:

```plaintext
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCCI9ml0PnMlZZaMYujB1gzmV9UJG+8aezFRiGaZ7e+yLz94i2sibIHwMDI4UCUNt+kMXHyaTkFRj1PYVunflFk85Hyh+kafsImKvPvuF3gesxJOfWvz3yROo+P+I1hUjmHN00xPwpDAncT5zCjMfAPb/TBDEAXC/GIrC+t0LpcPVARcCP4lI56UjZAd7KzVye7Xldc27O/K3BtJmlaRdn490jlJ1RPC6kS5UZH8d5UGbrjGYv4vz8aCQaTO4ZYQ4yEpE7A2kHHRLpdxL6cNPBEihpa/K3L48zJqXz3OT9AO27T/Hkz8uqBAQFDRHJMrOpOad/0yqUtRtRBAgxi+pTVAgMBAAECggEAFUNuSF2AsyCt1EbMHfMRQj0JCmJ5rztPaFwxGV1g9FcwKftOoyZMZF/mH+xN9OmSWO2LRKRUoLv9QH8TzqYg/nGdoxb5y05ywnG6MazaCdeGkWBa+ELag5Ah7NAbqY8ZvzIV9rnqH1DDzAi2NbPvGVadkv1Ba4KUEFSx5aB5EqDmTgwQ7lisYNVf3tKAbqfY1gTHwi6SI5msURUgQ4e1qbXiQcw15I93WMfm6PKPgbevBMjmqvSKOdo/M3LBXrIyqTm3nExI1itLOi00LxjPtgI/Ke68rcGhdS79ZWeEecXqeotViG+iwOW9YSuOF72MkrgD2l1GT7pMCF+xTdbDgQKBgQC7GuB2wvNz0DWA3GO7HHh8bXavQwDLqV/UW9H2JMYFlAzyVzZNErHVg0Ew9qsESi9Vgz3fH8DnstdoMCjdX+HmvSWnM0IOTtqe6JqRSiCyu03Mkn4HFPRd7myE9GfdSQCWp8mhuVKJTGxK8+Cg2JIxAsEl2JDDlFV9YYPdz4Tp7QKBgQCyD0XHi6hOjiV9WO2jN2zJYgtIsAiDn1Ch1dBahVm9mbay8KrwdR9NrIn73Bh16Hb0I1ObismfEWclYA/Fh1uXKWkFsy3t/BfVIofWYuLUFcOXad8srfyNlPCYRsng7kd2JDfQBoEg1YNxxRZgPsBxLz463cDMV/7sqRYY1N5ZiQKBgE4lT5LKobvBPldvtQe1QG1XmrZgmbh2KVwcbXkMqtgxmaat3jQalsPCajv1CkBka5ifk/vY20zqWSVe1/J91W/1mABZXEF1lcHBDK2Z9EYyDLBgjtqOWfHRXum42piFoQVLVt+A84P8s04qxaroSUbHC7yu0uec0IfpbpX50l2RAoGANFpDNQF98eLfaPRtonCYXrmiAbQoPLLp3TtlcEgG87UvP3t9dweotYjGZTP4SSqZVvzQB0qOL2PJhPayjGxY5J/7Tf65wWA+jZ8Ce2lFsf/YKzuor5VUTTh+aPdfQfAtOLI7asGO092TMS82fgPVRzIRxPMQTcSNon2wjop/+akCgYBAAmFHmEol9wgAOVh70T5A3HP7xXDdBb1bn+g+IR3UgMyji/aHgfOjJdBfrS77cDOb9PXAhMLReiJQWvet7GbkshHiiHrojlDVrUWzPOB4BKbu5LoVyYNUbTsEwebZl2vLkOoFap2CX4Tvhfghg4iMXOpcUKejEVv8T9IsrhQw5g==
```

With the preceding example `Content_To_Be_Signed` and `privateKey`, the generated signature (represented by `generatedSignature`) is as follows:

```plaintext
HRkD%2Fx8Muwg8yNSS8RUwyBkwfQ1Q2AMvdErhwfZYjkXevMwsXuK0MnA8IE3TWsJv0VRTpcIZrCKZCt2cFmshZUDrdwF91o0kLKdjQXOSycacTWqxoIPhkJXKeEQ4PfeMJ0E4Ag0h0vNMpLceG5nvkeY3I12ErVniKrUkjSBiVC4hAPCUX%2FV2KtYTVerrtIEx%2BjjdHbqvW1SdehKOe9VduXq8b0K5NVDhKCrZfBGj%2F30lYq8SBWCXaDP56dEoXhYsw937ryFln7uKOKRkfJnoKVjUwVB7DUJaVnYJhcMZMzNF4wGk%2FLxc9moSJLQYf7fpjz%2F5lsPcqLYt%2FxN5cMUvFA%3D%3D
```

### 4\. Configure the signature in the request header

Assemble a signature string by using the following syntax:

```plaintext
'Signature: algorithm=<algorithm>,keyVersion=<key-version>,signature=<generatedSignature>'
```

-   `algorithm` , `keyVersion`: See the header of the chapter [Message structure](api_overview#3pRaK).
-   `generatedSignature`: The signature that is generated in [Step 3](#jk0Hg).

The following sample describes an assembled signature string:

```plaintext
'Signature: algorithm=RSA256,keyVersion=0,signature=HRkD%2Fx8Muwg8yNSS8RUwyBkwfQ1Q2AMvdErhwfZYjkXevMwsXuK0MnA8IE3TWsJv0VRTpcIZrCKZCt2cFmshZUDrdwF91o0kLKdjQXOSycacTWqxoIPhkJXKeEQ4PfeMJ0E4Ag0h0vNMpLceG5nvkeY3I12ErVniKrUkjSBiVC4hAPCUX%2FV2KtYTVerrtIEx%2BjjdHbqvW1SdehKOe9VduXq8b0K5NVDhKCrZfBGj%2F30lYq8SBWCXaDP56dEoXhYsw937ryFln7uKOKRkfJnoKVjUwVB7DUJaVnYJhcMZMzNF4wGk%2FLxc9moSJLQYf7fpjz%2F5lsPcqLYt%2FxN5cMUvFA%3D%3D'
```

Then, add the signature string to the request header.

## Send a request

Construct a request by adding the `Client-Id`, `Request-Time`, and `Signature` fields to the request header. After a request is constructed, you can use common tools, such as cURL or Postman, to send the request. In the following example, cURL is used:

```plaintext
curl -X POST \
  https://example.com/aps/api/v1/payments/pay \
  -H 'Content-Type: application/json' \
  -H 'Client-Id: SANDBOX_5YC47N2ZQHJ004124' \
  -H 'Request-Time: 2025-02-20T08:51:49.09Z' \
  -H 'Signature: algorithm=RSA256,keyVersion=0,signature=HRkD%2Fx8Muwg8yNSS8RUwyBkwfQ1Q2AMvdErhwfZYjkXevMwsXuK0MnA8IE3TWsJv0VRTpcIZrCKZCt2cFmshZUDrdwF91o0kLKdjQXOSycacTWqxoIPhkJXKeEQ4PfeMJ0E4Ag0h0vNMpLceG5nvkeY3I12ErVniKrUkjSBiVC4hAPCUX%2FV2KtYTVerrtIEx%2BjjdHbqvW1SdehKOe9VduXq8b0K5NVDhKCrZfBGj%2F30lYq8SBWCXaDP56dEoXhYsw937ryFln7uKOKRkfJnoKVjUwVB7DUJaVnYJhcMZMzNF4wGk%2FLxc9moSJLQYf7fpjz%2F5lsPcqLYt%2FxN5cMUvFA%3D%3D' \
  -d '{
      "order":{
          "orderId":"OrderID_0101010101",
          "orderDescription":"sample_order",
          "orderAmount":{
             "value":"100",
             "currency":"JPY"
          }
       },
       "paymentAmount":{
          "value":"100",
          "currency":"JPY"
       },
       "paymentFactor": {
           "isInStorePayment": "true"
       }
}'
```

## Handle a response

After you receive a response, you need to validate the signature of the response. A response consists of a response header and a response body. The following examples show the header and body of a response:

-   The response header sample

```plaintext
Client-Id: SANDBOX_5YC47N2ZQHJ004124
Response-Time: 2025-02-21T05:43:09Z
Signature: algorithm=RSA256,keyVersion=0,signature=LG8hpLILF1sKlydGaB2cr4EwpG%2BnZiqp1omV6IHgYDeCd6wzA9c2UMNM%2BkxK%2Bltdjers6R6jMxld5%2BuM1MAAO%2F1wHQ%2FVpGeUkGXV%2Fk6Ow7wd%2FjNTLZ%2FB5Cpi9qudkWNXxW3N1eCvcys6wVIHP75A9I4aMX5zBUDjjodVP0gj02F84h%2F0ailuWVMFqEF%2B%2FIHNRT88J5idyrDLlgo%2Fg32d%2BddkFXrcLYhbWi9gSlmG3JtY5Mj9XzS%2FuNt6SkKK%2BT3WdD1q0sbbHtN4reJDNyF%2BABIWlY8Y3Y2OGQbSBcpQZwKep6uG0dAIKAcRgeQtUtpqOUumnolY4LmSr4HRRd15rw%3D%3D
```

-   The response body sample

```json
{
  "result":{
    "resultCode":"ORDER_NOT_EXIST",
    "resultMessage":"Order does not exist.",
    "resultStatus":"F"
  }
}
```

The following steps demonstrate how to validate the signature of a response by using the example above.

### 1\. Obtain the Alipay+ public key

Obtain the Alipay+ public key by uploading your public key. For more information, see [Before you begin](#oCGWG).

### 2\. Construct the content to be validated

Given the [response body sample](#GO0oL) above, construct the content to be validated (`Content_To_Be_Validated`) by complying with the [Syntax of Content\_To\_Be\_Validated](#aouyB) as follows:

```plaintext
POST /aps/api/v1/payments/inquiryPayment
SANDBOX_5YC47N2ZQHJ004124.2025-02-21T05:43:09Z.{"result":{"resultCode":"ORDER_NOT_EXIST","resultMessage":"Order does not exist.","resultStatus":"F"}}
```

#### Syntax of `Content_To_Be_Validated`

```plaintext
<HTTP-METHOD> <Response-URI>
<Client-Id>.<Response-Time>.<Response-Body>
```

-   `HTTP-METHOD`: POST
-   `Response-URI`: The URI of an HTTP link. For example, if the URL is `https://example.com/aps/api/v1/payments/inquiryPayment`, this field is `/aps/api/v1/payments/inquiryPayment`.
-   `Client-Id`: A unique ID that is assigned by Alipay+ to identify a Partner. You can get this field from the response header. For example `SANDBOX_5YC47N2ZQHJ004124`.
-   `Response-Time`: Specifies the time when a response is returned, as defined by [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). This field must be accurate to seconds. You can get this field from the response header.
-   `Response-Body`: Specifies the body of the response.

### 3\. Get the signature from the response header

The target signature string ( `target_signature` ) is extracted from the `Signature` header of the response. For details about the response header, see the chapter [Message structure](api_overview#3pRaK).

```plaintext
Signature: algorithm=RSA256,keyVersion=0,signature=<target_signature>
```

### 4\. Validate the signature

Use the `sha256withrsa_verify` method to validate the signature of the response.

The syntax of the `sha256withrsa_verify` method is as follows:

```plaintext
IS_SIGNATURE_VALID=sha256withrsa_verify(base64UrlDecode(<target_signature>), <Content_To_Be_Validated>, <serverPublicKey>)
```

Methods:

-   `base64UrlDecode`: The method to decode the signature.
-   `sha256withrsa_verify`: The method to verify the signature.

Input parameters:

-   `target_signature`: The target signature that is obtained in [Step 3](#CyJv8).
-   `Content_To_Be_Validated`: The content to be validated, which is created in [Step 2](#gOCOY).
-   `serverPublicKey`: The Alipay+ public key that is obtained in [Step 1](#cDDQC). For example:

```plaintext
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjCnZV89YE5FpawMMA25JWlwnzKI5r0/F0DH0hBrW3aOLqqqFrYEzN1FzUuv9Gnji8rMU2gkdpsiSfsg/nIIfn3B/ANHO046j9eM2TvvC1Ppi8FEJnh2liKzkQwWDiSPFfeLoR6J8OK0bFrhdr/f/O+PVuowLrZSFMf3rXhxQzvsnoBPsoEqLy8BDwBnagMynpdWuTt8ng2ulsi9CZaJf7ZKXQWJabZKq5E5Qf7ejUWGFwbAAor8Ht7fGWOy2Ayd6s8kBZ6xoJYkyHL08pQamy4tSQ20FVQi/z3DzgfnH+caSIPogzkmfbWjgIvCZ/f+EfuJxq827A+DavJR8/vMEpwIDAQAB
```

Output parameter:

-   `IS_SIGNATURE_VALID`: A Boolean value that specifies whether the signature is valid.

-   `true`: the signature is valid.
-   `false`: the signature is not valid. Possible causes are that the private key and the public key do not match, or `Content_To_Be_Validated` is not correctly constructed.

With the preceding example `target_signature`,`Content_To_Be_Validated`, and `serverPublicKey`, the result of `IS_SIGNATURE_VALID`) is `true`.

# Direction: Alipay+ > Mobile Payment Provider

This section introduces the Alipay+ to MPP API workflow.

## Handle a request

After you receive a request from Alipay+, you need to validate the signature of the request. The process is similar to the process as introduced in [Handle a response](#GO0oL). To validate the signature, complete the following steps

1.  Obtain the Alipay+ public key, which is used to validate the request signature.
2.  Construct the `Content_To_Be_Validated`, which is:

```json
<HTTP-METHOD> <Request-URI>
<Client-Id>.<Request-Time>.<Request-Body>
```

> **Note**: The `Request-URI` is the endpoint of your API path. For example, when Alipay+ sends a **pay** request to the API path `https://www.sampleMPP.com/aaa/bbb/ccc`, the `Request-URI` is `/aaa/bbb/ccc`.

3.  Get the signature from the request header.
4.  Validate the signature.

## Sign a response

You must sign your response before sending it to Alipay+. The process is similar to the process introduced in [Sign a request](#uancS). To sign your response, complete the following steps:

1.  Use your private key to sign the response.
2.  Construct the content to be signed, which is:

```plaintext
<HTTP-METHOD> <Response-URI>
<Client-Id>.<Response-Time>.<Response-Body>
```

-   `HTTP-METHOD`: POST
-   `Response-URI`: The `Response-URI` is the endpoint of your API path. For example, when you respond to Alipay+'s **pay** request, whose API path is `https://www.sampleMPP.com/aaa/bbb/ccc`, the `Response-URI` is `/aaa/bbb/ccc`.
-   `Client-Id`: A unique ID that is assigned by Alipay+ to identify a Partner. For example, `SANDBOX_5YC47N2ZQHJ004124`.
-   `Response-Time`: Specifies the time when a request is sent, as defined by [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). This field must be accurate to at least seconds. For example, `2019-05-28T12:12:14+08:00`.
-   `Response-Body`: The body of the request.

For example:

```plaintext
POST /aaa/bbb/ccc
SANDBOX_5YC47N2ZQHJ004124.2019-05-28T12:12:14+08:00.{"result":{"resultCode":"SUCCESS","resultStatus":"S","resultMessage":"success"}}
```

3.  Calculate and generate the signature.
4.  Configure the signature in the response header.

## Send a response

Construct a response by adding the `Client-Id`, `Response-Time`, and `Signature` fields to the response header and send it to Alipay+.

An example of the response that Alipay+ receives is shown as follows. In the following example, cURL is used by Alipay+ to receive the response.

```plaintext
curl -X POST \
  https://www.sampleMPP.com/aaa/bbb/ccc \
  -H 'Content-Type: application/json' \
  -H 'Client-Id: SANDBOX_5YC47N2ZQHJ004124' \
  -H 'Response-Time: 2019-05-28T12:12:14+08:00' \
  -H 'Signature: algorithm=RSA256,keyVersion=0,signature=sampleSignature***' \
  -d '{
 "result": {
    "resultCode":"SUCCESS",
    "resultStatus":"S",
    "resultMessage":"success"
 }
}'
```