Skip to content

开发者接入指南


Hi ,云从用户您好,欢迎使用云从云服务平台,以下内容是您接入服务的一些基本介绍,希望您能够在这里找到适合您业务的技术能力,感谢您的使用!

An image

1. 注册成为开发者

两步完成账号的基本注册与企业实名认证

STEP1 :点击云从公有云平台导航右侧的 注册,输入用户名和密码,并对用户的手机号码进行短信验证码验证,注册完成之后即可进入到云从公有云开发者后台。

STEP2 :首次使用,登录后将会进入企业实名认证页面,首先需要绑定使用账号的联系人信息,并绑定关联的邮箱,其次需要填写相关信息完成企业实名制认证。由云从工程师审核通过后系统自动发送短信及邮件告知。

2. 服务市场API申请授权

企业实名制审核完成后,成功登录到云从公有云用户后台,您需要在服务市场中选择服务并对想要调用的API申请授权,申请完成后,运营人员将第一时间进行审核,仅审核通过的API可进行调用。

STEP1 :在服务市场选择服务,点击 立即体验 进入服务详情;

An image

STEP2 :在服务详情切换到 可用API服务列表,点击 申请授权并填写申请说明后则提交申请成功。可申请不同服务的多个API;

An image

STEP3 :申请成功后可在应用中心-API授权查看API审核进度,审核通过可进行下一步操作。

An image

3. 创建应用

创建应用成功系统自动生成密钥。

STEP1 :在[应用中心-应用管理]点击创建应用

An image

STEP2 :维护应用信息,维护应用关联的API,仅已授权审核通过的API可被关联;

An image

STEP3 :打开应用详情,可查看系统给每个开发者应用生成的App Key、App Secret、sm2公钥和sm4密钥。一个应用对应一套密钥信息,请妥善保管密钥信息,避免遗失或泄露。

An image

完成以上步骤,开发者就可以通过代码进行开放能力调用。

4. 能力调用

云从公有云平台使用OAuth2.0授权调用开放API,开发者调用开放能力前,需要先使用申请的App Key、App Secret获取令牌access_token,然后携带access_token调用开放能力。

能力调用域名:https://api-ai.cloudwalk.com

  • 注意: 请额外依赖下述JAR包:

bcprov-jdk15to18

4.1. Token获取

接口说明:

用于获取访问云从公有云平台开放能力的身份令牌,为保障系统安全性,开发者每次请求都是独立的,即每次请求需要先来获取令牌。

调用流程:

An image

请求 URL:

/sso/oauth/token

请求参数

  • method: POST

  • 请求头参数:"Content-Type":"application/x-www-form-urlencoded"

  • 表单参数:

参数名称必填数据类型长度参数描述
clientIdString1-32客户端ID,对应创建应用生成的App Key
clientSecretString1-255加密后的客户端密钥,使用创建应用生成的App Secret和SM2公钥进行加密
scopeString1-32权限范围,固定值为scope

请求示例:

        Content-Type: application/x-www-form-urlencoded
              scope:scope
              clientId:xxxxxxxx
              clientSecret:xxxxxxxxxx

响应参数

参数名称数据类型长度参数描述
access_tokenString1-32访问令牌
token_typeString1-32令牌类型 bearer
expires_inLong1-32令牌有效期,单位:秒,默认12小时
scopeString1-32授权范围 返回scope

响应示例:

{
    "access_token": "xxxxxxxxxxxxxx",
    "token_type": "bearer",
    "expires_in": 170932,
    "scope": "scope"
}

示例代码(JAVA)

package cloudwalk.kaleidoscope;

import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.crypto.engines.SM2Engine;

import java.util.HashMap;
import java.util.Map;

public class tokenTest {

    /**
     * sm2-sm4加密算法的应用详情中的App Key和App Secret、SM2公钥
     */
    public static String APP_KEY = "xxxxxxxx";
    public static String APP_SECRET = "xxxxxxxxxxxxxxxx";
    public static String SM2_PUB = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
    /**
     * 调用地址
     */
    public static String HTTP_ADDRESS = "https://ai.cloudwalk.cn";
    /**
     * Token管理请求路径
     */
    private static final String TOKEN_URL = HTTP_ADDRESS + "/sso/oauth/token";

    public static void main(String[] args) throws Exception {
        getToken();
    }

    private static String sm2Encrypt(String plain) {
        SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams("04".concat(SM2_PUB)));
        sm2.setMode(SM2Engine.Mode.C1C2C3);
        return sm2.encryptHex(plain, KeyType.PublicKey);
    }


    private static String getToken() {
        Map<String, String> paramMap = new HashMap<>(2);

        paramMap.put("clientId", APP_KEY);
        paramMap.put("clientSecret", sm2Encrypt(APP_SECRET));

        String result = HttpUtil.post(TOKEN_URL, JSON.toJSONString(paramMap));
        System.out.println(result);

        JSONObject object = JSON.parseObject(result);
        return object.getString("access_token");
    }

}

内容输出:

{"access_token":"xxxxxxxx","token_type":"bearer","expires_in":172342,"scope":"scope"}

4.2. 接口调用

获取Token成功后,开发者调用开放能力接口,需要携带token,使用token获取的access_token,在请求头中设置Authorization参数,参数值为:Bearer + token。

同时,云从公有云平台使用国家密码局认定的国产密码算法进行传输加解密及签名认证,以保障数据安全性。 传入报文使用SM3算法计算摘要,SM2算法生成签名,使用SM4算法加密。接口返回报文同样使用SM4算法加密,调用方需使用密钥进行解密。具体调用流程及示例代码如下。

调用流程:

An image

参数解释:

  • nonceStr: 随机字符串,用于生成签名,用户需自行生成

  • timestamp: 时间戳,用于生成签名

  • digest: 对业务参数明文计算的摘要

  • workKey: 随机生成的16位长度的sm4算法的对称密钥

  • keyCipher: workKey密文

  • contentCipher: 业务参数密文

示例代码(JAVA)

以联网核查接口为例,示例代码如下

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.crypto.symmetric.SM4;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.bouncycastle.crypto.engines.SM2Engine;

import java.nio.charset.StandardCharsets;
import java.util.*;

public class InterfaceUseTest {

    
    /**
     * sm2公钥
     */
    public static String SM2_PUB = "xxxxxxxxxxxxxxxx";
    /**
     * sm4密钥
     */
    public static String SM4_SECRET = "xxxxxxxx";

    public static String HTTP_ADDRESS = "https://ai.cloudwalk.cn";

    /**
     * 身份令牌
     */
    private static String accessToken = "xxxxxxxxx";
    
    /**
     * 请求路径
     */
    private static final String URL = HTTP_ADDRESS + "/ai-cloud-cweis/netCheck/checkCIdAndName";
    public static void main(String[] args) throws Exception {
     
        checkIdNameSm(accessToken, "张三", "123");
    }

   
    private static void checkIdNameSm(String token, String name, String id) {


        // 随机字符串,用于生成签名
        String nonceStr = UUID.fastUUID().toString(true);
        System.out.println("nonceStr:" + nonceStr);

        //时间戳,用于生成签名
        long timestamp = System.currentTimeMillis();
        System.out.println("timestamp:" + timestamp);

        //业务参数
        Map<String, Object> busMap = new HashMap<>();
        busMap.put("cId", id);
        busMap.put("cName", name);

        String busFlowId = RandomUtil.randomString(16);
        System.out.println("busFlowId:" + busFlowId);
        busMap.put("busFlowId", busFlowId);

        Map<String, Object> signMap = new HashMap<>(busMap);
        Map<String, Object> sortedMap = sortByKey(signMap);

        //计算摘要
        String digest = sm3Digest(JSON.toJSONString(sortedMap), nonceStr);
        System.out.println("digest:" + digest);

        //随机生成16位长度的workKey作为sm4的对称密钥
        String workKey = genSm4Key();
        System.out.println("workKey:" + workKey);

        // 进行sm4加密
        String contentCipher = sm4Encrypt(JSON.toJSONString(busMap), workKey);
        System.out.println("contentCipher:" + contentCipher);

        // 对workKey进行非对称sm2加密
        String keyCipher = sm2Encrypt(workKey);
        System.out.println("keyCipher:" + keyCipher);

        Map<String, Object> finalMap = new HashMap<>();
        finalMap.put("contentCipher", contentCipher);
        finalMap.put("keyCipher", keyCipher);
        finalMap.put("digest", digest);
        finalMap.put("timestamp", timestamp);
        finalMap.put("nonceStr", nonceStr);

        // 创建一个POST请求
        HttpRequest request = HttpUtil.createPost(URL);

        // 设置请求头参数
        request.header("Content-Type", "application/json");
        request.header("Authorization", "Bearer " + token);

        // 设置请求体
        request.body(JSON.toJSONString(finalMap));

        // 发送请求并获取响应
        String result = request.execute().body();

        SM4 sm4 = new SM4(HexUtil.decodeHex(SM4_SECRET));
        try {
            JSONObject object = JSON.parseObject(result);
            String data = object.getString("data");
            // 响应报文解密
            String plain = sm4.decryptStr(data);
            object.replace("data", JSON.parseObject(plain));
            System.out.println(object.toJSONString());
        } catch (Exception e) {
            System.out.println(result);
        }
    }
    
     public static Map<String, Object> sortByKey(Map<String, Object> map) {
        List<Map.Entry<String, Object>> list = new ArrayList<>(map.entrySet());
        list.sort(Map.Entry.comparingByKey());

        Map<String, String> result = new LinkedHashMap<>();
        for (Map.Entry<String, Object> entry : list) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    private static String sm2Encrypt(String plain) {
        SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams("04".concat(SM2_PUB)));
        sm2.setMode(SM2Engine.Mode.C1C2C3);
        return sm2.encryptHex(plain, KeyType.PublicKey);
    }

    private static String sm3Digest(String content, String nonceStr) {
        String salt = nonceStr.substring(nonceStr.length() - 16);
        SM3 sm3 = new SM3(salt.getBytes(StandardCharsets.UTF_8));
        return sm3.digestHex(content.getBytes(StandardCharsets.UTF_8));
    }

    private static String genSm4Key() {
        return UUID.fastUUID().toString(true).substring(8, 24);
    }

    private static String sm4Encrypt(String plain, String key) {
        SM4 sm4 = new SM4(Mode.ECB, Padding.PKCS5Padding, key.getBytes(StandardCharsets.UTF_8));
        return sm4.encryptHex(plain, StandardCharsets.UTF_8);
    }

}

如果您还有任何疑问,欢迎 联系我们!