[关闭]
@18612183942 2019-04-15T09:18:06.000000Z 字数 8698 阅读 49

酒店客户信息接口文档

文档版本 修订记录 修订人 修订时间
v1.0 文档创建 杨金奎 2019-04-15

1 文档简介

本文档定义了酒店客户信息与助销客平台的对接。

2 重要说明

2.1 测试账号

用户名:yangjinkui
密钥:12345678
版本号:v1.0
接口地址:http://service.zhuxiaoke.cn/Tongcheng/ProcessRequest/
测试产品:1000101639

2.2 加密算法

双方按约定的加密规则进行加密认证,防止数据篡改和伪造。
(1) 加密方式:MD5,32 位小写;
(2) 拼接接口中的公用参数,请求内容报文requestBody,user_key;
(3) 签名方法:
sign=md5(user_id+method+timestamp+version+requestBody+user_key) ;
(4)平台接收到请求报文后,按照相同的签名算法进行加密,将双方的 sign 进行比对,如果一致,则验证通。

2.3 传输方式

(1)接口采用http post方式,返回数据格式为json格式;
(2)统一采用utf-8编码。

2.4 数据交互规范

2.4.1 请求报文规范

公共参数 requestHead
参数名 说明 参数类型 是否必须
user_id 用户标识,由助销客提供 string
method 方法名 string
timestamp 时间戳,时间标准为 UTC,取当前请求时间时间格式为 2016/5/25 21:36:44 精确到秒然后转化为时间戳 int
version 版本号,根据接口版本传入 string
sign 签名,用于安全校验 string
业务参数 requestBody
参数名 说明 参数类型 是否必须
pageIndex 查询页索引 int
pageSize 查询数量 int
productNo 产品编号 string
sceneryNo 景区编号 string
签名示例

sign:计算方法 Md5(user_id+method+timestamp+version+requestBody+user_key)
明文(MD5 前):yangjinkuiGetProductInfo1458871246v1.0IPd5HD/HsjyMK7b1JALkopqhDlrgrV3zTEzyThrof28=12345678
签名(MD5 后-小写):2ba56cd0a986fe8e4d9815444594620b

requestBody 加密方式 (user_key=12345678)

将json格式的业务参数进行des加密,加密模式ECB充方式 PKCS7Padding,密钥为user_key。
传入requestBody参数 {"pageIndex": 1,"pageSize": 10}
传入Userkey参数12345678
Des(requestBody,userkey)= IPd5HD/HsjyMK7b1JALkopqhDlrgrV3zTEzyThrof28

请求示例
 {
    "requestHead": {
        "user_id": "yangjinkui",
        "method": "GetProductInfo",
        "timestamp": 1458871246,
        "version": "v1.0",
        "sign": "2ba56cd0a986fe8e4d9815444594620b"
    },
    "requestBody": "IPd5HD/HsjyMK7b1JALkopqhDlrgrV3zTEzyThrof28="
}

2.4.2 响应报文规范

公共参数 responseHead
参数名 说明 参数类型 是否必须
res_code 响应码 string
res_msg 响应消息 string
timestamp 时间戳,时间标准为 UTC,取当前请求时间 int
业务参数 responseBody
参数名 说明 参数类型 是否必须
totalCount 产品总数量 long
productList 产品列表 object[]
responseBody 加密方式 (user_key=12345678)

将json格式的业务参数进行des加密,密钥为user_key。

responseBody: {
    "totalCount": 1,
    "productList": [
        {
            "productNo": "Test01",
            "productName": "测试产品 01",
            "retailPrice": 5000,
            "webPrice": 4700,
            "contractPrice": 4300,
            "sceneryNo": "",
            "sceneryName": "",
            "payType": 2,
            "beginDate": "2016-05-01",
            "endDate": "2016-06-11",
            "shieldDate": "",
            ......
        }
    ]
}
响应示例
{
    "responseHead": {
        "res_code": "1000",
        "res_msg": "成功",
        "timestamp": 1529979752
    },
    "responseBody": "des加密字符串,需解密"
}

3 酒店接口

3.1 推送酒店客户信息接口(平台提供)

方法名:PushHotelMember
调用方:酒管系统
响应方:助销客开放平台
接口说明:酒管系统调用此接口向助销客平台传送酒店客户信息。

3.1.1 业务请求参数

参数名 类型 描述 是否必传
hotelName string 酒店名称
name string 姓名
checkinDate string 入住日期(yyyy-MM-dd)
checkoutDate string 退房日期(yyyy-MM-dd)
roomName string 房间名称
idType int 证件类型(10 身份证 20 其他)
idNo string 证件号码
address string 详细地址
sex string 性别

3.1.2 业务响应参数

3.1.3 请求示例

{
    "requestHead": {
        "user_id": "yangjinkui",
        "method": "PushHotelMember",
        "timestamp": 1458871246,
        "version": "v1.0",
        "sign": "55af2e19e8efa6f7609c9a7e23903fc1"
    },
    "requestBody": {
        "hotelName": "城市之家酒店",
        "name":"代",
        "checkinDate":"2019-04-15",
        "checkoutDate":"2019-04-16",
        "roomName":"B201",
        "idType":10,
        "idNo":"110222199501016410",
        "address":"河北邯郸",
        "sex":"男"
    }
}
注:实际交互中 requestBody 是用 des 加密后的一串文本。
{
    "requestHead": {
        "user_id": "yangjinkui",
        "method": "PushHotelMember",
        "timestamp": 1458871246,
        "version": "v1.0",
        "sign": "55af2e19e8efa6f7609c9a7e23903fc1"
    },
    "requestBody": "h6MmkCEzEpQJDu+vvRJiFPGfM9oZ2Z0zsf1wuMLt34r48wJVk0gUHA=="
}

3.1.4 响应示例

  {
    "responseHead": {
        "res_code": "1000",
        "res_msg": "操作成功",
        "timestamp": 1530681252
    },
    "responseBody": ""
}
注:实际交互中 responseBody 是用 des 加密后的一串文本。
{
    "responseHead": {
        "res_code": "1000",
        "res_msg": "成功",
        "timestamp": 1530681252
    },
    "responseBody": ""
}

4 错误码列表

类型 错误码 说明
成功 1000 成功(如果贵方系统中订单已经生成或者已经取消就按正常返回)
推送酒店客户信息失败 6001 推送酒店客户信息失败
通用错误 5001 订单号不存在或已作废
通用错误 5002 余额不足
通用错误 5003 签名验证失败
通用错误 5004 数据出错或为空
通用错误 5005 合作方系统出错

5 des加密代码示例

5.1 C#版本

   /// <summary>
        /// des加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <param name="encryptKey"></param>
        /// <returns></returns>
        private string Encrypt(string encryptString, string encryptKey)
        {
            string returnValue;
            try
            {
                byte[] temp = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                byte[] byteEncrypt = Encoding.UTF8.GetBytes(encryptString);
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(Encoding.UTF8.GetBytes(encryptKey), temp), CryptoStreamMode.Write);
                cryptoStream.Write(byteEncrypt, 0, byteEncrypt.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Convert.ToBase64String(memoryStream.ToArray());
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return returnValue;
        }
        /// <summary>
        /// des解密
        /// </summary>
        /// <param name="decryptString"></param>
        /// <param name="decryptKey"></param>
        /// <returns></returns>
          public static string Decrypt(string decryptString, string decryptKey)
        {
            string returnValue;
            try
            {
                byte[] temp = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                DESCryptoServiceProvider des = new DESCryptoServiceProvider();
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.PKCS7;
                byte[] byteDecryptString = Convert.FromBase64String(decryptString);
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, des.CreateDecryptor(Encoding.UTF8.GetBytes(decryptKey), temp), CryptoStreamMode.Write);
                cryptoStream.Write(byteDecryptString, 0, byteDecryptString.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Encoding.UTF8.GetString(memoryStream.ToArray());
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return returnValue;
        }

5.2 JAVA版本

package com.afreon.util;

import java.io.IOException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
    /**
     * Description 根据键值进行加密
     * @param data 
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    public static String encrypt(String data, String key) throws Exception {
        byte[] bt = encrypt(data.getBytes("UTF-8"), key.getBytes("UTF-8"));
        String strs = new BASE64Encoder().encode(bt);
        return strs;
    }

    /**
     * Description 根据键值进行解密
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static String decrypt(String data, String key) throws Exception,
            Exception {
        if (data == null)
            return null;
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] buf = decoder.decodeBuffer(data);
        byte[] bt = decrypt(buf,key.getBytes("UTF-8"));
        return new String(bt, "UTF-8");
    }
    /**
     * Description 根据键值进行加密
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        // 生成一个可信任的随机数源
        SecureRandom sr = new SecureRandom();

        // 从原始密钥数据创建DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(key);

        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);

        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance(DES);

        // 用密钥初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

        return cipher.doFinal(data);
    }


    /**
     * Description 根据键值进行解密
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        // 生成一个可信任的随机数源
        SecureRandom sr = new SecureRandom();

        // 从原始密钥数据创建DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(key);

        // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);

        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(DES);

        // 用密钥初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

        return cipher.doFinal(data);
    }

5.3 PHP版本

<?php  
class Des  
{  
    private $key = "";  
        private $iv = "";  

    /** 
     * 构造,传递二个已经进行base64_encode的KEY与IV 
     * 
     * @param string $key 
         * @param string $iv 
     */  
    function __construct($key, $iv)  
    {  
        if (empty($key) || empty($iv)) {  
            echo 'key and iv is not valid';  
            exit();  
        }  
        $this->key = $key;  
        $this->iv = $iv;  
    }  

    /** 
     *加密 
     * @param <type> $value 
         * @return <type> 
         */  
        public function encrypt($value)  
    {  
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');  
            $iv = base64_decode($this->iv);  
            $value = $this->PaddingPKCS7($value);  
        $key = base64_decode($this->key);  
        mcrypt_generic_init($td, $key, $iv);  
            $ret = base64_encode(mcrypt_generic($td, $value));  
        mcrypt_generic_deinit($td);  
            mcrypt_module_close($td);  
        return $ret;  
    }  

    /** 
     *解密 
     * @param <type> $value 
         * @return <type> 
         */  
        public function decrypt($value)  
    {  
        $td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');  
            $iv = base64_decode($this->iv);  
            $key = base64_decode($this->key);  
            mcrypt_generic_init($td, $key, $iv);  
        $ret = trim(mdecrypt_generic($td, base64_decode($value)));  
            $ret = $this->UnPaddingPKCS7($ret);  
        mcrypt_generic_deinit($td);  
            mcrypt_module_close($td);  
        return $ret;  
    }  

    private function PaddingPKCS7($data)  
        {  
            $block_size = mcrypt_get_block_size('tripledes', 'cbc');  
            $padding_char = $block_size - (strlen($data) % $block_size);  
            $data .= str_repeat(chr($padding_char), $padding_char);  
            return $data;  
    }  

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

//使用  
$key = 'test1234';  
    $iv = 'test1234';  
$msg = '{"pageIndex":1,"pageSize":10,"productNo":"","sceneryNo":""}';  
    $des = new Des(base64_encode($key), base64_encode($iv));  
$rs1 = $des->encrypt($msg);  
    echo $rs1 . '<br />';  
$rs2 = $des->decrypt($rs1);  
    echo $rs2;  
?>
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注