Skip to content

接入说明与开发指南 ​

本文档介绍商户接入孟加拉支付系统的通用规范、请求头标准、RSA 签名机制与密钥生成方法。


一、通用请求规范 ​

交互类型请求方法请求头 Content-Type报文格式
API 请求(订单创建、查询、余额等)POSTapplication/json; charset=utf-8JSON
回调通知(平台推送至商户系统)POSTapplication/json; charset=utf-8JSON

二、通用请求头(HTTP Headers) ​

所有发送至平台的 API 请求以及平台发送的回调通知,均必须包含以下请求头:

请求头参数是否必填类型说明
merchantNo是String商户号,由平台统一下发分配
sign是String请求 Body 内容的 RSA 签名(Base64 编码)

三、RSA 签名与验签算法 ​

1. 签名流程 ​

  1. 根据具体的接口文档构造请求参数对象;
  2. 将请求参数对象序列化为标准 JSON 字符串(作为请求 Body);
  3. 使用**商户自身的私钥(Private Key)**对该 JSON 字符串进行 SHA256withRSA 签名;
  4. 将签名后的字节数组通过 Base64 编码后放入 HTTP Header 的 sign 字段中;
  5. 将商户号放入 HTTP Header 的 merchantNo 字段中,发起 HTTP POST 请求。

2. 验签流程 ​

  1. 商户端请求平台:平台使用商户提供的公钥对 sign 与请求 Body 进行验签;
  2. 平台回调商户端:平台推送异步回调时,商户端需使用平台提供的公钥对 sign 与回调 Body 进行验签(注:验签时请注意忽略大小写差异)。

四、平台公钥 ​

测试环境平台公钥 ​

NOTE

以下为测试环境的平台公钥,用于验证平台回调的签名(正式环境公钥,在商户后台-账号信息查看):

text
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx370DGx1EXhyRVF242HkEtGAYuGbG51bE8Ne/lMgRJXnCZLvL4jYsb+3X8vRxLhitzp/iU6Dtdo0f5dMWW8i2ofnZPkg0bD2jeXXsK5KvGYh89Y0SrNROspQcMR+e2R7XdXVfjwiPcTwnpAviYPgFkgIBB0ZpssO4BVMeYeh51dc496emQadB4KXaN7KJGld1nimzYVUigA6SQfMV5jHiD4BgVRSWof3f6I2H4hdFpLniQ+rY/zAC3mwMdKP6/UIFp83DIzRSszjsLVdZ/BA5re9Ifur9Rlps/CY0+N28om/e9U5wXxuGuGWtiJ/Y4lMm8DzxzNTVq+SBShWFCCdnHxfn4Y3TwgXYg1s4uIue3XMcSfLa9nwq31UvMq7+YH0JeVduWsdtvyzJ+ZD8oQ30CwPNkPFpT3lCH78Quq269PRFvxtWOFS2t4gS4yEQgwIwN9jzT0WLhLK9HFs9/4+6kQEpHe0BrFoGKyAhtUvejj8elLJnb+3vX+zkQVFbKwWMyJsGKH1dcdpR8k6Q4XBYe9zDo+jJw34LFo5h+oX5ImwDoLc5VxvbwT7lDpBcAXygP96rTIvCh9HGQkAZSgLyI5UrjAmv1nV6PpWc8DooMxyMzFpjIzkKYd+juC6GYIbh1Vnb45lgJns42irOzYoyVGL+dxZ27m0/0lmxSW5t7UCAwEAAQ==

五、Java 代码示例 ​

1. 签名与验签工具类 (SignUtil.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 请求头中的签名 sign
     * @param publicKey 公钥字符串 (Base64)
     * @return 验签是否通过
     */
    public static boolean checkSign(String param, String sign, String publicKey) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            signature.initVerify(keyFactory.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 私钥字符串 (Base64)
     * @return Base64 签名串
     */
    public static String sign(String param, String privateKey) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            signature.initSign(keyFactory.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;
    }
}

2. 发起请求示例 ​

java
import com.google.gson.Gson;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import java.util.HashMap;
import java.util.Map;

public class RequestDemo {
    public static void main(String[] args) {
        String url = "https://api.example.com/payin/create";
        String merchantNo = "M1639466186292";
        String privateKey = "YOUR_PRIVATE_KEY_BASE64";

        Map<String, Object> map = new HashMap<>();
        map.put("timestamp", System.currentTimeMillis());
        map.put("merchantOrderNo", "ORDER_" + System.currentTimeMillis());
        map.put("amount", "200.00");
        map.put("payType", "BKASH"); // 支付通道类型:BKASH 或 NAGAD
        map.put("notifyUrl", "https://yourdomain.com/payin/notify");

        Gson gson = new Gson();
        String body = gson.toJson(map);
        String sign = SignUtil.sign(body, privateKey);

        HttpResponse<String> response = Unirest.post(url)
                .header("Content-Type", "application/json; charset=utf-8")
                .header("merchantNo", merchantNo)
                .header("sign", sign)
                .body(body)
                .asString();

        System.out.println("HTTP Status: " + response.getStatus());
        System.out.println("Response Body: " + response.getBody());
    }
}

3. RSA 密钥对生成示例 ​

商户接入前需生成一对 RSA-4096(或 RSA-2048)密钥,并将生成的公钥提供给平台配置:

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 KeyPairGenDemo {
    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("--- 商户公钥 (提供给平台) ---");
        System.out.println(publicKeyBase64);

        PrivateKey privateKey = keyPair.getPrivate();
        String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
        System.out.println("--- 商户私钥 (商户本地妥善保管) ---");
        System.out.println(privateKeyBase64);
    }
}

六、商户 RSA 密钥生成示例 ​

6.1 在线生成工具 ​

相关工具链接:

生成与配置说明:

  1. 生成密钥对:使用密钥生成工具生成密钥对,长度必须是 1024bit、2048bit 或 4096bit,格式必须是 PKCS#8。
  2. 去除换行并上传公钥:将生成密钥对中的公钥,去除换行后复制,上传到商户后台。不要包含 -----BEGIN *** KEY----- 与 -----END *** KEY-----。
  3. 保管私钥:公钥上传完成后,请妥善保管私钥,切勿外泄。
  4. 技术支持:如对接过程遇到加解密、签名异常等问题,可以发送请求参数至对接群里,并艾特我们客服或者技术人员。
  5. 回调验签说明:对于平台回调签名,请使用平台公钥进行解密验证,切勿使用商户公钥(您自行生成的公钥)。

WARNING

回调通知是由平台发送给商户的,因此商户验证回调签名时必须使用平台公钥。商户自身公钥仅用于平台验证商户主动发起的 API 请求。

孟加拉支付网关 API 接口规范