抖音开放平台Logo
开发者文档
“/”唤起搜索
控制台
  • 生活服务商家应用 OpenAPI SDK 总览
  • 接入前准备
  • API接口
  • 通用接口
  • 餐饮
  • 大交通
  • 酒旅
  • 酒店通用错误码
  • 酒店行业日历房解决方案
  • 酒店日历房常见枚举值列表
  • 酒店静态信息匹配/创建/更新能力
  • 酒店静态信息自助获取能力
  • 物理房型静态信息匹配/创建/更新
  • 营销规则价格推送
  • 物理房型上下架能力
  • 主动拉取价量态
  • 营销退出报名
  • 营销价量态拉取
  • 营销规则推送
  • 营销库存推送
  • 日历房线上开票
  • 开票结果通知
  • 酒店日历房线上开票SPI
  • 日历房上下架能力
  • 营销规则价格模式推送
  • 营销查询
  • 入住/离店状态同步能力
  • 日历房交易正向
  • 酒店会员管理
  • 日历房交易逆向
  • 售卖房型创建/更新能力
  • 物理房型静态信息自助获取能力
  • 房价/房态/房量更新
  • 代理商-酒店静态信息自助获取
  • 酒店账单详情查询
  • 酒店行业新预售券解决方案
  • 度假行业解决方案
  • 景区行业日历票解决方案
  • 景区团购三方码方案
  • 综合
  • 能力
  • 历史版本文档(不推荐)
  • 基本信息

    名称描述
    暂无数据

    请求参数

    响应参数

    切换单列布局

    解密方法

      1.根据 ClientKey 找到 ClientSecret,将 ClientSecret 向左右使用字符补齐 32 位/裁剪至 32 位,
      a.补齐:补位字符:#, 先补左侧再补右侧再补左侧······直到补满 32 位。
      b.裁剪:先裁剪左侧再裁右侧再裁左侧······直到剩余 32 位。
      c.(正常不需要补齐,secret 默认为 32 位,此举是为了以防万一)
      2.将 ClientSecret 作为 Key, 右侧 16 位为向量 IV
      3.将密文进行 base64 解码。
      4.使用 AES-256-CBC 模式解密解码后的密文,对齐使用 PKCS5Padding 方式
    Golang SDK
    package utils import ( "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" ) // AesDecrypt 解密函数 // encryptedStr:base64后的密文 // secret:appid/client_key对应的client_secret // return: []byte 明文 func AesDecrypt(encryptedStr string, secret string) ([]byte, error) { // 加密字符串进行base64解码 decodeBytes, err := base64.StdEncoding.DecodeString(encryptedStr) if err != nil { return nil, err } key, iv := parseSecret(secret) block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() blockMode := cipher.NewCBCDecrypter(block, iv[:blockSize]) origData := make([]byte, len(decodeBytes)) blockMode.CryptBlocks(origData, decodeBytes) origData = PKCS5UnPadding(origData) return origData, nil } // parseSecret 将secret解析为key和iv func parseSecret(secret string) ([]byte, []byte) { // secret对齐为32位 secret = cutSecret(secret) secret = fillSecret(secret) key, iv := secret, secret[16:] return []byte(key), []byte(iv) } func fillSecret(secret string) string { if len(secret) >= 32 { return secret } rightCnt := (32 - len(secret)) / 2 leftCnt := 32 - len(secret) - rightCnt var byt bytes.Buffer byt.Write(bytes.Repeat([]byte("#"), leftCnt)) byt.WriteString(secret) byt.Write(bytes.Repeat([]byte("#"), rightCnt)) return byt.String() } func cutSecret(secret string) string { if len(secret) <= 32 { return secret } rightCnt := (len(secret) - 32) / 2 leftCnt := len(secret) - 32 - rightCnt return secret[leftCnt: 32+leftCnt] } func PKCS5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)] }
    Java SDK
    package com.douyin.open.goodlife; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class SignUtil { /* * appid/client_key对应的client_secret TODO 这里换成服务商的appsecret */ private static final String secret = "12345678901234566543210987654321"; private static final String key; private static final String iv; static { key = parseSecret(secret); iv = key.substring(16); } /** * @Description AES解密 * @param data base64后的密文 * @return 明文 */ public static String decryptAES(String data) throws Exception { try { byte[] encrypted1 = decode(data);//先用base64解密 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original); return originalString.trim(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * base64编码 */ public static String encode(byte[] byteArray) { return new String(Base64.getEncoder().encode(byteArray)); } /** * base64解码 */ public static byte[] decode(String base64EncodedString) { return Base64.getDecoder().decode(base64EncodedString); } private static String parseSecret(String secret) { secret = fillSecret(secret); secret = cutSecret(secret); return secret; } private static String cutSecret(String secret) { if (secret.length() <= 32) { return secret; } int rightCnt = (secret.length() - 32) / 2; int leftCnt = secret.length() - 32 - rightCnt; return secret.substring(leftCnt, 32 + leftCnt); } private static String fillSecret(String secret) { if (secret.length() >= 32) { return secret; } int rightCnt = (32 - secret.length()) / 2; int leftCnt = 32 - secret.length() - rightCnt; StringBuilder sb = new StringBuilder(""); for (int i = 0; i < leftCnt; i++) { sb.append('#'); } sb.append(secret); for (int i = 0; i < rightCnt; i++) { sb.append('#'); } return sb.toString(); } }