> ## Documentation Index
> Fetch the complete documentation index at: https://doc.haipay.net/llms.txt
> Use this file to discover all available pages before exploring further.

# HaiPay Configuration and Signature Guide

> Explore the new key configuration panel of the HaiPay merchant platform, master public/private key management, business ID mapping, key replacement, and other core operations to ensure correct, secure, and efficient integration.

## 1. Overview

HaiPay has launched a brand-new **Key Configuration Panel**, designed to provide merchants with a more convenient and more secure key management experience. The new panel is compatible with the original configuration logic and adds the following core features:

* **One-click key pair generation** — Merchants can generate RSA 2048 public/private key pairs directly on the platform side, without installing additional tools
* **Flexible business ID mapping** — Supports configuring different public keys for different business IDs (appIds), as well as one-click configuration for "All" business IDs
* **Batch key replacement** — Intuitively manage the mapping between business IDs and keys through a transfer box
* **Multi-dimensional key viewing** — Merchant public keys, HaiPay public keys, and encrypted fields are managed in separate tabs

<Info>
  Signatures use the **SHA256WithRSA** algorithm with a key length of **2048 bits**. The merchant private key is used to sign request messages, and the merchant public key is uploaded to HaiPay for signature verification; the HaiPay public key is used to verify the signatures of messages returned by the platform.
</Info>

<Tip>
  If this is your first time integrating with HaiPay, we recommend reading the [Integration Steps Guide](/docs/en/guide/integration_guide) first to learn the complete integration process.
</Tip>

### Role of Public and Private Keys

In HaiPay's communication architecture, public and private keys provide the core security guarantee for request signing and response verification:

```mermaid theme={null}
flowchart LR
    %% Node styles
    classDef entity fill:#f9fbff,stroke:#cbd5e1,stroke-width:1px;
    classDef key fill:#e6f7ff,stroke:#94a3b8,stroke-width:1px;
    classDef arrow stroke:#60a5fa,stroke-width:1.5px;

    %% Groups
    subgraph Merchant["Merchant"]
        A["Merchant Private Key<br/>Used to sign requests"]:::key
        B["Platform Public Key (HaiPay)<br/>Used to verify response signatures"]:::key
    end
    subgraph Platform["HaiPay Platform"]
        C["Merchant Public Key<br/>Used to verify merchant request signatures"]:::key
        D["Platform Private Key<br/>Used to sign response messages"]:::key
    end

    %% Flow
    A -->|1. Sign the body with the private key and send the request to the platform| C:::arrow
    D -->|2. The platform signs the response with its private key and sends it back| B:::arrow
    C -->|3. The platform verifies the signature with the merchant public key| A:::arrow
    B -->|4. The merchant verifies the signature with the platform public key| D:::arrow

    %% Arrow colors (customizable)
    linkStyle 0 stroke:#3b82f6,color:#2563eb,stroke-width:1.5px;
    linkStyle 1 stroke:#22c55e,color:#15803d,stroke-width:1.5px;
    linkStyle 2 stroke:#f97316,color:#c2410c,stroke-width:1.5px;
    linkStyle 3 stroke:#a855f7,color:#7e22ce,stroke-width:1.5px;
```

<div class="frame-caption">Figure 1: Public/private key signing and verification flow between the merchant and the platform</div>

## 2. Prerequisites

Before using the key configuration panel, make sure you have completed the following preparations:

<Steps>
  <Step title="Obtain a merchant platform account">
    After the partnership is confirmed, HaiPay will create a Merchant Management Platform account based on the "Administrator Account Information" filled in the Merchant Access Application Form. Please watch for the activation email from HaiPay and activate the account as instructed. The first login requires a password change.
  </Step>

  <Step title="Log in to the Merchant Management Platform">
    Log in to the HaiPay Merchant Management Self-Service Platform with the activated administrator account.
  </Step>

  <Step title="Enter Development Configuration">
    In the merchant main menu, find the new "**Development Configuration**" menu and click it to open the key configuration panel.
  </Step>
</Steps>

<Warning>
  The merchant appId and keys are **used as a pair**, and are distinguished by currency and between the test and production environments. Make sure to configure keys in the correct environment.
</Warning>

## 3. Panel Overview

After entering "Development Configuration" - "Key Configuration", you will see the following panel. At the top of the panel there are three tabs, each managing a different type of key:

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/merchant-main.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=4e4f3b704fc55efe0eafc97be244666c" alt="Key configuration panel main page" width="1523" height="574" data-path="images/rsa/en/merchant-main.png" />

  <div class="frame-caption">Figure 2: Key configuration panel main page — Your Public Keys tab</div>
</div>

| Tab                    | Description                                                                                        | Permissions                       |
| :--------------------- | :------------------------------------------------------------------------------------------------- | :-------------------------------- |
| **Your Public Keys**   | Manage the merchant's own public keys, used by HaiPay to verify merchant request signatures        | Add, replace, and change mappings |
| **HaiPay Public Keys** | View the HaiPay platform's public keys, used by the merchant to verify response message signatures | View only, cannot be modified     |
| **Encrypted Fields**   | View encrypted field configuration                                                                 | View only, cannot be modified     |

<Info>
  For new merchants, the platform public key and encrypted fields are configured to the "All" business ID by default. For existing merchants with multiple different public keys, they will be displayed as multiple rows.
</Info>

### Key Display and Copy

The key content in the panel is long, so it is displayed with ellipsis in the middle for readability. Click a key field to **copy the full content** to the clipboard.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-haipay-key.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=b36cb751507cd1bc9aca73521327e275" alt="HaiPay Public Keys tab" width="1520" height="487" data-path="images/rsa/en/wireframe-haipay-key.png" />

  <div class="frame-caption">Figure 3: HaiPay Public Keys tab — switch to view and search platform public keys</div>
</div>

## 4. Business ID Filter

At the top of the panel, the **Business ID** filter supports single-select dropdown search. You can search all appIds associated with the merchant to filter the view.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-main-page.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=3edec5a9639c66914b5cfcf12fc01b5d" alt="Business ID filter" width="1259" height="487" data-path="images/rsa/en/wireframe-main-page.png" />

  <div class="frame-caption">Figure 4: Business ID filter — supports searching for a specific appId in the dropdown</div>
</div>

<Info>
  **About the "All" business ID**

  * If all of a user's appIds use the same key, the appId column displays "**All**"
  * No matter which appId the user searches for, the row with the "All" option is always displayed
  * When the appId is "All", businesses added later are **automatically configured** with this public key
</Info>

## 5. Add/Replace Keys

Click the "**Add/Replace Key**" button in the upper-right corner of the panel to open the key configuration dialog. In this dialog, you can select the key generation method and the business ID mapping scope.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/replace-key-dialog.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=5c0b51e43d877b53d86a9708c42e9c20" alt="Add/Replace Key dialog" width="1159" height="545" data-path="images/rsa/en/replace-key-dialog.png" />

  <div class="frame-caption">Figure 5: Add/Replace Key dialog — select the generation method and mapping scope</div>
</div>

The dialog contains the following configuration items:

<Steps>
  <Step title="Select the key replacement method">
    Two methods are available (see the next chapter for details):

    * <span class="badge-recommended">Recommended</span> **Generate all public/private keys with HaiPay** — the platform generates an RSA 2048 key pair, the private key is copied to the clipboard, and only the public key is stored on the platform
    * **Use your own public/private keys** — manually enter a pre-generated public key
  </Step>

  <Step title="Select the business ID mapping scope">
    Two options are available:

    * **All** — the key applies to all business IDs
    * **Specific Business IDs** — opens a transfer box to configure the public key for specific business IDs
  </Step>

  <Step title="Generate or enter the key">
    Depending on the selected method, click the "Generate" button to generate a key pair, or enter your public key in the text box.
  </Step>

  <Step title="Confirm the replacement">
    Click the button at the bottom to submit, and the system will show a secondary confirmation dialog. Once confirmed, the new key takes effect immediately and the old key becomes invalid.
  </Step>
</Steps>

## 6. Key Generation Methods

### Method 1: One-Click Generation by HaiPay <span class="badge-recommended">Recommended</span>

This is the simplest method. After you click "Generate", the HaiPay platform will directly generate an RSA 2048 public/private key pair for you.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-replace-dialog.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=bf334b0c8f8865c35333fcb9956f0024" alt="HaiPay one-click key generation" width="1160" height="545" data-path="images/rsa/en/wireframe-replace-dialog.png" />

  <div class="frame-caption">Figure 6: Key configuration interface after selecting "Generate with HaiPay"</div>
</div>

<Steps>
  <Step title="Select the generation method">
    In the dialog, select "Generate all public/private keys with HaiPay" (selected by default and marked as "Recommended").
  </Step>

  <Step title="Click the &#x22;Generate&#x22; button">
    The system generates an RSA 2048 public/private key pair on the platform side. The public key is displayed in the "Your Public Key" field, and the private key in the "Your Private Key" field.
  </Step>

  <Step title="Click &#x22;Add/Replace and Copy Private Key&#x22;">
    After submitting the replacement, **the private key is automatically copied to your clipboard**. Save it to a secure location immediately.
  </Step>

  <Step title="Secondary confirmation">
    The system shows a secondary confirmation dialog; once confirmed, the new key takes effect immediately.
  </Step>
</Steps>

<Danger title="High-risk operation reminders">
  * **The private key is not stored on the platform** — it is only copied to the clipboard this once. Make sure to save it immediately; it cannot be retrieved again after closing the page.
  * After replacing a key, **the original key becomes invalid immediately**, and requests signed with the old key will fail signature verification.
  * Perform this operation during off-peak business hours, and make sure the new key has been configured in your system before replacing.
</Danger>

### Method 2: Use Your Own Public/Private Keys

If you already have a key pair or prefer to manage the key generation process yourself, you can choose this method. A text box will appear, asking you to enter the **public key**.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-user-key.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=a83fbaa6518bf45e1a240eaf3f7fd110" alt="Use your own public/private keys" width="1160" height="604" data-path="images/rsa/en/wireframe-user-key.png" />

  <div class="frame-caption">Figure 7: Select "Use your own public/private keys" — the public key must be entered manually</div>
</div>

You can generate a key pair in the following ways:

<Columns cols={3}>
  <Card title="OpenSSL" icon="wrench" iconColor="#1565C0" iconBackground="#E3F2FD">
    Use the openssl command-line tool to generate an RSA 2048-bit key pair. OpenSSL must be installed; the key length is 2048 bits. Refer to online examples.
  </Card>

  <Card title="Online generation tool" icon="globe" iconColor="#2E7D32" iconBackground="#E8F5E9" href="/docs/en/rsa/rsa-generate">
    Use the online RSA key generation tool provided by HaiPay (implemented purely in JavaScript, with no server interaction, so merchant key information is never leaked).
  </Card>

  <Card title="Code generation" icon="laptop" iconColor="#7B1FA2" iconBackground="#F3E5F5">
    Use Java, PHP, or other SDK code to generate an RSA 2048-bit key pair and convert it to PEM format.
  </Card>
</Columns>

<Expandable title="View code generation examples (Java / PHP)">
  <CodeGroup>
    ```java Java theme={null}
    /**
     * Generates a 2048-bit RSA key pair and converts the public and private keys to PEM format.
     */
    public static Map<String, String> generateRSAKeyPair() {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            String publicKeyPem = convertPublicKeyToPEM(keyPair.getPublic());
            String privateKeyPem = convertPrivateKeyToPEM(keyPair.getPrivate());

            Map<String, String> keyPairMap = new HashMap<>();
            keyPairMap.put("publicKey", publicKeyPem);
            keyPairMap.put("privateKey", privateKeyPem);
            return keyPairMap;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Failed to generate RSA key pair", e);
        }
    }

    // Remove the -----BEGIN/END PUBLIC KEY----- markers, line breaks, and spaces before uploading the public key
    ```

    ```php PHP theme={null}
    /**
     * Initialize an RSA key pair
     * @param int $keysize 2048 is recommended
     */
    public function initRSAKey($keysize) {
        $config = array(
            "digest_alg" => "sha256",
            "private_key_bits" => $keysize,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        );
        $rsaKey = openssl_pkey_new($config);
        openssl_pkey_export($rsaKey, $privateKey);
        $publicKey = openssl_pkey_get_details($rsaKey);
        $publicKey = $publicKey["key"];

        return array(
            'public_key' => $publicKey,
            'private_key' => $privateKey
        );
    }
    ```
  </CodeGroup>
</Expandable>

<Warning>
  When uploading the public key to the HaiPay platform, **remove** the `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` markers at the beginning and end, along with line breaks and spaces. Keep only the Base64-encoded content.
</Warning>

<Info>
  **Differences from Method 1**

  When you choose the self-created method, the replacement still requires a secondary confirmation dialog, but the private key is **not** copied to the clipboard (because the platform does not generate a private key in this case). The private key is kept by you.
</Info>

## 7. Business ID Mapping

In the Add/Replace Key dialog, "Mapped Business IDs" provides two options: **"All"** and **"Specific Business IDs"**. Your choice determines how the key is associated with business IDs.

### 7.1 Keep the Default Mapping (Select "All")

When "All" is selected, the new public key applies to all business IDs under the merchant. Businesses added later are automatically configured with this public key as well.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-replace-no-change.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=9c343177f8a7a904db73c65f3f3bdca2" alt="Keep the default mapping — select All" width="1154" height="603" data-path="images/rsa/en/wireframe-replace-no-change.png" />

  <div class="frame-caption">Figure 8: Mapped business IDs set to "All" — the public key applies to all business IDs</div>
</div>

### 7.2 Change Key Mapping (Select "Specific Business IDs")

When "Specific Business IDs" is selected, a **transfer box** opens, where you can select which business IDs to map the public key to.

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-transfer.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=f321503da8d309f6f773b5ea1ca8f8cb" alt="Transfer box — business ID mapping" width="1147" height="898" data-path="images/rsa/en/wireframe-transfer.png" />

  <div class="frame-caption">Figure 9: Transfer box interface — the left side shows unmapped/all business IDs, and the right side shows selected business IDs</div>
</div>

The structure of the transfer box is as follows:

| Area                     | Description                                                                                                                                                                                                                                          |
| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Left Panel**           | Displays all **unmapped** business IDs by default. Click the "Show/Hide Mapped" button below to toggle the display of business IDs mapped to other keys. The header title switches between "Mapped Business IDs" and "All Business IDs" accordingly. |
| **Right Panel**          | Displays all business IDs configured for the current key. If the public key was previously mapped to "All", all business IDs are shown on the right when toggled.                                                                                    |
| **Transfer Box Columns** | Three columns: **Business ID**, **Currency**, and **Business Name**                                                                                                                                                                                  |
| **Reset Button**         | Click "Reset to Original Configuration" to restore the mapping state before modification                                                                                                                                                             |

<Warning>
  When a business ID is moved from the right panel back to the left panel, it is **not** treated as a mapped business ID. If other keys have mapped that business ID, it is hidden — but the mapping for the current key is not hidden.
</Warning>

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-transfer-detail.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=c6a62b7ea7575b35cede296e9c03579a" alt="Transfer box detailed view" width="989" height="430" data-path="images/rsa/en/wireframe-transfer-detail.png" />

  <div class="frame-caption">Figure 10: Transfer box detailed view — with search, pagination, and transfer buttons</div>
</div>

## 8. Key Overwrite Reminders

When you submit a configuration in the Add/Replace Key dialog, if the new mapping scope would overwrite the association of existing public keys, the system will **automatically pop up a key overwrite reminder**, informing you which business IDs will be affected. This is designed to prevent signature verification failures caused by accidental operations.

<Info>
  **When is the overwrite reminder triggered?**

  The overwrite reminder is triggered when the business IDs mapped to your new key **are already associated with other public keys**. The system asks you to confirm whether to replace the original public key associations of these business IDs with the new one.
</Info>

There are two types of warnings depending on the scope of impact:

```mermaid theme={null}
flowchart TD
    A([Submit key configuration]) --> B{Overwrite existing public key mappings?}
    B -->|No| C[Save directly]
    B -->|Yes| D{Scope of impact?}
    D -->|Partial| E[List the specific affected business IDs]
    D -->|All| F[Warn that all business IDs will be affected]
    E --> G[Secondary confirmation dialog]
    F --> G
    G --> H([New key takes effect, old key becomes invalid])
```

<div class="frame-caption">Figure 11: Complete key overwrite reminder flow — from submission to secondary confirmation to taking effect</div>

### 8.1 Partial Mapping Overwrite

When your changes affect only **some** of the mapped business IDs, the system pops up a "Key Overwrite Reminder" dialog that clearly lists the **specific affected business IDs**.

The dialog contains the following:

* **Title**: Key Overwrite Reminder
* **Warning message**: *"This change will overwrite the keys associated with the following business IDs, and the old keys will become invalid immediately. Continue?"*
* **Affected business IDs**: The system lists all affected appIds line by line (e.g., 1122, 3344, 5566)
* **Action buttons**: "Cancel" (returns to the dialog) / "Confirm Replacement" (proceeds to secondary confirmation)

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/overwrite-warning.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=f02f08332d8072a32d1b15858c3c78bd" alt="Key overwrite reminder — partial business IDs" width="559" height="369" data-path="images/rsa/en/overwrite-warning.png" />

  <div class="frame-caption">Figure 12: Key overwrite reminder (partial mapping overwrite) — lists the specific affected business IDs</div>
</div>

<Warning>
  The old public keys associated with the business IDs in the list will **become invalid immediately** after you confirm the replacement. Make sure the new private key has been configured in your system for these business IDs; otherwise, the related requests will fail signature verification.
</Warning>

### 8.2 Full Mapping Overwrite

When you change a public key that originally maps only **some** business IDs to "**All**" business IDs, this operation overwrites the key associations of all business IDs. The pop-up warns that **all business IDs** will be affected.

The dialog contains the following:

* **Title**: Key Overwrite Reminder
* **Warning message**: *"This change will overwrite the keys associated with all business IDs, and the old keys will become invalid immediately. Continue?"*
* **Action buttons**: "Cancel" (returns to the dialog) / "Confirm Replacement" (proceeds to secondary confirmation)

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/overwrite-warning-all.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=79ba5ebcabd05d4f146fcb9acc8eba81" alt="Key overwrite reminder — all business IDs" width="557" height="315" data-path="images/rsa/en/overwrite-warning-all.png" />

  <div class="frame-caption">Figure 13: Key overwrite reminder (full mapping overwrite) — warns that all business IDs will be affected</div>
</div>

<Danger title="High-risk scenario">
  "Full mapping overwrite" means **all business IDs under the merchant will have their keys replaced at once**. This is the operation with the widest impact. Please confirm:

  * The new private key has been saved securely and configured in all your business systems
  * The operation is performed during off-peak business hours
  * The relevant development/operations teams have been notified and are ready
</Danger>

### 8.3 Secondary Confirmation

Whether you click "Confirm Replacement" in the partial or full mapping overwrite reminder dialog, the system will show a **secondary confirmation dialog** as the last line of defense.

The secondary confirmation dialog contains the following:

* **Title**: Confirm Key Replacement?
* **Warning message**: *"Replacing a key is a high-risk operation. Once the original key is invalidated, it can no longer be used. Proceed with caution."*
* **Action buttons**: "Cancel" (returns to the overwrite reminder dialog) / "Confirm Replacement" (executes the replacement; the key takes effect immediately)

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/confirm-replace.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=8604ed100948b49cae03f5c53a2ce59c" alt="Confirm key replacement — secondary confirmation" width="558" height="318" data-path="images/rsa/en/confirm-replace.png" />

  <div class="frame-caption">Figure 14: Secondary confirmation dialog — reminds that replacing a key is a high-risk operation</div>
</div>

<Tip>
  Design purpose of the two-layer confirmation mechanism: the **first layer** (key overwrite reminder) informs you of the scope of impact, and the **second layer** (secondary confirmation) lets you make the final decision. Please read the warning message carefully before confirming.
</Tip>

### 8.4 Execution Logic After Confirmation

After you click "Confirm Replacement" in the secondary confirmation dialog, the system executes the key replacement immediately. The logic is as follows:

| Scenario                      | Result                                                                                                                                                                                                              |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Partial Mapping Overwrite** | The affected business IDs are removed from the old public key's mapping, and the new public key is automatically associated with them. The old public key retains its mapping to the other unaffected business IDs. |
| **Full Mapping Overwrite**    | All business ID mappings of the old public key are taken over by the new public key. The old public key row disappears from the list, and the new public key is displayed as mapped to "All" business IDs.          |

<Info>
  **About the "Back/Cancel" buttons**

  In both the first-layer overwrite reminder dialog and the second-layer secondary confirmation dialog, clicking "Cancel" or "Back" **returns to the key configuration dialog** instead of closing it directly. You can continue editing the configuration or close the dialog manually.
</Info>

## 9. Replace Key or Change Mapping Individually

In addition to using the "Add/Replace Key" button at the top for batch operations, you can also perform individual operations on a **specific public key**. In the "Actions" column of the data table, each row provides two action links:

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-single-ops.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=52cbe8a0e52be980e60fe98d6ad76a35" alt="Replace key and change business ID mapping individually" width="1758" height="537" data-path="images/rsa/en/wireframe-single-ops.png" />

  <div class="frame-caption">Figure 15: Actions column — "Replace Key" and "Change Business ID Mapping"</div>
</div>

| Operation                      | Description                                                   | Fixed Item                                                   |
| :----------------------------- | :------------------------------------------------------------ | :----------------------------------------------------------- |
| **Replace Key**                | Replaces the key content for the public key in this row       | The business ID mapping stays **unchanged**                  |
| **Change Business ID Mapping** | Modifies the mapping between this public key and business IDs | The public key stays **unchanged** and is optional to modify |

Individual operations work the same way as the top button, with the following differences:

* When replacing a key, the business ID mapping is fixed; only the key content is changed
* When changing the mapping, the public key is fixed and optional to modify; only the mapping scope is adjusted

<div class="frame">
  <img src="https://mintcdn.com/haipay-3385f6e8/s1806vdqkUj3xbR6/images/rsa/en/wireframe-change-mapping.png?fit=max&auto=format&n=s1806vdqkUj3xbR6&q=85&s=c7586416629768204fe17dd16b1f29b5" alt="Change business ID mapping interface" width="1160" height="810" data-path="images/rsa/en/wireframe-change-mapping.png" />

  <div class="frame-caption">Figure 16: Change Business ID Mapping — select the new mapping scope in the transfer box</div>
</div>

## 10. Security Best Practices

<Danger title="Important security reminders">
  * **The private key is displayed only once** — when the platform generates a key pair with one click, the private key is only copied to the clipboard and is not stored on the platform. It cannot be retrieved again after closing the page.
  * **merchantSecretKey and the merchant RSA private key** are both sensitive information. Do not place them in frontend code, client applications, logs, or public repositories.
  * **Save the private key immediately** — after generating a key, immediately save the private key to a secure key management system or encrypted storage.
  * **Key leakage response** — if a key is accidentally leaked, update the key through the platform as soon as possible.
</Danger>

### Signature Security Rules

| Item                | Description   |
| :------------------ | :------------ |
| Algorithm           | RSA           |
| Signature Algorithm | SHA256WithRSA |
| Key Length          | 2048 bits     |

**Signature generation rule:**

Include every parameter whose value is neither `null` nor `""`, exclude the `sign` and `sign_type` fields, sort the remaining field names in ASCII ascending order, and concatenate each key and value in the format `k1=v1&k2=v2&...`. Append `&key=merchantSecretKey` (the merchant secret key) to form the string to be signed. The merchant signs the string to be signed with its RSA private key using the SHA256WithRSA algorithm.

<Warning title="Signature notes">
  * Fields with a value of `null` or `""` are excluded from signing
  * API response fields may be added over time; when verifying a signature, you must include all new valid fields from the response message, rather than verifying against a fixed field list
  * The string to be signed must be encoded as **UTF-8** bytes before performing SHA256WithRSA signing or verification
  * Do not use loose empty checks (such as PHP `empty()` or JS `!value`) to filter parameters; otherwise `0`, `false`, or `"0"` may be incorrectly excluded, causing signature verification failures
</Warning>

<Expandable title="View signature tool code (Java / PHP / JavaScript)">
  <CodeGroup>
    ```java Java theme={null}
    public static String getSign(Object obj, String secretKey) {
        Map<String, Object> map;
        if (obj instanceof Map) {
            map = (Map<String, Object>) obj;
        } else {
            map = BeanMapTool.beanToMap(obj);
        }
        Set<String> keys = map.keySet();
        List<String> list = new ArrayList<>(keys);
        Collections.sort(list);

        StringBuilder sb = new StringBuilder();
        for (String key : list) {
            Object val = map.get(key);
            if (!("".equals(val) || val == null
                || List.of("sign_type", "sign").contains(key))) {
                sb.append(key).append("=").append(val).append("&");
            }
        }
        sb.append("key=").append(secretKey);
        return sb.toString();
    }
    ```

    ```php PHP theme={null}
    // Do not use loose empty checks such as empty()
    function getSign($array, $merchantSecretKey) {
        $keys = array_keys($array);
        sort($keys, SORT_STRING);
        $str = "";
        foreach ($keys as $key) {
            $val = $array[$key];
            if ($val !== null && $val !== ''
                && $key !== "sign" && $key !== "sign_type") {
                $str .= $key . "=" . $val . "&";
            }
        }
        return $str . "key=" . $merchantSecretKey;
    }
    ```

    ```js JavaScript theme={null}
    // Do not use loose checks such as if (!value)
    function getSign(map, merchantSecretKey) {
        const keys = Object.keys(map).sort();
        const sb = keys.reduce((acc, key) => {
            const val = map[key];
            if (val !== "" && val !== null
                && key !== "sign" && key !== "sign_type") {
                acc.push(`${key}=${val}`);
            }
            return acc;
        }, []).join('&');
        return `${sb}&key=${merchantSecretKey}`;
    }
    ```
  </CodeGroup>
</Expandable>

## 11. Key Format Requirements

When uploading a public key to the HaiPay platform, note the following format requirements:

| Item                | Requirement                                                                                                                                   |
| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- |
| Key Algorithm       | RSA                                                                                                                                           |
| Key Length          | 2048 bits                                                                                                                                     |
| Public Key Format   | PEM format (X.509 SubjectPublicKeyInfo)                                                                                                       |
| Upload Requirements | Remove the `-----BEGIN PUBLIC KEY-----` and `-----END PUBLIC KEY-----` markers, line breaks, and spaces; keep only the Base64-encoded content |
| Public Key Example  | `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...`                                                                                                         |

<Tip>
  If you choose the "HaiPay one-click generation" method, the platform handles the format automatically, so you do not need to process it manually. This note applies only to the "use your own public/private keys" method.
</Tip>

## 12. FAQ

<Accordion title="Q: Where is the private key stored after choosing HaiPay one-click generation?">
  The private key **is not stored on the HaiPay platform**. After generation, it is automatically copied to your clipboard, and you need to save it to a secure location immediately. The platform stores only the public key for signature verification.

  <Danger title="Note">
    The private key cannot be retrieved again after the dialog is closed. Make sure to save it immediately during the operation.
  </Danger>
</Accordion>

<Accordion title="Q: Can the old key still be used after replacement?">
  No. After a key replacement, **the original key becomes invalid immediately**. Requests signed with the old private key will fail HaiPay's signature verification. Perform the operation during off-peak business hours, and make sure the new private key has been configured in your system before replacing.
</Accordion>

<Accordion title="Q: What does it mean when a business ID shows 'All'?">
  When the appId column displays "All", it means the key applies to **all business IDs** under the merchant. Businesses added later are automatically configured with this public key as well. If you need different keys for different business IDs, use the "Specific Business IDs" mapping feature.
</Accordion>

<Accordion title="Q: What does the 'Show/Hide Mapped' button in the transfer box do?">
  The left panel of the transfer box displays only **unmapped** business IDs by default. Clicking the "Show/Hide Mapped" button toggles the display of business IDs mapped to other keys, making it easier to adjust mappings between different keys. The header title also switches between "Mapped Business IDs" and "All Business IDs" accordingly.
</Accordion>

<Accordion title="Q: Why are there multiple pop-up confirmations when replacing a key?">
  Key replacement is a **high-risk operation**, so the system is designed with multiple layers of confirmation to prevent accidental operations:

  * **First layer**: key overwrite reminder — informs which business IDs will be affected
  * **Second layer**: secondary confirmation dialog — final confirmation of the replacement

  Clicking "Back/Cancel" at any step returns to the dialog page; the dialog is not closed directly.
</Accordion>

<Accordion title="Q: How do I configure different public keys for different business IDs?">
  In the "Add/Replace Key" dialog, select "Specific Business IDs" for the mapped business IDs to open the transfer box. Move the business IDs to be mapped from the left side to the right side. After confirmation, the public key applies only to the business IDs selected on the right.

  You can also click "Change Business ID Mapping" in the Actions column of the data table to adjust the mapping scope of an existing public key.
</Accordion>

<Accordion title="Q: What should I do if signature verification fails?">
  Please check the following:

  * Confirm that the **private key** you use and the **public key** uploaded to the platform belong to the same key pair
  * Confirm that the signature string is sorted and concatenated in **ASCII ascending order**
  * Confirm that the `sign` and `sign_type` fields are excluded
  * Confirm that parameters with a value of `null` or `""` are excluded from signing
  * Confirm that the string to be signed is **UTF-8 encoded**
  * Confirm that loose empty checks (such as PHP `empty()` or JS `!value`) are not used
  * When verifying response messages, confirm that **all new valid fields** are included in the verification
</Accordion>

## Related Topics

<Columns cols={2}>
  <Card title="Integration Steps Guide" icon="plug" iconColor="#7B3FF2" iconBackground="#F3EEFF" href="/docs/en/guide/integration_guide">
    The complete integration flow from account creation to your first API call.
  </Card>

  <Card title="Integration Environment and Request URLs" icon="clipboard-list" iconColor="#1565C0" iconBackground="#E3F2FD" href="/docs/en/guide/api_parameters_doc">
    API integration environment descriptions and request URL reference.
  </Card>

  <Card title="API Description and Common Rules" icon="book-open" iconColor="#2E7D32" iconBackground="#E8F5E9" href="/docs/en/guide/api_description_guide">
    HaiPay API description and common request/response rules.
  </Card>

  <Card title="RSA Online Key Generation Tool" icon="key-round" iconColor="#E65100" iconBackground="#FFF3E0" href="/docs/en/rsa/rsa-generate">
    An online RSA key pair generation tool implemented purely in JavaScript, with no server interaction.
  </Card>
</Columns>

***

<div class="doc-footer">
  Last updated: September 2026 · HaiPay Technical Documentation Team

  If you have any questions, contact the HaiPay 24/7 operations team in the integration group.
</div>
