# 第三方订单回退

接口地址:http://gateway--cnki--net--https.cnki.mdjsf.utuvpn.utuedu.com:9000/openx/jssdk/order/v1/rollback

请求方式:POST

请求数据类型:application/json

响应数据类型:*/*

接口描述: 第三方订单回退

请求示例:

{
    "appId": "1757*****8985",
    "payExtra": "GIdO0im4RP****G63soG2xBzLvx8GG++cOql77HeyCU="
}

请求参数:

参数名称 参数说明 请求类型 是否必须 数据类型
  appId 第三方应用在研学开放平台申请的应用ID body true string
  payExtra 订单信息,包含订单详编码的加密字符串,生成方式见下文备注。 body true string
Authorization 接口请求的凭证,获取方式详见:知网研学开放平台文档-认证中心-客户端模式获取JWT (opens new window) header true string
Content-Type application/json header true string

注意事项:Authorization参数是携带在请求的header中,格式示例(注意Bearer 后有空格):

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCaWF...

备注:支付订单主体payExtra生成规则如下:

order_no使用键值对的格式(即key=value)拼接成字符串,结果类似:order_no=dsfzf20250907,之后对拼接后的字符串进行AES加密。

字段 释义 类型 是否必须
order_no 支付订单编号 String

加密的示例代码如下(秘钥为开发者在研学开放平台申请的ApiKey):

/**
 * 加密Map
 *
 * @param data 要加密的数据
 * @return 加密后的字符串
 * @throws Exception
 */
public static String encryptMap(Map<String, String> data, String secretKey) throws Exception {
    // 元素排序
    Map<String, String> sortedData = new TreeMap<>(data);
    StringBuilder dataToEncrypt = new StringBuilder();
    for (Map.Entry<String, String> entry : sortedData.entrySet()) {
        dataToEncrypt.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
    }
    // 去掉最后一个多余的&
    if (dataToEncrypt.length() > 0) {
        dataToEncrypt.setLength(dataToEncrypt.length() - 1);
    }
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    byte[] encryptedBytes = cipher.doFinal(dataToEncrypt.toString().getBytes(StandardCharsets.UTF_8));
    return Base64.getEncoder().encodeToString(encryptedBytes);
}

 /**
     * 解密Map
     *
     * @param encryptedData 加密后的字符串
     * @return 解密后的Map
     * @throws Exception
     */
public static Map<String, String> decrypt(String encryptedData, String secretKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    byte[] decodedBytes = Base64.getDecoder().decode(encryptedData);
    byte[] decryptedBytes = cipher.doFinal(decodedBytes);
    String decryptedString = new String(decryptedBytes, StandardCharsets.UTF_8);

 Map<String, String> decryptedMap = new TreeMap<>();
    String[] pairs = decryptedString.split("&");
 for (String pair : pairs) {
        int idx = pair.indexOf("=");
     if (idx > 0) {
            decryptedMap.put(pair.substring(0, idx), pair.substring(idx + 1));
     }
    }
    return decryptedMap;
}

public static void main(String[] args) {
    Map<String, String> data = new HashMap<>();
    data.put("order_no", "dsfzf20250907");
    try {
        String encrypt = encryptMap(data, "Nmq******H0Rp");
        System.out.println("加密结果:" + encrypt);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

加密算法:AES

工作模式:ECB

填充方式:PKCS5Padding

以上是Java语言实现的加密算法,其它语言加密请保证相同的算法、工作模式、填充方式。

注意编码格式为:UTF_8

请妥善保存应用秘钥ApiKey

响应状态:

状态码 说明
200 OK
500 系统异常!
400505 应用不存在!
400523 xxxx参数不能为空!
400533 第三订单不存在!
400531 订单信息解密失败!
400529 三方支付信息缺失!
400534 第三方订单未支付!

响应参数:

参数名称 参数说明 类型 schema
code 接口返回状态码 integer(int32) integer(int32)
content 接口返回数据 object
count 接口返回数据条数,用于分页查询 integer(int32) integer(int32)
message 接口返回信息 string
success 接口返回是否成功 boolean
total 接口返回数据条数,用于分页查询 integer(int32) integer(int32)

响应示例:

{
    "success": true,
    "message": "SUCCESS",
    "content": null,
    "count": null,
    "total": null,
    "code": 200
}