| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.malk.rjk.Boot;
- import com.malk.rjk.server.RjkServer;
- import com.malk.server.common.McException;
- import com.smecloud.apigw.client.ApigwClient;
- import com.smecloud.apigw.model.ApiRequest;
- import com.smecloud.apigw.model.ApiResult;
- import com.smecloud.apigw.model.ApigwConfig;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.entity.StringEntity;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.util.EntityUtils;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.net.*;
- import java.nio.charset.StandardCharsets;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.util.*;
- import static com.smecloud.apigw.constant.HttpMethod.GET;
- @Slf4j
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = Boot.class)
- public class test {
- @Test
- public void testService() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
- Map<String, String> mes_params = push_app_authorize("300657", "9163551ef2e2a2cd2398dc05ec527132", "356919829745242112");//根据应用ID(Client ID),第三方实例ID调取实时
- if (mes_params.size() > 0) {
- String appSecret = mes_params.get("appSecret").toString();
- String domain = mes_params.get("domain").toString();
- if (domain != "" && appSecret != "" && domain != null && appSecret != null) {
- get_material("300657", domain, appSecret, "9163551ef2e2a2cd2398dc05ec527132");
- }
- }
- //
- // CookieStore cookieStore = new BasicCookieStore();
- // // 创建一个 Httpclient 实例
- // CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
- // HttpGet otherRequest = new HttpGet("https://api.kingdee.com/jdy/v2/bd/material");
- // otherRequest.setHeader("Content-Type", "300657");
- // otherRequest.setHeader("X-Api-ClientID", "application/json");
- // otherRequest.setHeader("X-Api-Auth-Version", "2.0");
- // otherRequest.setHeader("X-Api-TimeStamp", String.valueOf(System.currentTimeMillis()));
- // otherRequest.setHeader("X-Api-SignHeaders", "X-Api-TimeStamp,X-Api-Nonce");
- // otherRequest.setHeader("X-Api-Nonce", this.get_randomNumber());
- // otherRequest.setHeader("X-Api-Signature", get_app_signature("tcyhmh71","206bfff1ea61c4699f55ce895848c3e52a8dff02"));
- // otherRequest.setHeader("app-token", this.get_appToken());
- // otherRequest.setHeader("X-GW-Router-Addr", this.get_appToken());
- // CloseableHttpResponse otherResponse = httpclient.execute(otherRequest);
- }
- /**
- * 主动获取授权
- *
- * @return
- */
- public static Map<String, String> push_app_authorize(String clientId, String Secret, String outerInstanceId) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
- Map<String, String> mes_params = new TreeMap<>();
- String url = "https://api.kingdee.com/jdyconnector/app_management/push_app_authorize?outerInstanceId=" + outerInstanceId;
- HttpPost httpPost = new HttpPost(url);
- String TimeStamp = String.valueOf(System.currentTimeMillis());
- String randomNumber = get_randomNumber();
- /**
- * Signature加密
- */
- String QQFS = "POST";
- String path = "/jdyconnector/app_management/push_app_authorize";
- Map<String, String> params = new TreeMap<>(); // TreeMap 会自动按键的 ASCII 码排序
- params.put("outerInstanceId", outerInstanceId);
- String Signature = get_app_signature(Secret, QQFS, path, params, TimeStamp, randomNumber);//X-Api-Signature加密获取
- httpPost.setHeader("X-Api-ClientID", clientId);
- httpPost.setHeader("X-Api-Auth-Version", "2.0");
- httpPost.setHeader("X-Api-TimeStamp", TimeStamp);
- httpPost.setHeader("X-Api-Nonce", randomNumber);
- httpPost.setHeader("X-Api-SignHeaders", "X-Api-TimeStamp,X-Api-Nonce");
- httpPost.setHeader("X-Api-Signature", Signature);
- // 设置请求体(如果有)
- httpPost.setEntity(new StringEntity("", "UTF-8"));
- try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
- // 发送请求并处理响应
- HttpResponse response = httpClient.execute(httpPost);
- String responseBody = EntityUtils.toString(response.getEntity());
- JSONObject jsonObject = JSON.parseObject(responseBody);
- if (jsonObject.getString("code").equals("200")) {
- JSONArray dataArray = jsonObject.getJSONArray("data");
- // 假设JSON数组中只有一个对象,或者我们只关心第一个对象
- JSONObject dataObject = dataArray.getJSONObject(0);
- String appSecret = dataObject.getString("appSecret");
- String domain = dataObject.getString("domain");
- mes_params.put("appSecret", appSecret);
- mes_params.put("domain", domain);
- } else {
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return mes_params;
- }
- /**
- * 获取商品列表
- *
- * @return
- */
- public static String get_material(String clientId, String domain, String appSecret, String Secret) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
- String url = "https://api.kingdee.com/jdy/v2/bd/material";
- HttpGet httpGet = new HttpGet(url);
- String TimeStamp = String.valueOf(System.currentTimeMillis());
- String randomNumber = get_randomNumber();
- /**
- * Signature加密
- */
- String QQFS = "GET";
- String path = "/jdy/v2/bd/material";
- Map<String, String> params = new TreeMap<>(); // TreeMap 会自动按键的 ASCII 码排序
- String Signature = get_app_signature(Secret, QQFS, path, params, TimeStamp, randomNumber);//X-Api-Signature加密获取
- httpGet.setHeader("X-Api-ClientID", clientId);
- httpGet.setHeader("X-Api-Auth-Version", "2.0");
- httpGet.setHeader("X-Api-TimeStamp", TimeStamp);
- httpGet.setHeader("X-Api-Nonce", randomNumber);
- httpGet.setHeader("X-Api-SignHeaders", "X-Api-TimeStamp,X-Api-Nonce");
- httpGet.setHeader("X-Api-Signature", Signature);
- httpGet.setHeader("Content-Type", "application/json");
- httpGet.setHeader("app-token", get_appToken(appSecret));
- httpGet.setHeader("X-GW-Router-Addr", domain);
- try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
- // 发送请求并处理响应
- HttpResponse response = httpClient.execute(httpGet);
- String responseBody = EntityUtils.toString(response.getEntity());
- JSONObject jsonObject = JSON.parseObject(responseBody);
- System.out.println("jsonObject:" + jsonObject);
- String errcode = jsonObject.getString("errcode");
- if (errcode.equals("0")) {//判断有返回值
- JSONObject dataObject = jsonObject.getJSONObject("data");
- // 从data对象中获取rows数组
- JSONArray rowsArray = dataObject.getJSONArray("rows");
- // 循环遍历rows数组中的每个对象
- for (int i = 0; i < rowsArray.size(); i++) {
- JSONObject rowObject = rowsArray.getJSONObject(i);
- // 获取rowObject中的任意字段,例如name
- String shop_name = rowObject.getString("name");//商品名称
- String shop_number = rowObject.getString("number");//商品编码
- if (!shop_number.equals("")){
- }
- // 打印或其他处理
- System.out.println("商品名称: " + shop_name);
- //根据编号查询详情
- // 你可以继续获取其他字段并进行处理
- }
- } else {
- }
- } catch (McException e) {
- System.out.println("e:"+e.getMessage());
- }
- return "";
- }
- //正整数
- public static String get_randomNumber() {
- Random random = new Random();
- // 指定随机数的范围(例如,1到100之间的随机正整数)
- int min = 100000000;
- int max = 999999999;
- // 生成随机数
- int randomNumber = random.nextInt((max - min) + 1) + min;
- return String.valueOf(randomNumber);
- }
- public static String get_appToken(String appSecret) throws IOException {
- ApigwConfig config = new ApigwConfig();
- //设置client_id
- config.setClientID("300657");
- //设置client_secret
- config.setClientSecret("9163551ef2e2a2cd2398dc05ec527132");
- ApigwClient apigwClient = ApigwClient.getInstance();
- //初始化API网关客户端
- apigwClient.init(config);
- ApiRequest request = new ApiRequest(GET, "api.kingdee.com", "/jdyconnector/app_management/kingdee_auth_token");
- Map<String, String> map = new HashMap<>();
- map.put("app_key", "tcyhmh71");
- String app_signature = get_app_signature("tcyhmh71", appSecret);
- map.put("app_signature", app_signature);
- request.setQuerys(map);
- request.setBodyJson(JSONObject.toJSONString("").getBytes());
- ApiResult result = ApigwClient.getInstance().send(request);
- // 解析JSON字符串
- String jsonBody = result.getBody();
- // 解析JSON字符串
- JSONObject jsonObject = JSON.parseObject(jsonBody);
- JSONObject dataObject = jsonObject.getJSONObject("data");
- // 获取app-token,注意fastjson对key中包含特殊字符(如-)的处理是自动的
- String appToken = dataObject.getString("app-token");
- System.out.println(appToken);
- return appToken;
- }
- //加密X-Api-Signature加密规则
- public static String get_app_signature(String app_key, String appSecret) {
- try {
- // 创建一个Mac实例,并指定使用HmacSHA256算法
- Mac mac = Mac.getInstance("HmacSHA256");
- // 使用appSecret作为密钥
- SecretKeySpec secretKeySpec = new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
- mac.init(secretKeySpec);
- // 对appKey进行加密
- byte[] hmacBytes = mac.doFinal(app_key.getBytes(StandardCharsets.UTF_8));
- // 将加密结果转换为16进制字符串
- StringBuilder hexString = new StringBuilder(2 * hmacBytes.length);
- for (byte b : hmacBytes) {
- String hex = Integer.toHexString(0xff & b);
- if (hex.length() == 1) hexString.append('0');
- hexString.append(hex);
- }
- // 将16进制字符串进行Base64编码
- byte[] hexBytes = hexString.toString().getBytes(StandardCharsets.UTF_8);
- String base64Encoded = Base64.getEncoder().encodeToString(hexBytes);
- return base64Encoded;
- } catch (NoSuchAlgorithmException | InvalidKeyException e) {
- throw new RuntimeException("Error while generating HMAC-SHA256 hash", e);
- }
- }
- //加密X-Api-Signature生成规则
- public static String get_app_signature(String clientSecret, String QQFS, String path, Map<String, String> params, String TimeStamp, String randomNumber) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
- String method = QQFS;
- String originalString = path;
- String target = "/"; // 要替换的字符,转换为字符串
- String replacement = "%2F"; // 替换后的字符串
- // 使用String的replace方法替换所有出现的target为replacement
- String encodedString = originalString.replace(target, replacement);
- StringBuilder signatureText = new StringBuilder();
- signatureText.append(method).append("\n");
- signatureText.append(encodedString).append("\n");
- // 拼接 params 参数(进行两次 URL 编码并转换为大写,但 TreeMap 已排序且只需编码一次)
- if (params != null) {
- Map<String, String> encodedParams = doubleUrlEncodeParams(params);
- // 按参数名的ASCII码升序排序
- List<Map.Entry<String, String>> sortedParams = new ArrayList<>(encodedParams.entrySet());
- sortedParams.sort(Comparator.comparing(Map.Entry::getKey));
- String signString = generateSignString(sortedParams);
- signatureText.append(signString).append("\n");
- System.out.println("签名字符串: " + signString);
- } else {
- signatureText.append("\n");
- }
- // 添加 headers 参数(x-api-nonce 和 x-api-timestamp,小写编码但拼接时保持原样)
- // 注意:这里实际上不需要再次编码,因为 nonce 和 timestamp 通常是数字或基64字符串,且规则要求小写(但编码后是大写字母的情况在这里不适用)
- signatureText.append("x-api-nonce:").append(randomNumber).append("\n");
- signatureText.append("x-api-timestamp:").append(TimeStamp).append("\n");
- // 输出签名原文(实际签名算法应在此原文基础上进行)
- System.out.println("Signature Text:\n" + signatureText.toString());
- String message = signatureText.toString();
- String hmacHex = get_app_signature(message, clientSecret);
- return hmacHex;
- }
- /**
- * 对参数值进行两次URL编码,并将字母转为大写
- */
- private static Map<String, String> doubleUrlEncodeParams(Map<String, String> params) {
- Map<String, String> encodedParams = new HashMap<>();
- for (Map.Entry<String, String> entry : params.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue();
- try {
- // 第一次URL编码
- String firstEncode = URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
- // 第二次URL编码
- String secondEncode = URLEncoder.encode(firstEncode, StandardCharsets.UTF_8.toString());
- // 转为大写
- encodedParams.put(key, secondEncode.toUpperCase());
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("URL编码失败", e);
- }
- }
- return encodedParams;
- }
- /**
- * 生成签名字符串(key1=value1&key2=value2)
- */
- private static String generateSignString(List<Map.Entry<String, String>> sortedParams) {
- StringBuilder signString = new StringBuilder();
- for (Map.Entry<String, String> entry : sortedParams) {
- if (signString.length() > 0) {
- signString.append("&");
- }
- signString.append(entry.getKey()).append("=").append(entry.getValue());
- }
- return signString.toString();
- }
- public static String signMessage(String message, String clientSecret) throws NoSuchAlgorithmException, InvalidKeyException {
- // 创建一个HMAC-SHA256 Mac实例
- Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
- // 将clientSecret转换为密钥规范
- SecretKeySpec secretKeySpec = new SecretKeySpec(clientSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
- // 初始化Mac实例
- sha256_HMAC.init(secretKeySpec);
- // 计算HMAC
- byte[] hmacBytes = sha256_HMAC.doFinal(message.getBytes(StandardCharsets.UTF_8));
- // 将字节数组转换为十六进制字符串
- return bytesToHex(hmacBytes);
- }
- /**
- * 将字节数组转换为十六进制字符串
- *
- * @param bytes 要转换的字节数组
- * @return 转换后的十六进制字符串
- */
- public static String bytesToHex(byte[] bytes) {
- Formatter formatter = new Formatter();
- for (byte b : bytes) {
- formatter.format("%02x", b);
- }
- String result = formatter.toString();
- formatter.close();
- return result;
- }
- @Autowired
- private RjkServer rjkServer;
- @Test
- public void testH3UserToweiling() {
- // 准备测试数据
- Map<String, String> testData = new HashMap<>();
- // 替换为实际的氚云业务对象ID
- // testData.put("BizObjectId", "0233a0df-24a1-4ee2-9de8-b4f3029b5594");
- // testData.put("BizObjectId", "d47b5b5b-0a4b-4120-8d08-6c5d79f8378f");
- // testData.put("BizObjectId", "151452f7-33f9-407e-a95e-5e040168ba3d");
- testData.put("BizObjectId", "967a68c1-5197-47cd-86e1-0a1cd42afb1f");
- // 调用H3UserToweiling方法
- rjkServer.H3UserToweiling(testData);
- }
- @Test
- public void testH3BusinessToWeiling() {
- // 准备测试数据
- Map<String, String> testData = new HashMap<>();
- // 替换为实际的氚云业务对象ID
- // testData.put("BizObjectId", "b7932c25-b081-498a-9c7e-da67c14208c2");
- testData.put("BizObjectId", "1f610bab-ada8-4247-a55c-d4d389450ce9");
- // 调用H3UserToweiling方法
- rjkServer.H3BusinessToWeiling(testData);
- }
- }
|