# Interface Parameter Signature Flow

# Content

parameter name Is it mandatory type of data description
appId mandatory string Merchant APP ID, provided by PayCools
sign mandatory string RSA signature of param
param mandatory string Request parameter string

# Example

{
  "appId": "abc6e413c37f14f9fabc36fcee8d97c5e",
  "sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "param": "{}"
}

# Description

  1. appId is a fixed value provided by PayCools;
  2. According to the specific interface documentation, construct the request parameters and format them into JSON. Use the formatted JSON as the value for param;
  3. Sign the param using the RSA private key, and the resulting value becomes the value for sign.

# Appendix: RSA Usage Example (Java Language)

Generate RSA key pair:

import java.security.*;
import java.util.Base64;

public class RsaGenerateKeyPair {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.genKeyPair();

        PublicKey publicKey = keyPair.getPublic();
        byte[] publicKeyBytes = publicKey.getEncoded();
        String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKeyBytes);
        System.out.println(publicKeyBase64);

        PrivateKey privateKey = keyPair.getPrivate();
        byte[] privateKeyBytes = privateKey.getEncoded();
        String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKeyBytes);
        System.out.println(privateKeyBase64);
    }
}

# API request signing key pair

The following public and private keys are example key pairs. When going live, be sure to generate and use your own keys.

Please submit the RSA public key to PayCools and do not disclose it to any third party.

The RSA private key is to be kept confidential by the merchant and should not be disclosed to anyone.

When a merchant makes requests to PayCools Open API, the merchant signs the request parameters with the RSA private key.

PayCools will use the RSA public key provided by the merchant to verify the signature in the request. If the verification fails, PayCools servers will reject processing the request.

RSA Public Key:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAna4Dyz8nGJiAlc9jTGyRa+TtlZXYABTc+Xfb3T4NdDbnUO8vtNLHugwmqARp8kzEzsMRbmvKro4EpaXqANn7SAGo+YI6sVUDmX7ESk3P6j51PtTvWR6dikJN6qwtmV64ojEbxDnIBL3VKuctefL8uPcI7MZBUPBXg9l8CZmnn2cKqWjZ8MuEQr4G45IqmJ0tRsRmW9ofNnvI1MLPt7c/Z/D1E6HKVwjPcMZKMuF0HpIDqdQaPX83dlSzv9FF9jFR8HWfWW8Oz3jz+GtSLSdh2ERcyO56WHpWl1POV4o9jF+4R/oBgcH+0zA1Z2aFfQf/n9miMhacrioStBaHkh1f/QIDAQAB

RSA Private Key:

MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdrgPLPycYmICVz2NMbJFr5O2VldgAFNz5d9vdPg10NudQ7y+00se6DCaoBGnyTMTOwxFua8qujgSlpeoA2ftIAaj5gjqxVQOZfsRKTc/qPnU+1O9ZHp2KQk3qrC2ZXriiMRvEOcgEvdUq5y158vy49wjsxkFQ8FeD2XwJmaefZwqpaNnwy4RCvgbjkiqYnS1GxGZb2h82e8jUws+3tz9n8PUTocpXCM9wxkoy4XQekgOp1Bo9fzd2VLO/0UX2MVHwdZ9Zbw7PePP4a1ItJ2HYRFzI7npYelaXU85Xij2MX7hH+gGBwf7TMDVnZoV9B/+f2aIyFpyuKhK0FoeSHV/9AgMBAAECggEAYyqq5iucqgJXdGCO4eSx/LpolZg81ahJZXf1RgqdqYZSKnuTdFTQGflEYo0MGMAhUqwqDVkrimZ1E7zqE4kEWT/6BpnZ0edWsTWhu91+MqL/V/nRYio4CFk06a9JqliBJDhgbyOr4ReGtknYNwcT3Dw5V7hEIeRWFe007lC9tCi7mlpzBNwEIf4itmnncuA70GlxcoMkoGzfYg79eUCfXorbfJcaamR2wXLSU6KoJ422UR3L0rgzmgXzVQw9rrlQ3h6viDykKfaPi/43MN2qb6Zu5isbJIzyz0kHrcE6KJMgJhBDkLIo0f0qE/rEl1Xp/qDwr4+3WBfCHeuTFsud/QKBgQDXmA3f0/ONPMgEGdJlwG20W+7jXHabnRPuUJyDQKbtP+vuaKrpzN+jC1rlxBfAJj2iAVXXXM/RFWWapBd16TqGI4P3RW8eocaxhyl8rWSvCOy/OueNI+fM8gX/IjsJc7VMmCEWHuLvXoM2ixXPWP3v0DEPPPDrCd5dnjR6+5oGgwKBgQC7O03ps4KzMUzEtJcrFFKV0C/m1X905OqQ3cKQnGqRzLp/7d9DQsv+oKzjlpz1xktdJmig7ABiL0+FqJHdcrNiVabI5c6oS2SZkToQFlKv2GYT2KikJ0L43xLfiDvB3tues//9OXuU0WzXZqq7CNAvcmAdPjlFi9RxHsRGABo3fwKBgEi2EJ/XpQGSaUbwyoPktVsp0lS9/4aWIH20lES0DlhfwZuDk3kMzrP3hW2OiBAXFZxI5QGgXLqAg+b2xq7OvR02ZzCDK2niV9fR5Q0Wkaly0h3gqO1yGaCGU71rdwvGCXROroH+Yr0mXAyONgnbUrGJvrIL9JjgmC1syPhdWOIvAoGBAJHJbbNpWX3aB2KrE4IxwtRwVLwyxZnpnVPLuPINOVXpydZPDCc9XcYYqkZUQkeFba1MeO/Ek8/f8tWqGloKM+9/reyENFQK0Hxa/pEEMMJHh8QwUa/v+k/6sqFnXNBqjSuYEN3F4ppQL6XRhWM5S5GGR5y9lK64YGTshfvTnJZVAoGBAJ3TmJcRJWfi7CA985VAnE+IQoQfKKz9NTT7hGBwWTVd7iUc0QCpgHNIixZnfVcjKxz7Hhq6Vy+cEbDBtwbSuDfuVf1spiiqOuYVIjFqq5AsuvpX1CJmm7V+LRtJO/NXmXQP5YfojzET9NqTZvGEVXuzPA0qp8JC7HKrCYykscqE

# RSA Signature:

import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

public class RsaSign {

    public static final String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCdrgPLPycYmICVz2NMbJFr5O2VldgAFNz5d9vdPg10NudQ7y+00se6DCaoBGnyTMTOwxFua8qujgSlpeoA2ftIAaj5gjqxVQOZfsRKTc/qPnU+1O9ZHp2KQk3qrC2ZXriiMRvEOcgEvdUq5y158vy49wjsxkFQ8FeD2XwJmaefZwqpaNnwy4RCvgbjkiqYnS1GxGZb2h82e8jUws+3tz9n8PUTocpXCM9wxkoy4XQekgOp1Bo9fzd2VLO/0UX2MVHwdZ9Zbw7PePP4a1ItJ2HYRFzI7npYelaXU85Xij2MX7hH+gGBwf7TMDVnZoV9B/+f2aIyFpyuKhK0FoeSHV/9AgMBAAECggEAYyqq5iucqgJXdGCO4eSx/LpolZg81ahJZXf1RgqdqYZSKnuTdFTQGflEYo0MGMAhUqwqDVkrimZ1E7zqE4kEWT/6BpnZ0edWsTWhu91+MqL/V/nRYio4CFk06a9JqliBJDhgbyOr4ReGtknYNwcT3Dw5V7hEIeRWFe007lC9tCi7mlpzBNwEIf4itmnncuA70GlxcoMkoGzfYg79eUCfXorbfJcaamR2wXLSU6KoJ422UR3L0rgzmgXzVQw9rrlQ3h6viDykKfaPi/43MN2qb6Zu5isbJIzyz0kHrcE6KJMgJhBDkLIo0f0qE/rEl1Xp/qDwr4+3WBfCHeuTFsud/QKBgQDXmA3f0/ONPMgEGdJlwG20W+7jXHabnRPuUJyDQKbtP+vuaKrpzN+jC1rlxBfAJj2iAVXXXM/RFWWapBd16TqGI4P3RW8eocaxhyl8rWSvCOy/OueNI+fM8gX/IjsJc7VMmCEWHuLvXoM2ixXPWP3v0DEPPPDrCd5dnjR6+5oGgwKBgQC7O03ps4KzMUzEtJcrFFKV0C/m1X905OqQ3cKQnGqRzLp/7d9DQsv+oKzjlpz1xktdJmig7ABiL0+FqJHdcrNiVabI5c6oS2SZkToQFlKv2GYT2KikJ0L43xLfiDvB3tues//9OXuU0WzXZqq7CNAvcmAdPjlFi9RxHsRGABo3fwKBgEi2EJ/XpQGSaUbwyoPktVsp0lS9/4aWIH20lES0DlhfwZuDk3kMzrP3hW2OiBAXFZxI5QGgXLqAg+b2xq7OvR02ZzCDK2niV9fR5Q0Wkaly0h3gqO1yGaCGU71rdwvGCXROroH+Yr0mXAyONgnbUrGJvrIL9JjgmC1syPhdWOIvAoGBAJHJbbNpWX3aB2KrE4IxwtRwVLwyxZnpnVPLuPINOVXpydZPDCc9XcYYqkZUQkeFba1MeO/Ek8/f8tWqGloKM+9/reyENFQK0Hxa/pEEMMJHh8QwUa/v+k/6sqFnXNBqjSuYEN3F4ppQL6XRhWM5S5GGR5y9lK64YGTshfvTnJZVAoGBAJ3TmJcRJWfi7CA985VAnE+IQoQfKKz9NTT7hGBwWTVd7iUc0QCpgHNIixZnfVcjKxz7Hhq6Vy+cEbDBtwbSuDfuVf1spiiqOuYVIjFqq5AsuvpX1CJmm7V+LRtJO/NXmXQP5YfojzET9NqTZvGEVXuzPA0qp8JC7HKrCYykscqE";

    public static void main(String[] args) throws Exception {
        String param = "{\"mchOrderId\":\"TestMchOrderIdP0001\",\"amount\":10000,\"email\":\"test@123.com\",\"mobile\":\"81234567890\",\"customerName\":\"test\",\"remark\":\"test payment code\",\"notifyUrl\":\"http://test\",\"channelCode\":\"ALFAMART_DYNAMIC_VA\",\"timestamp\":1678356680000}";

        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(PRIVATE_KEY))));
        signature.update(param.getBytes());
        byte[] bytes = signature.sign();
        String sign = Base64.getEncoder().encodeToString(bytes);
        System.out.println(sign);
    }
}

sign value:

AqZmoNEY4Hwt3tFhQCiQgULYAdrr0cJOZQSAJzU9Dta6y7aMGVsK800ubGrjF+4arXcO14df4uKy52N9Z8N/HPOn/Kq0QEZWmhT0XY99FkRzMG4ZJvIu2rHXqOIZTb+YjEI9ZRlMg1ng7+Qj1XppAZOunZEakYhksq7uLb7GNmXfV/jJBYTBoQw9/axIAnqnr3GllgdES6ZtGgVqKLnErMpm/KbJjjSABEvfPI2mg6EQcZmvVJD/SEt9uTvicROJFx5Y/l3gQbTFRFfBjfWvNk+yFiKnyYvVHH1KiM49QGNcr7Eb3wTVMbRoHwK2p2qLHTYA4Qns4GOUkpvdCJmS7w==

# RSA Signature Verification

import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RsaVerifySign {

    public static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAna4Dyz8nGJiAlc9jTGyRa+TtlZXYABTc+Xfb3T4NdDbnUO8vtNLHugwmqARp8kzEzsMRbmvKro4EpaXqANn7SAGo+YI6sVUDmX7ESk3P6j51PtTvWR6dikJN6qwtmV64ojEbxDnIBL3VKuctefL8uPcI7MZBUPBXg9l8CZmnn2cKqWjZ8MuEQr4G45IqmJ0tRsRmW9ofNnvI1MLPt7c/Z/D1E6HKVwjPcMZKMuF0HpIDqdQaPX83dlSzv9FF9jFR8HWfWW8Oz3jz+GtSLSdh2ERcyO56WHpWl1POV4o9jF+4R/oBgcH+0zA1Z2aFfQf/n9miMhacrioStBaHkh1f/QIDAQAB";

    public static void main(String[] args) throws Exception {
        String param = "{\"mchOrderId\":\"TestMchOrderIdP0001\",\"amount\":10000,\"email\":\"test@123.com\",\"mobile\":\"81234567890\",\"customerName\":\"test\",\"remark\":\"test payment code\",\"notifyUrl\":\"http://test\",\"channelCode\":\"ALFAMART_DYNAMIC_VA\",\"timestamp\":1678356680000}";

        String sign = "AqZmoNEY4Hwt3tFhQCiQgULYAdrr0cJOZQSAJzU9Dta6y7aMGVsK800ubGrjF+4arXcO14df4uKy52N9Z8N/HPOn/Kq0QEZWmhT0XY99FkRzMG4ZJvIu2rHXqOIZTb+YjEI9ZRlMg1ng7+Qj1XppAZOunZEakYhksq7uLb7GNmXfV/jJBYTBoQw9/axIAnqnr3GllgdES6ZtGgVqKLnErMpm/KbJjjSABEvfPI2mg6EQcZmvVJD/SEt9uTvicROJFx5Y/l3gQbTFRFfBjfWvNk+yFiKnyYvVHH1KiM49QGNcr7Eb3wTVMbRoHwK2p2qLHTYA4Qns4GOUkpvdCJmS7w==";
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(PUBLIC_KEY))));
        signature.update(param.getBytes());
        boolean result = signature.verify(Base64.getDecoder().decode(sign));
        System.out.println(result);
    }
}

result value: true

# UAT Environment Callback Verification Key:

This public key is only used for UAT environment signature verification. For production environment signature verification, please contact PayCools to obtain the production verification public key.

Verification method is the same as above.

UAT environment

RSA Public Key:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkVfk60Kfyny3ZGDQeiImEstQ+4DuLkHzXEJBQS4LL844rme6YVTibirk71L1BsW995GVVlj2wOdbafXOFHW0Q+a07oDauZJU76BjA4BdVTO0KprZYpnOAzQPcYwEXNrSJA19jt8SXBKLTMKHHvpaQ4tc25WBFwcHWZhZlvrSspDyRIoE9Jge76TbmuTK2SaB9i3vNTBb0VTRrhnI9K5p5VQIJQRqXhIe28foF1jl7Rz4Q1hQuUgw7DHh9vRFR/VrJbVD9rcQT8czGKXFjAmzX+fs3vzW5/vXsXmz4sbmhd4PH4Rqzz3Xr5Z7+YYYPZ/TxWiK3Uq+BHe7UKK0lgJt0QIDAQAB