通讯模式

接口如无特殊要求均采用HTTP POST方式提交。

接口地址

参数说明

参数类型 简称 参数说明
整数 I 整数,十亿以内,简称是大写INT的首字母
日期 D 使用yyyyMMdd(如20210315)的格式
日期时间 T 使用yyyyMMddHHmmss(如20210315155012)的格式
字符串 S 任意合法的字符串,如S(16),表示字符串长度不超过16位
枚举值 E 见具体参数描述
浮点数 F 不超过10亿,小数点后最多7位
复合类型 C 数组内部嵌套键值对
布尔类型 B 布尔类型,true:是,false:否

签名和验签

  • 所有请求和返回报文都包含签名参数,接收方务必检查签名的正确性,以保证业务数据合法安全。
  • 签名和验签支持国密(SM2)和RSA两种方式,签名结果需要转换成16进制字符串。
  • RSA签名使用标准签名算法”SHA256withRSA”,密钥长度2048位。
  • RSA签名步骤:明文转json字符串->RSA->HEX(16)->密文(signStr)

敏感字段解密

手机号等敏感字段要求加密的需使用3DES解密,其中包含获取3DES密钥,之后才能用3des进行解密

  • 获取3DES密钥,需使用商户私钥解密数字信封字段(dgtlEnvlp)获取密钥
  • 3DES解密:使用获取的密钥进行3DES解密

幂等支持

本文档中部分接口支持幂等,当同一个商户订单号outTradeNo多次调用时,遵循如下:

  • 同一个outTradeNo代表同一笔交易,outTradeNo需保证全局唯一
  • 如之前已经返回成功,再次调用仍然会返回成功,不会重复处理交易
  • outTradeNo只能包含字母、数字、下划线 _

特殊说明

本文档中部分接口字段名前包含中划线(-),当出现中划线时,表示该字段为上一级字段的叶子字段,即代表父字段为一个集合字段(JSON数组或JSON格式)

3DES解密说明

需使用商户私钥解密数字信封(dgtlEnvlp)字段得到3DES解密的密钥key

  • 解密前需对加密数据和密钥key转为btye[]数组,java和php参考以下解密示例

JAVA

    public static byte[] hex2Bytes(String source) {
        byte[] sourceBytes = new byte[source.length() / 2];
        for (int i = 0; i < sourceBytes.length; i++) {
            sourceBytes[i] = (byte) Integer.parseInt(source.substring(i * 2, i * 2 + 2), 16);
        }
        return sourceBytes;
    }

    public static String threeDesDecrypt(String data, String keyStr) throws Exception {
        try {
            byte[] src = hex2Bytes(data);
            byte[] keybyte = hex2Bytes(keyStr);
            // 生成密钥
            byte[] key = new byte[24];
            if (keybyte.length < key.length) {
                System.arraycopy(keybyte, 0, key, 0, keybyte.length);
            } else {
                System.arraycopy(keybyte, 0, key, 0, key.length);
            }
            SecretKey deskey = new SecretKeySpec(key, "DESede");
            // 解密
            Cipher c1 = Cipher.getInstance("DESede/ECB/PKCS5Padding");
            c1.init(Cipher.DECRYPT_MODE, deskey);
            byte[] decryptByte = c1.doFinal(src);
            return new String(decryptByte);
        } catch (Exception e) {
            throw new Exception("3DES解密发生错误", e);
        }
    }

PHP

<?php

class TripleDES
{
    private const CIPHER_METHOD = 'DES-EDE3';
    private $key;

    public function __construct($key)
    {
        // 3DES密钥需要24字节(192位),确保密钥为48个十六进制字符(24字节)
        $this->key = hex2bin($key);
        if ($this->key === false || strlen($this->key) !== 24) {
            throw new InvalidArgumentException('Invalid 3DES key provided. Key must be 48 hexadecimal characters.');
        }
    }

    public function encrypt($data)
    {
        // 使用3DES ECB模式进行加密,PKCS5Padding填充
        $paddedData = $this->pkcs5_pad($data);
        $encrypted = openssl_encrypt($paddedData, self::CIPHER_METHOD, $this->key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
        return bin2hex($encrypted);
    }

    public function decrypt($data)
    {
        $data = hex2bin($data);
        if ($data === false) {
            throw new InvalidArgumentException('Invalid encrypted data provided.');
        }
        // 使用3DES ECB模式进行解密
        $decrypted = openssl_decrypt($data, self::CIPHER_METHOD, $this->key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
        return $this->pkcs5_unpad($decrypted);
    }

    private function pkcs5_pad($text, $blocksize = 8)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }

    private function pkcs5_unpad($text)
    {
        $pad = ord($text[strlen($text) - 1]);
        if ($pad > strlen($text) || strspn($text, chr($pad), strlen($text) - $pad) !== $pad) {
            return false;
        }
        return substr($text, 0, -1 * $pad);
    }
}

// 测试示例
try {
    $key = "8c5dd9b9235180a77c9298f273fe67e08c5dd9b9235180a7";
    $tripleDES = new TripleDES($key);

    $originalData = "This is a secret message.";
    $encryptedData = $tripleDES->encrypt($originalData);
    $decryptedData = $tripleDES->decrypt($encryptedData);

    echo "原始数据: " . $originalData . PHP_EOL . "<br>";
    echo "加密数据: " . $encryptedData . PHP_EOL . "<br>";
    echo "解密数据: " . $decryptedData . PHP_EOL . "<br>";
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

?>
作者:xiaofeng  创建时间:2025-03-25 16:45
最后编辑:xiaofeng  更新时间:2025-04-24 15:18