# 接口参数签名流程
# 内容
| 参数名 | 是否必填 | 类型 | 说明 |
|---|---|---|---|
| appId | 是 | string | 商户APP ID,由PayCools提供 |
| sign | 是 | string | param 的RSA签名 |
| param | 是 | string | 请求参数字符串 |
# 示例
{
"appId": "abc6e413c37f14f9fabc36fcee8d97c5e",
"sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"param": "{}"
}
# 说明
appId是由 PayCools 提供的固定值;- 根据具体接口文档,构造请求参数,将请求参数格式化为 JSON 格式,作为
param的值; - 使用 RSA 私钥对
param进行签名,得到的值作为sign的值。
# 附录 RSA 使用示例(Java 语言)
生成RSA密钥对:
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请求请求加签密钥对
以下公钥、私钥为示例密钥对,服务上线请务必重新生成并使用自己的密钥
RSA 公钥请提交给 PayCools,请不要透露给任何第三方。
RSA 私钥由商户保管,请不要透露给任何人。
当商户请求 PayCools 的 Open API 时,商户使用 RSA 私钥对请求参数进行签名,Eztrans 会使用商户提供的 RSA 公钥对请求中的签名进行验证。如果验证失败,Eztrans 服务器会拒绝处理请求。
RSA 公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAna4Dyz8nGJiAlc9jTGyRa+TtlZXYABTc+Xfb3T4NdDbnUO8vtNLHugwmqARp8kzEzsMRbmvKro4EpaXqANn7SAGo+YI6sVUDmX7ESk3P6j51PtTvWR6dikJN6qwtmV64ojEbxDnIBL3VKuctefL8uPcI7MZBUPBXg9l8CZmnn2cKqWjZ8MuEQr4G45IqmJ0tRsRmW9ofNnvI1MLPt7c/Z/D1E6HKVwjPcMZKMuF0HpIDqdQaPX83dlSzv9FF9jFR8HWfWW8Oz3jz+GtSLSdh2ERcyO56WHpWl1POV4o9jF+4R/oBgcH+0zA1Z2aFfQf/n9miMhacrioStBaHkh1f/QIDAQAB
RSA 私钥:
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 签名:
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的值:
AqZmoNEY4Hwt3tFhQCiQgULYAdrr0cJOZQSAJzU9Dta6y7aMGVsK800ubGrjF+4arXcO14df4uKy52N9Z8N/HPOn/Kq0QEZWmhT0XY99FkRzMG4ZJvIu2rHXqOIZTb+YjEI9ZRlMg1ng7+Qj1XppAZOunZEakYhksq7uLb7GNmXfV/jJBYTBoQw9/axIAnqnr3GllgdES6ZtGgVqKLnErMpm/KbJjjSABEvfPI2mg6EQcZmvVJD/SEt9uTvicROJFx5Y/l3gQbTFRFfBjfWvNk+yFiKnyYvVHH1KiM49QGNcr7Eb3wTVMbRoHwK2p2qLHTYA4Qns4GOUkpvdCJmS7w==
# RSA 签名验证
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 的值:
true
# UAT环境回调验签密钥
该公钥仅用于UAT环境验签,服务上线请联系PayCools下发生产验签公钥
验签方式同上
RSA 公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkVfk60Kfyny3ZGDQeiImEstQ+4DuLkHzXEJBQS4LL844rme6YVTibirk71L1BsW995GVVlj2wOdbafXOFHW0Q+a07oDauZJU76BjA4BdVTO0KprZYpnOAzQPcYwEXNrSJA19jt8SXBKLTMKHHvpaQ4tc25WBFwcHWZhZlvrSspDyRIoE9Jge76TbmuTK2SaB9i3vNTBb0VTRrhnI9K5p5VQIJQRqXhIe28foF1jl7Rz4Q1hQuUgw7DHh9vRFR/VrJbVD9rcQT8czGKXFjAmzX+fs3vzW5/vXsXmz4sbmhd4PH4Rqzz3Xr5Z7+YYYPZ/TxWiK3Uq+BHe7UKK0lgJt0QIDAQAB
API通用提示码 →