Skip to content

全局说明

本章节介绍 Thailand Pay 接口的全局交互规范,包括请求方式、签名算法以及签名工具代码示例。


1. 请求方式

交互类型请求方法Content-Type备注
订单创建、查询POSTapplication/json; charset=utf-8商户向平台发起的请求
异步通知回调POSTapplication/json; charset=utf-8平台向商户发送的通知

2. 请求头 (Request Headers)

在请求所有接口时,必须在 HTTP Header 中携带以下参数以作身份校验:

参数名是否必填类型说明
merchantNostring商户号,由平台统一分配提供。
signstring请求体 JSON 字符串的 RSA-SHA256 签名值(Base64 编码)。

3. 签名算法说明

  1. 构造参数: 按照具体接口的参数定义,构造请求体对象。
  2. 格式化 JSON: 将请求体参数格式化为标准的 JSON 字符串(注意保持字段结构一致)。
  3. 加签与验签:
    • 商户发送请求: 商户使用自己的 RSA 私钥 对 JSON 请求体进行签名,并将签名结果放入 Header 的 sign 字段中。平台会使用商户提供的 RSA 公钥 进行验签。
    • 平台回调通知: 平台发送通知时,会使用平台的私钥签名。商户收到后,需要使用 平台公钥 进行验签。

平台测试公钥

IMPORTANT

以下为测试环境的平台公钥,用于验证平台回调的签名(正式环境的公钥将在对接完成后由平台发放):

text
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0kr9IpgDckceWl1g8IRAMV6hALHspEb+SzIsrcc2+Q9WSot/c9YbRZzd+yuzkazMv4HAHeW7oLkG1lcxFYxgPM2x0GbhWqy1Yk5iiARS0h3E2mbuDy7neaL9DzZ411Xwq/pcoEAaklJtwwkXwlIcJGVHUFAebX6Yc6BitcfSvjZe7ilyVX0LA2aTxRGoF490gWo3R7TEXK/Lmdh/rC6FldyexdlAoc1DYbCBFZJQXxJReBbvNj+jJi1BsrsrbrKXBHd9M7/vzBwrHGDa09Y4Yw1wVPm+ZRFFs8hC3bVlZWrpOrR9o9S9kSH47YmnHDPve8fK9/ySEHp6JZ0QxJOnd6DQ0uGdAWswWlIZ4Jjg2qJxC6PHmoRYeWjyc9BuekUtDv9Yiyi9SBfGJQJStjC9PksKsMtUCGaoszPMLhMDGCX9mvYKuxK+vHDK3csWu2iRtX9TIulk/ojNsoZkSKV9tnsmiPFKb9vD79k2RiRyKYVlwpLe9Gyq/joN32i6qIyuN7h5iyms+mxya3DiGNNGdrYwaRGK+nwyJtuZJ9LI8GvWjcq5hVDeAgYnUs16N/ujCbWzHpvzDpmZxgJHXxHPk9TAFzrbTUJQ4p6TBpY87NHb2ozJcOFkFzoYEmqMhivM7vn4gqmd/r1z7PNfjNpJK2dv7pjUQ28S9FEZnsnnJecCAwEAAQ==

4. Java 签名工具示例

java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class SignUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(SignUtil.class);

    /**
     * 验证签名
     *
     * @param param     原始 JSON 字符串
     * @param sign      Base64 签名值
     * @param publicKey RSA公钥字符串 (Base64)
     * @return 验签是否通过
     */
    public static boolean checkSign(String param, String sign, String publicKey) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initVerify(KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey))));
            signature.update(param.getBytes());
            return signature.verify(Base64.getDecoder().decode(sign));
        } catch (Exception e) {
            LOGGER.error("Sign校验错误 :", e);
        }
        return false;
    }

    /**
     * 生成签名
     *
     * @param param      待加签的 JSON 字符串
     * @param privateKey RSA私钥字符串 (Base64)
     * @return 签名后的 Base64 字符串
     */
    public static String sign(String param, String privateKey) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))));
            signature.update(param.getBytes());
            byte[] bytes = signature.sign();
            return Base64.getEncoder().encodeToString(bytes);
        } catch (Exception e) {
            LOGGER.error("Sign签名错误 :", e);
        }
        return null;
    }
}

5. 请求发送示例 (Java)

java
Map<String, Object> map = new HashMap<>();
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
map.put("merchantOrderNo", "ORDER_123456789");
// ... 填充其他业务参数

String body = gson.toJson(map);
String sign = SignUtil.sign(body, merchantPrivateKey);

HttpResponse<String> stringHttpResponse = Unirest.post("https://api.thailandpay.com/payin/create")
        .header("Content-Type", "application/json; charset=utf-8")
        .header("merchantNo", "M1639466186292")
        .header("sign", sign)
        .body(body)
        .asString();

6. 商户 RSA 密钥生成示例 (Java)

java
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;

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

        // 公钥
        PublicKey publicKey = keyPair.getPublic();
        String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        System.out.println("----- Public Key (Provide to Platform) -----");
        System.out.println(publicKeyBase64);

        // 私钥
        PrivateKey privateKey = keyPair.getPrivate();
        String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        System.out.println("----- Private Key (Keep Secret) -----");
        System.out.println(privateKeyBase64);
    }
}