# 统一 API请求参数
# 内容
参数名 | 是否必填 | 类型 | 说明 |
---|---|---|---|
appId | 是 | string | 商户APP ID,由 Platform 提供 |
sign | 是 | string | param 的RSA签名 |
param | 是 | string | 请求参数字符串 |
# 示例
{
"appId": "123456",
"sign": "abcdef",
"param": "{}"
}
# 说明
appId
是由 Platform 提供的固定值;- 根据具体接口文档,构造请求参数,将请求参数格式化为 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);
}
}
RSA 公钥请提交给 Platform,请不要透露给任何第三方。
RSA 私钥由商户保管,请不要透露给任何人。
当商户请求 Platform 的 Open API 时,商户使用 RSA 私钥对请求参数进行签名,Platform 会使用商户提供的 RSA 公钥对请求中的签名进行验证。如果验证失败,Platform 服务器会拒绝处理请求。
# 示例密钥对
RSA 公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8aqn1piRvu6OyAO5shHOsKH/INH73zjwfTZ7A9+cJdLJaHZ+eiuGbM2wUnCTZadpH8xQiNDnBuSAZzByvc+IDCfhFlBGpzpLtBlSS3F2D85yc6HS8CcLVq3lyt5Vs83LU1p/vStaiivdzcFBY3w8X5fnGjU35ybZSgb47ye5s90a6H1tBTf8vzznKMMNj1mqRIGUDBxPy7B4MfrlYT5TmO45aLmrWjh+ng0E6EuU4mMKV4eDvoX+dDDdXmhZ53eDCeyn5V/pMkvpcbVwqXsdF3IbUYAu882DXD/tx2WDFYNmO8JbdJUMbz+6pW9VwGsope5jYfVSLWO0wxqo7kOMQIDAQAB
RSA 私钥:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/xqqfWmJG+7o7IA7myEc6wof8g0fvfOPB9NnsD35wl0slodn56K4ZszbBScJNlp2kfzFCI0OcG5IBnMHK9z4gMJ+EWUEanOku0GVJLcXYPznJzodLwJwtWreXK3lWzzctTWn+9K1qKK93NwUFjfDxfl+caNTfnJtlKBvjvJ7mz3RrofW0FN/y/POcoww2PWapEgZQMHE/LsHgx+uVhPlOY7jlouataOH6eDQToS5TiYwpXh4O+hf50MN1eaFnnd4MJ7KflX+kyS+lxtXCpex0XchtRgC7zzYNcP+3HZYMVg2Y7wlt0lQxvP7qlb1XAayil7mNh9VItY7TDGqjuQ4xAgMBAAECggEAG4hpPKGcVHaVgSGUIhwE5fHB1kX+0OpMRK9jjhmXXJDMECYRhmiafkQVi2CMjdke3twH9WfcsA/hQWwBAqPGfpacgELULv7yF2+B6ySwL+C76jZFhGGtynEoxIJQVF9Bm7ZujlUQhJo8vs/eX7LGMdWj4m/GiCgSw04j2ulcouRMJPU/FrKnljWI2a8Dy02laTjt5gnulGbd+1V+kxo7BkvpGNAJE1q3Mm6vRDAlEBESOJuv/SRvfKT3L1XvPrIAuVAhmtW4beAXUF7ohWslYWbYy8ct5mWP3457A4COTpTmnV1gcrUTwxiEN9Rjxuxk2zShGLzWJ1DshP+Q++Oh9QKBgQDrRCt6CLIea+pqBEHNeKEBFHfB4FabptZcm17lyk177zDNEAENCsYKsruudotnP5ZkmJk6xl3wcCmsf5UQ3YzWamBxzZZV7CMHf8yUlSeEWf+OvEE05A5oFV2rR2rLvssG4UzuSyEpkFkigblMP7tmCAHhLlLxr2nlAaNXWiV6awKBgQDQrVDFg3OQETQ/HvtBq6REhr6WMqM2CdFTHjDJRFofPr3Vo+tscGN8WNp8cq8Phu1Z9qNn33CF3Zqv/021K92fXMFu1Ha8I3QWxu8aLgUQgWz+cVNTyRNRrgF3Q1V41qN0JAC9kKARL64oT3yZRML53GpbzcEmMyeXC+64sxl40wKBgEhESWKT9zq3BWuJYTkfW718LwkjwxbO2bvakfzd9o0iPQhQaTI7Y/f3TQVbLpkJhEXkRfUy57oqifKNwhlLJK7cQEHU1+AOx/fOvuXJJzlVd9W9Z/46K163aW1qY5iwQ6caX8o207nzuB2MYYHVddfyj7k+xIWuz0VkCmuTqj1/AoGBAMCrpW4YRrT4DYNSOa6SqeLTfljzfBpCylCyCV1rjMJYjbIZ3R6MTm7bIy/QO65cZ/2uaYVYmm4fA9oIIVlrnP6tB7Qq204uddsp5k4Hu4lX1qi/Pa6YcwvxW00gkGQ32Uc8jqp4RDJaEbUKXwKsqFFGn7UProx0otMlo05JnvUdAoGAO1KKSqSWrADfx06uAS8TdBYWV4cVOpfFZiTm3lLD59D3TxlQijXoGdLJsqywdBpe5dhoVMI91i+XDkAOT1xW2yondEdUurnYhijM91OfsoGIJeR30r4DqEDDiuGctgKqi0xWS69i3sFT9w+tANvwSLtQIyU0T70wWb9RhTxafJk=
# 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 = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC/xqqfWmJG+7o7IA7myEc6wof8g0fvfOPB9NnsD35wl0slodn56K4ZszbBScJNlp2kfzFCI0OcG5IBnMHK9z4gMJ+EWUEanOku0GVJLcXYPznJzodLwJwtWreXK3lWzzctTWn+9K1qKK93NwUFjfDxfl+caNTfnJtlKBvjvJ7mz3RrofW0FN/y/POcoww2PWapEgZQMHE/LsHgx+uVhPlOY7jlouataOH6eDQToS5TiYwpXh4O+hf50MN1eaFnnd4MJ7KflX+kyS+lxtXCpex0XchtRgC7zzYNcP+3HZYMVg2Y7wlt0lQxvP7qlb1XAayil7mNh9VItY7TDGqjuQ4xAgMBAAECggEAG4hpPKGcVHaVgSGUIhwE5fHB1kX+0OpMRK9jjhmXXJDMECYRhmiafkQVi2CMjdke3twH9WfcsA/hQWwBAqPGfpacgELULv7yF2+B6ySwL+C76jZFhGGtynEoxIJQVF9Bm7ZujlUQhJo8vs/eX7LGMdWj4m/GiCgSw04j2ulcouRMJPU/FrKnljWI2a8Dy02laTjt5gnulGbd+1V+kxo7BkvpGNAJE1q3Mm6vRDAlEBESOJuv/SRvfKT3L1XvPrIAuVAhmtW4beAXUF7ohWslYWbYy8ct5mWP3457A4COTpTmnV1gcrUTwxiEN9Rjxuxk2zShGLzWJ1DshP+Q++Oh9QKBgQDrRCt6CLIea+pqBEHNeKEBFHfB4FabptZcm17lyk177zDNEAENCsYKsruudotnP5ZkmJk6xl3wcCmsf5UQ3YzWamBxzZZV7CMHf8yUlSeEWf+OvEE05A5oFV2rR2rLvssG4UzuSyEpkFkigblMP7tmCAHhLlLxr2nlAaNXWiV6awKBgQDQrVDFg3OQETQ/HvtBq6REhr6WMqM2CdFTHjDJRFofPr3Vo+tscGN8WNp8cq8Phu1Z9qNn33CF3Zqv/021K92fXMFu1Ha8I3QWxu8aLgUQgWz+cVNTyRNRrgF3Q1V41qN0JAC9kKARL64oT3yZRML53GpbzcEmMyeXC+64sxl40wKBgEhESWKT9zq3BWuJYTkfW718LwkjwxbO2bvakfzd9o0iPQhQaTI7Y/f3TQVbLpkJhEXkRfUy57oqifKNwhlLJK7cQEHU1+AOx/fOvuXJJzlVd9W9Z/46K163aW1qY5iwQ6caX8o207nzuB2MYYHVddfyj7k+xIWuz0VkCmuTqj1/AoGBAMCrpW4YRrT4DYNSOa6SqeLTfljzfBpCylCyCV1rjMJYjbIZ3R6MTm7bIy/QO65cZ/2uaYVYmm4fA9oIIVlrnP6tB7Qq204uddsp5k4Hu4lX1qi/Pa6YcwvxW00gkGQ32Uc8jqp4RDJaEbUKXwKsqFFGn7UProx0otMlo05JnvUdAoGAO1KKSqSWrADfx06uAS8TdBYWV4cVOpfFZiTm3lLD59D3TxlQijXoGdLJsqywdBpe5dhoVMI91i+XDkAOT1xW2yondEdUurnYhijM91OfsoGIJeR30r4DqEDDiuGctgKqi0xWS69i3sFT9w+tANvwSLtQIyU0T70wWb9RhTxafJk=";
public static void main(String[] args) throws Exception {
String param = "{\"mchOrderId\":\"Ezpay00001\",\"amount\":5000,\"customerName\":\"EzpayUser\",\"channelCode\":\"PH_GCASH_URL\",\"payMode\":\"WEB\",\"email\":\"Ezpay@gmail.com\",\"redirectUrl\":\"https://www.google.com/\",\"mobile\":\"09123456789\",\"timestamp\":\"1717579821874\"}";
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
的值:
tFzLYvD0xpevdghs9ukFoStNWBfXY10hHTYOLsLC2AL5H5zjdlF7ALdYAVNuq/aqDJVkqQgDA36maE9BcSpkoYCdtbajrOJ+JADSBO1718LdhTmjzVBU0C4PtUE4XrPHPhI3tfBOUK7aDFEG7RtGLB1gLPzxZRpv8+elc0Tqvt0SooSTyEhaaId20uPAFUIYUF4KDMmiqLpGQ37kHLXglwYa4nix4VbnyEHzw+JzEqSMhrzJAwCw9VIFZxCqOFEJH5yltVDJGlPM5Wm5rP9oHabEM8Qll1LDJZRfaNK/DbQuUT1SJ7hrKRJbD/RR1h5K4c0SjK2T1rHYKavhdSaX5Q==
# 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 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv8aqn1piRvu6OyAO5shHOsKH/INH73zjwfTZ7A9+cJdLJaHZ+eiuGbM2wUnCTZadpH8xQiNDnBuSAZzByvc+IDCfhFlBGpzpLtBlSS3F2D85yc6HS8CcLVq3lyt5Vs83LU1p/vStaiivdzcFBY3w8X5fnGjU35ybZSgb47ye5s90a6H1tBTf8vzznKMMNj1mqRIGUDBxPy7B4MfrlYT5TmO45aLmrWjh+ng0E6EuU4mMKV4eDvoX+dDDdXmhZ53eDCeyn5V/pMkvpcbVwqXsdF3IbUYAu882DXD/tx2WDFYNmO8JbdJUMbz+6pW9VwGsope5jYfVSLWO0wxqo7kOMQIDAQAB";
public static void main(String[] args) throws Exception {
String param = "{\"mchOrderId\":\"Ezpay00001\",\"amount\":5000,\"customerName\":\"EzpayUser\",\"channelCode\":\"PH_GCASH_URL\",\"payMode\":\"WEB\",\"email\":\"Ezpay@gmail.com\",\"redirectUrl\":\"https://www.google.com/\",\"mobile\":\"09123456789\",\"timestamp\":\"1717579821874\"}";
String sign = "tFzLYvD0xpevdghs9ukFoStNWBfXY10hHTYOLsLC2AL5H5zjdlF7ALdYAVNuq/aqDJVkqQgDA36maE9BcSpkoYCdtbajrOJ+JADSBO1718LdhTmjzVBU0C4PtUE4XrPHPhI3tfBOUK7aDFEG7RtGLB1gLPzxZRpv8+elc0Tqvt0SooSTyEhaaId20uPAFUIYUF4KDMmiqLpGQ37kHLXglwYa4nix4VbnyEHzw+JzEqSMhrzJAwCw9VIFZxCqOFEJH5yltVDJGlPM5Wm5rP9oHabEM8Qll1LDJZRfaNK/DbQuUT1SJ7hrKRJbD/RR1h5K4c0SjK2T1rHYKavhdSaX5Q==";
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
统一异步通知参数 →