本文为您介绍X模式接口使用流程。

使用步骤

  1. 请联系阿里云运营或运维工程师,先完成X模式打标,再使用号码隐私保护控制台
  2. 根据本文档完成开发。
  3. 请将接口地址提供给阿里云运维工程师进行配置。运维工程师在配置完成后会将签名密钥提供给您。
  4. 请联系阿里云运维工程师配合完成接口调试。

接口公共参数

  • 公共入参:
    入参类型是否必填描述
    signatureMethodString签名算法。取值范围:HMAC-SHA1
    signatureNonceString签名唯一随机数。用于防止网络重放攻击。Java语言建议用:java.util.UUID.randomUUID()生成。
    signatureVersionString签名算法版本。固定取值:1.0
    signatureString请求签名,即最终生成的签名结果值。如何生成请求签名,请参见参数签名说明
    timestampString请求的时间戳。按照ISO8601 标准表示,并需要使用UTC时间,格式为yyyy-MM-ddTHH:mm:ssZ。示例:2018-01-01T12:00:00Z表示北京时间20180101200000秒。
    formatString返回参数的语言类型。固定取值:JSON
  • 公共出参:
    出参类型必填描述
    codeString状态码。返回OK表示请求成功。
    messageString请求结果描述。
    modelString返回的业务参数。具体结构见业务接口定义。

参数签名说明

  • 公共入参(signature除外)和业务入参(参数值为空除外)按参数名升序排序,参数名和参数值以等于号(=)连接,每对参数以and(&)连接。对参数名、参数值执行UrlEncode编码,生成待签名字符串encryptStr。
  • 计算字符串encryptStr的签名。
    1. 先将字符串encryptStr执行UrlEncode编码,采用HmacSHA1算法+Base64,字符采用UTF-8编码。
    2. 再将计算的结果执行UrlEncode得到请求中的signature签名结果值。(验签的Java代码示例片段,请参见附录。)

呼叫控制查询接口

  • 业务入参:
    入参类型是否必填描述
    callNoString主叫号码。
    secretNoString隐私号码。
    extensionString分机号,适用于输入分机的场景。
    recordTypeString呼叫类型。取值:
    • SMS:短信。
    • CAL:语音。
    callTimeString呼叫时间,格式为yyyyMMddHHmmss。
    callIdString呼叫ID。
  • 业务出参:
    出参类型必填描述
    controlOperateString呼叫控制操作类型。取值:
    • CONTINUE:接续另一端。
    • REJECT:拒绝接续另一端。
    • IVR:主叫播放语音。
    controlMsgString无绑定关系时传NO_SUBS_EXIST。
    subsIdString绑定关系ID。
    说明 此处只能填写数字,若没有可以传0。
    callNoPlayCodeString主叫放音编码。
    说明
    • 必须和号码隐私平台编码保持一致。在控制台上上传审核才能使用。提供185、187两个默认编码。
    • controlOperate=CONTINUE时必填。
    callTypeString呼叫类型。取值:
    • MASTER:主叫(A->X)。
    • CALLED:被叫。
    • CALLED_REJECT:被叫拦截。
    • SMS_SENDER:短信发送(A->X)。
    • SMS_RECEIVER:短信接收。
    • SMS_REJECT:短信拦截。
    calledNoString被叫号码。
    说明controlOperate=CONTINUE时必填。
    calledDisplayNoString被叫号显只能是A号码或X号码。不能是其他号码,否则默认为X号码。
    needRecordBoolean是否录音。取值:
    • true:录音。
    • false:不录音。
    recTypeString录音格式,目前只支持MP3。
    smsChannelString短信设置。
    • SMS_NORMAL_SEND:正常转发。
    • SMS_INTERCEPT:短信托收。
    • SMS_SMART:智能短信。
    • SMS_DROP:短信丢弃。
    说明 为空时以控制台号池配置为准。
    outIdString外部ID,话单中返回。
  • 示例:
    • 接口请求地址:
      http://127.0.0.1:8000/queryCallControl?signature=%2Fhg7OnsiNmH6xDvR1aJudlQatH****&callId=17679476805054159279721******&callNo=1381111****&callTime=20200622114011&format=JSON&recordType=SMS&secretNo=1391111****&signatureMethod=HMAC-SHA1&signatureNonce=4c04a80e-9320-4519-9327-c5e60b21****&signatureVersion=1.0&timestamp=2020-06-22T03%3A40%3A11Z
    • 返回结果:
      {
         "code":"OK",
         "message":"OK",
         "model":{
             "controlOperate":"CONTINUE",
             "subsId":"9081",
             "callNoPlayCode":"185",
             "calledNoPlayCode":"185",
             "callType":"SMS_SENDER",
             "calledNo":"1390000****",
             "calledDisplayNo":"1391111****",
             "needRecord":true,
             "recType":"mp3",
             "smsChannel":"SMS_SMART",
             "outId":"9089"
         }
      }

附录

代码示例片段:
public static boolean signParams (String signature, String signatureMethod, String signatureNonce,
                                      String signatureVersion, String timestamp, String format,
                                      Map<String, String> callParams) throws Exception {
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        // 这里一定要设置GMT时区
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
        Date timeDate  = df.parse(timestamp);

        java.util.Map<String, String> paras = new java.util.HashMap<>();
        // 1. 系统参数
        paras.put("signatureMethod", signatureMethod);
        paras.put("signatureNonce", signatureNonce);
        paras.put("signatureVersion", signatureVersion);
        paras.put("timestamp", df.format(timeDate));
        paras.put("format", format);

        // 2. 业务参数
        paras.putAll(callParams);

        // 3. 去除签名关键字Key
        paras.remove("signature");

        // 4. 参数KEY排序
        java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>(paras);

        // 5. 构造待签名的字符串
        java.util.Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext()) {
            String key = it.next();
            if (StringUtils.isNoneBlank(paras.get(key))) {
                sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(
                    specialUrlEncode(paras.get(key)));
            }
        }
        // 去除第一个多余的&符号
        // signatureKey 由阿里云提供,使用此密钥对参数加密,确保HTTP传输过程的数据安全
        String sign = sign(signatureKey, specialUrlEncode(sortQueryStringTmp.substring(1)));
        // 6. 签名最后也要做特殊URL编码
        String signatureResult = specialUrlEncode(sign);
        // 最终打印出合法GET请求的URL
        return signatureResult.equals(specialUrlEncode(signature));
    }

    /**
     * encode编码
     * @param value
     * @return
     * @throws Exception
     */
    private static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8");
    }

    /**
     * 加密
     * @param signatureKey
     * @param stringToSign
     * @return
     * @throws Exception
     */
    private static String sign(String signatureKey, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(signatureKey.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }