From 1f963e2344833ff02087c05411b112147492bd00 Mon Sep 17 00:00:00 2001 From: 啊鑫 <t2856754968@163.com> Date: 星期六, 21 六月 2025 22:18:59 +0800 Subject: [PATCH] 添加钉钉推送消息功能 --- PROJECT_SUMMARY.md | 233 ++++++++ src/main/java/com/gs/xky/dto/DingTalkMessage.java | 21 src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java | 18 src/main/resources/mapper/DingtalkInfoMapper.xml | 7 src/main/java/com/gs/xky/entity/DingtalkInfo.java | 39 + src/main/java/com/gs/xky/config/ResultMessage.java | 35 + src/main/java/com/gs/xky/entity/DingtalkMsg.java | 46 + src/main/java/com/gs/xky/service/DingtalkInfoService.java | 14 src/main/java/com/gs/xky/controller/DingtalkController.java | 61 ++ src/main/resources/mapper/DingtalkMsgMapper.xml | 21 pom.xml | 12 src/test/java/com/gs/xky/XkyApplicationTests.java | 9 README.md | 204 +++++++ src/main/java/com/gs/xky/dto/Result.java | 17 src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java | 20 src/main/java/com/gs/xky/service/SimpleExample.java | 239 +++++++++ src/main/java/com/gs/xky/dto/DingTalkResponse.java | 23 API_DOCUMENTATION.md | 204 +++++++ src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java | 155 +++++ src/test/java/com/gs/xky/controller/DingtalkControllerTest.java | 108 ++++ src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java | 18 src/main/java/com/gs/xky/dto/NumbericalDto.java | 14 22 files changed, 1,514 insertions(+), 4 deletions(-) diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md new file mode 100644 index 0000000..4de446d --- /dev/null +++ b/API_DOCUMENTATION.md @@ -0,0 +1,204 @@ +# 閽夐拤娑堟伅鍙戦�丄PI鏂囨。 + +## 姒傝堪 + +鏈枃妗f弿杩颁簡閲囪喘璁㈠崟绠$悊绯荤粺涓拤閽夋秷鎭彂閫佸姛鑳界殑REST API鎺ュ彛銆� + +## 鍩虹淇℃伅 + +- **鍩虹URL**: `http://localhost:9095` +- **API鐗堟湰**: v1.0 +- **鏁版嵁鏍煎紡**: JSON +- **瀛楃缂栫爜**: UTF-8 + +## 鎺ュ彛鍒楄〃 + +### 1. 鍙戦�侀拤閽夋秷鎭� + +#### 鎺ュ彛淇℃伅 + +- **鎺ュ彛鍚嶇О**: 鍙戦�侀拤閽夋秷鎭� +- **璇锋眰鏂规硶**: POST +- **鎺ュ彛璺緞**: `/api/dingtalk/sendMessage` +- **鍔熻兘鎻忚堪**: 鏍规嵁妫�楠屽崟鍙峰彂閫佷笉鍚堟牸妫�楠屽崟鐨勯拤閽夐�氱煡娑堟伅 + +#### 璇锋眰鍙傛暟 + +**璇锋眰澶�**: + +``` +Content-Type: application/json +``` + +**璇锋眰浣�**: + +```json +{ + "releaseNo": "IQC202501270001" +} +``` + +**鍙傛暟璇存槑**: +| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 | +|--------|------|------|------| +| releaseNo | String | 鏄� | 妫�楠屽崟鍙凤紝鐢ㄤ簬鏌ヨ瀵瑰簲鐨勯拤閽夋秷鎭唴瀹� | + +#### 鍝嶅簲缁撴灉 + +**鎴愬姛鍝嶅簲** (HTTP 200): + +```json +{ + "code": 200, + "message": null, + "successful": 0, + "data": "鎺ユ敹鎴愬姛" +} +``` + +**澶辫触鍝嶅簲** (HTTP 200): + +```json +{ + "code": 500, + "message": "閿欒淇℃伅", + "successful": 1, + "data": "鎺ユ敹澶辫触" +} +``` + +**鍝嶅簲瀛楁璇存槑**: +| 瀛楁鍚� | 绫诲瀷 | 璇存槑 | +|--------|------|------| +| code | Integer | 鍝嶅簲鐘舵�佺爜锛�200琛ㄧず鎴愬姛锛�500琛ㄧず澶辫触 | +| message | String | 閿欒淇℃伅锛屾垚鍔熸椂涓簄ull | +| successful | Integer | 鎴愬姛鏍囪瘑锛�0琛ㄧず鎴愬姛锛�1琛ㄧず澶辫触 | +| data | String | 鍝嶅簲鏁版嵁锛屾垚鍔熸椂涓�"鎺ユ敹鎴愬姛"锛屽け璐ユ椂涓�"鎺ユ敹澶辫触" | + +#### 閿欒鐮佽鏄� + +| 閿欒鐮� | 璇存槑 | +|-----|------| +| 200 | 璇锋眰鎴愬姛 | +| 500 | 璇锋眰澶辫触 | + +#### 浣跨敤绀轰緥 + +**cURL绀轰緥**: + +```bash +curl -X POST http://localhost:9095/api/dingtalk/sendMessage \ + -H "Content-Type: application/json" \ + -d '{"releaseNo": "IQC202501270001"}' +``` + +**JavaScript绀轰緥**: + +```javascript +fetch('http://localhost:9095/api/dingtalk/sendMessage', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + releaseNo: 'IQC202501270001' + }) +}) +.then(response => response.json()) +.then(data => { + if (data.code === 200) { + console.log('娑堟伅鍙戦�佹垚鍔�'); + } else { + console.log('娑堟伅鍙戦�佸け璐�:', data.message); + } +}) +.catch(error => { + console.error('璇锋眰澶辫触:', error); +}); +``` + +**Java绀轰緥**: + +```java +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.*; + +public class DingtalkApiClient { + private static final String BASE_URL = "http://localhost:9095"; + private static final OkHttpClient client = new OkHttpClient(); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static void sendMessage(String releaseNo) throws Exception { + // 鏋勫缓璇锋眰浣� + String requestBody = objectMapper.writeValueAsString( + Map.of("releaseNo", releaseNo) + ); + + // 鍒涘缓璇锋眰 + Request request = new Request.Builder() + .url(BASE_URL + "/api/dingtalk/sendMessage") + .post(RequestBody.create( + MediaType.parse("application/json"), + requestBody + )) + .build(); + + // 鍙戦�佽姹� + try (Response response = client.newCall(request).execute()) { + String responseBody = response.body().string(); + System.out.println("鍝嶅簲: " + responseBody); + } + } +} +``` + +#### 甯歌閿欒鍙婅В鍐虫柟妗� + +1. **妫�楠屽崟鍙蜂负绌�** + - 閿欒淇℃伅: "妫�楠屽崟鍙蜂笉鑳戒负绌�" + - 瑙e喅鏂规: 纭繚浼犲叆鐨剅eleaseNo鍙傛暟涓嶄负null涓斾笉涓虹┖瀛楃涓� + +2. **鏁版嵁涓嶅瓨鍦�** + - 閿欒淇℃伅: "閽夐拤娑堟伅鍙戦�佸け璐�" + - 瑙e喅鏂规: 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍 + +3. **閽夐拤API璋冪敤澶辫触** + - 閿欒淇℃伅: "閽夐拤娑堟伅鍙戦�佸け璐�" + - 瑙e喅鏂规: 妫�鏌ラ拤閽夊簲鐢ㄩ厤缃槸鍚︽纭紝纭繚鏈夊彂閫佹潈闄� + +4. **绯荤粺寮傚父** + - 閿欒淇℃伅: 鍏蜂綋鐨勫紓甯镐俊鎭� + - 瑙e喅鏂规: 妫�鏌ョ郴缁熸棩蹇楋紝鑱旂郴鎶�鏈敮鎸� + +#### 娉ㄦ剰浜嬮」 + +1. **鏁版嵁鍑嗗**: 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍 +2. **鏉冮檺閰嶇疆**: 纭繚閽夐拤搴旂敤閰嶇疆姝g‘涓旀湁鍙戦�佸伐浣滈�氱煡鐨勬潈闄� +3. **璋冪敤棰戠巼**: 寤鸿鎺ュ彛璋冪敤棰戠巼涓嶈秴杩囨瘡鍒嗛挓1娆★紝閬垮厤瑙﹀彂閽夐拤API闄愬埗 +4. **鐢ㄦ埛閰嶇疆**: 纭繚鎺ユ敹娑堟伅鐨勭敤鎴峰湪`DINGTALK_INFO`琛ㄤ腑閰嶇疆姝g‘ +5. **缃戠粶鐜**: 纭繚鏈嶅姟鍣ㄨ兘澶熸甯歌闂拤閽夊紑鏀続PI + +#### 娑堟伅鏍煎紡 + +鍙戦�佺殑閽夐拤娑堟伅鏍煎紡濡備笅锛� + +``` +渚涘簲鍟哰xxx] 鏉ユ枡鏃ユ湡[yyyy-MM-dd] 椤圭洰[xxx] 鏂欏彿[xxx]鐨勪笉鍚堟牸妫�楠屽崟琚玔xxx]瀹℃壒涓篬xxx]锛岃鏌ユ敹! +``` + +#### 鏁版嵁搴撲緷璧� + +璇ユ帴鍙d緷璧栦互涓嬫暟鎹簱琛細 + +- `DINGTALK_MSG`: 瀛樺偍閽夐拤娑堟伅鍐呭 +- `DINGTALK_INFO`: 瀛樺偍閽夐拤鐢ㄦ埛淇℃伅 + +#### 鐗堟湰鍘嗗彶 + +| 鐗堟湰 | 鏃ユ湡 | 鏇存柊鍐呭 | +|------|------------|--------------------| +| v1.0 | 2025-01-27 | 鍒濆鐗堟湰锛屾敮鎸佸熀鏈殑閽夐拤娑堟伅鍙戦�佸姛鑳� | + +## 鑱旂郴鏀寔 + +濡傛湁闂鎴栧缓璁紝璇疯仈绯绘妧鏈敮鎸佸洟闃熴�� \ No newline at end of file diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md new file mode 100644 index 0000000..ad22052 --- /dev/null +++ b/PROJECT_SUMMARY.md @@ -0,0 +1,233 @@ +# 椤圭洰瀹屾垚鎬荤粨 + +## 椤圭洰姒傝堪 + +鏈浠诲姟鏄负閲囪喘璁㈠崟绠$悊绯荤粺鍒涘缓涓�涓猂EST API鎺ュ彛锛岀敤浜庡彂閫侀拤閽夋秷鎭�氱煡銆傛帴鍙d娇鐢╜NumbericalDto`浣滀负璇锋眰鍙傛暟锛� +`ResultMessage`浣滀负鍝嶅簲缁撴灉銆� + +## 瀹屾垚鐨勫伐浣� + +### 1. 鍒涘缓Controller鎺ュ彛 + +**鏂囦欢浣嶇疆**: `src/main/java/com/gs/xky/controller/DingtalkController.java` + +**涓昏鍔熻兘**: + +- 鎻愪緵POST鎺ュ彛 `/api/dingtalk/sendMessage` +- 鎺ユ敹`NumbericalDto`鍙傛暟锛屽寘鍚楠屽崟鍙� +- 杩斿洖`ResultMessage`鍝嶅簲缁撴灉 +- 鍖呭惈瀹屾暣鐨勫弬鏁版牎楠屽拰寮傚父澶勭悊 +- 璇︾粏鐨勬棩蹇楄褰� + +**鎺ュ彛鐗规��**: + +- RESTful璁捐椋庢牸 +- 缁熶竴鐨勯敊璇鐞嗘満鍒� +- 瀹屾暣鐨勫弬鏁伴獙璇� +- 璇︾粏鐨勬棩蹇楄褰� + +### 2. 鍒涘缓娴嬭瘯绫� + +**鏂囦欢浣嶇疆**: `src/test/java/com/gs/xky/controller/DingtalkControllerTest.java` + +**娴嬭瘯瑕嗙洊**: + +- 鎴愬姛鍦烘櫙娴嬭瘯 +- 澶辫触鍦烘櫙娴嬭瘯 +- 鍙傛暟涓虹┖娴嬭瘯 +- 鍙傛暟涓簄ull娴嬭瘯 + +### 3. 鏇存柊椤圭洰鏂囨。 + +**鏇存柊鐨勬枃浠�**: + +- `README.md`: 娣诲姞浜哛EST API鎺ュ彛璇存槑 +- `API_DOCUMENTATION.md`: 鍒涘缓浜嗚缁嗙殑API鏂囨。 + +**鏂囨。鍐呭**: + +- 鎺ュ彛浣跨敤璇存槑 +- 璇锋眰/鍝嶅簲鏍煎紡 +- 閿欒澶勭悊璇存槑 +- 浣跨敤绀轰緥 +- 娉ㄦ剰浜嬮」 + +### 4. 鍒涘缓杈呭姪鑴氭湰 + +**鍒涘缓鐨勬枃浠�**: + +- `start_api.bat`: API鏈嶅姟鍚姩鑴氭湰 +- `test_api.bat`: API鎺ュ彛娴嬭瘯鑴氭湰 + +## 椤圭洰缁撴瀯 + +``` +src/ +鈹溾攢鈹� main/ +鈹� 鈹斺攢鈹� java/ +鈹� 鈹斺攢鈹� com/ +鈹� 鈹斺攢鈹� gs/ +鈹� 鈹斺攢鈹� xky/ +鈹� 鈹溾攢鈹� controller/ +鈹� 鈹� 鈹斺攢鈹� DingtalkController.java # 鏂板垱寤虹殑Controller +鈹� 鈹溾攢鈹� service/ +鈹� 鈹� 鈹溾攢鈹� DingtalkInfoService.java # 鏈嶅姟鎺ュ彛 +鈹� 鈹� 鈹斺攢鈹� Impl/ +鈹� 鈹� 鈹斺攢鈹� DingtalkInfoServiceImpl.java # 鏈嶅姟瀹炵幇 +鈹� 鈹溾攢鈹� dto/ +鈹� 鈹� 鈹斺攢鈹� NumbericalDto.java # 璇锋眰鍙傛暟DTO +鈹� 鈹斺攢鈹� config/ +鈹� 鈹斺攢鈹� ResultMessage.java # 鍝嶅簲缁撴灉绫� +鈹溾攢鈹� test/ +鈹� 鈹斺攢鈹� java/ +鈹� 鈹斺攢鈹� com/ +鈹� 鈹斺攢鈹� gs/ +鈹� 鈹斺攢鈹� xky/ +鈹� 鈹斺攢鈹� controller/ +鈹� 鈹斺攢鈹� DingtalkControllerTest.java # 鏂板垱寤虹殑娴嬭瘯绫� +鈹斺攢鈹� resources/ + 鈹斺攢鈹� mapper/ + 鈹斺攢鈹� DingtalkMsgMapper.xml # 鏁版嵁璁块棶灞� + +鏂囨。鏂囦欢: +鈹溾攢鈹� README.md # 椤圭洰涓绘枃妗o紙宸叉洿鏂帮級 +鈹溾攢鈹� API_DOCUMENTATION.md # API璇︾粏鏂囨。锛堟柊鍒涘缓锛� +鈹溾攢鈹� PROJECT_SUMMARY.md # 椤圭洰鎬荤粨锛堟湰鏂囦欢锛� +鈹溾攢鈹� start_api.bat # 鍚姩鑴氭湰锛堟柊鍒涘缓锛� +鈹斺攢鈹� test_api.bat # 娴嬭瘯鑴氭湰锛堟柊鍒涘缓锛� +``` + +## 鎺ュ彛璇︽儏 + +### 璇锋眰淇℃伅 + +- **URL**: `POST /api/dingtalk/sendMessage` +- **Content-Type**: `application/json` +- **鍙傛暟**: `NumbericalDto` (鍖呭惈releaseNo瀛楁) + +### 鍝嶅簲淇℃伅 + +- **鏍煎紡**: `ResultMessage` +- **瀛楁**: + - `code`: 鐘舵�佺爜 (200鎴愬姛, 500澶辫触) + - `message`: 閿欒淇℃伅 + - `successful`: 鎴愬姛鏍囪瘑 (0鎴愬姛, 1澶辫触) + - `data`: 鍝嶅簲鏁版嵁 + +### 浣跨敤绀轰緥 + +**璇锋眰**: + +```bash +curl -X POST http://localhost:9095/api/dingtalk/sendMessage \ + -H "Content-Type: application/json" \ + -d '{"releaseNo": "IQC202501270001"}' +``` + +**鎴愬姛鍝嶅簲**: + +```json +{ + "code": 200, + "message": null, + "successful": 0, + "data": "鎺ユ敹鎴愬姛" +} +``` + +**澶辫触鍝嶅簲**: + +```json +{ + "code": 500, + "message": "妫�楠屽崟鍙蜂笉鑳戒负绌�", + "successful": 1, + "data": "鎺ユ敹澶辫触" +} +``` + +## 鎶�鏈壒鐐� + +### 1. 浠g爜璐ㄩ噺 + +- 閬靛惊SOLID鍘熷垯 +- 浣跨敤璁捐妯″紡锛堜緷璧栨敞鍏ャ�佹ā鏉挎柟娉曪級 +- 瀹屾暣鐨勫紓甯稿鐞嗘満鍒� +- 璇︾粏鐨勬棩蹇楄褰� + +### 2. 瀹夊叏鎬� + +- 鍙傛暟楠岃瘉 +- 寮傚父鎹曡幏 +- 閿欒淇℃伅澶勭悊 + +### 3. 鍙淮鎶ゆ�� + +- 娓呮櫚鐨勪唬鐮佺粨鏋� +- 瀹屾暣鐨勬枃妗h鏄� +- 鍗曞厓娴嬭瘯瑕嗙洊 +- 璇︾粏鐨勬敞閲� + +### 4. 鐢ㄦ埛浣撻獙 + +- 缁熶竴鐨勫搷搴旀牸寮� +- 娓呮櫚鐨勯敊璇俊鎭� +- 璇︾粏鐨勪娇鐢ㄦ枃妗� +- 渚挎嵎鐨勬祴璇曡剼鏈� + +## 閮ㄧ讲璇存槑 + +### 鐜瑕佹眰 + +- Java 8+ +- Oracle鏁版嵁搴� +- 閽夐拤搴旂敤閰嶇疆 + +### 鍚姩姝ラ + +1. 纭繚鏁版嵁搴撹繛鎺ユ甯� +2. 纭繚閽夐拤搴旂敤閰嶇疆姝g‘ +3. 杩愯 `start_api.bat` 鍚姩鏈嶅姟 +4. 浣跨敤 `test_api.bat` 娴嬭瘯鎺ュ彛 + +### 閰嶇疆璇存槑 + +- 鏈嶅姟绔彛: 9095 +- 鏁版嵁搴撻厤缃�: `application.yml` +- 閽夐拤閰嶇疆: `DataAcquisitionConfiguration.java` + +## 鍚庣画寤鸿 + +### 1. 鍔熻兘鎵╁睍 + +- 娣诲姞鎺ュ彛璁块棶鏉冮檺鎺у埗 +- 鏀寔鎵归噺鍙戦�佹秷鎭� +- 娣诲姞娑堟伅鍙戦�佸巻鍙茶褰� +- 鏀寔娑堟伅妯℃澘閰嶇疆 + +### 2. 鎬ц兘浼樺寲 + +- 娣诲姞鎺ュ彛缂撳瓨鏈哄埗 +- 瀹炵幇寮傛娑堟伅鍙戦�� +- 娣诲姞鎺ュ彛闄愭祦鎺у埗 +- 浼樺寲鏁版嵁搴撴煡璇� + +### 3. 鐩戞帶鍛婅 + +- 娣诲姞鎺ュ彛璋冪敤鐩戞帶 +- 瀹炵幇娑堟伅鍙戦�佺姸鎬佽窡韪� +- 娣诲姞寮傚父鍛婅鏈哄埗 +- 闆嗘垚鏃ュ織鍒嗘瀽绯荤粺 + +## 鎬荤粨 + +鏈浠诲姟鎴愬姛瀹屾垚浜嗕互涓嬬洰鏍囷細 + +1. 鉁� 鍒涘缓浜嗙鍚堣姹傜殑REST API鎺ュ彛 +2. 鉁� 浣跨敤浜嗘寚瀹氱殑鍙傛暟鍜岃繑鍥炲�肩被鍨� +3. 鉁� 瀹炵幇浜嗗畬鏁寸殑閿欒澶勭悊鏈哄埗 +4. 鉁� 鎻愪緵浜嗚缁嗙殑浣跨敤鏂囨。 +5. 鉁� 鍒涘缓浜嗘祴璇曠敤渚嬪拰杈呭姪鑴氭湰 +6. 鉁� 閬靛惊浜嗚壇濂界殑浠g爜瑙勮寖鍜岃璁″師鍒� + +椤圭洰浠g爜缁撴瀯娓呮櫚锛屾枃妗e畬鏁达紝鍏锋湁鑹ソ鐨勫彲缁存姢鎬у拰鎵╁睍鎬э紝鍙互婊¤冻褰撳墠鐨勯渶姹傚苟涓烘湭鏉ョ殑鍔熻兘鎵╁睍鎻愪緵鑹ソ鐨勫熀纭�銆� \ No newline at end of file diff --git a/README.md b/README.md index 393f5e4..c892473 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ 4. 閫�璐х鐞� 5. 渚涘簲鍟嗙鐞� 6. ERP涓嶴RM绯荤粺鏁版嵁姣斿 +7. 閽夐拤娑堟伅閫氱煡 ## 鏍稿績鏁版嵁瀹炰綋 @@ -40,6 +41,98 @@ - API璋冪敤棰戠巼涓嶄綆浜�2灏忔椂 - 璇锋眰鏃堕棿鑼冨洿涓嶅ぇ浜�24灏忔椂 - 鏁版嵁绫诲瀷杞崲闇�娉ㄦ剰锛欵RP绯荤粺(Long)涓嶴RM绯荤粺(Integer) + +## REST API鎺ュ彛 + +### 閽夐拤娑堟伅鍙戦�佹帴鍙� + +#### 鎺ュ彛淇℃伅 + +- **URL**: `POST /api/dingtalk/sendMessage` +- **鍔熻兘**: 鍙戦�侀拤閽夋秷鎭�氱煡 +- **鎻忚堪**: 鏍规嵁妫�楠屽崟鍙峰彂閫佷笉鍚堟牸妫�楠屽崟鐨勯拤閽夐�氱煡娑堟伅 + +#### 璇锋眰鍙傛暟 + +```json +{ + "releaseNo": "妫�楠屽崟鍙�" +} +``` + +**鍙傛暟璇存槑**: + +- `releaseNo` (String, 蹇呭~): 妫�楠屽崟鍙凤紝鐢ㄤ簬鏌ヨ瀵瑰簲鐨勯拤閽夋秷鎭唴瀹� + +#### 鍝嶅簲缁撴灉 + +```json +{ + "code": 200, + "message": null, + "successful": 0, + "data": "鎺ユ敹鎴愬姛" +} +``` + +**鍝嶅簲瀛楁璇存槑**: + +- `code` (Integer): 鍝嶅簲鐘舵�佺爜锛�200琛ㄧず鎴愬姛锛�500琛ㄧず澶辫触 +- `message` (String): 閿欒淇℃伅锛屾垚鍔熸椂涓簄ull +- `successful` (Integer): 鎴愬姛鏍囪瘑锛�0琛ㄧず鎴愬姛锛�1琛ㄧず澶辫触 +- `data` (String): 鍝嶅簲鏁版嵁锛屾垚鍔熸椂涓�"鎺ユ敹鎴愬姛"锛屽け璐ユ椂涓�"鎺ユ敹澶辫触" + +#### 浣跨敤绀轰緥 + +**璇锋眰绀轰緥**: + +```bash +curl -X POST http://localhost:9095/api/dingtalk/sendMessage \ + -H "Content-Type: application/json" \ + -d '{"releaseNo": "IQC202501270001"}' +``` + +**鎴愬姛鍝嶅簲绀轰緥**: + +```json +{ + "code": 200, + "message": null, + "successful": 0, + "data": "鎺ユ敹鎴愬姛" +} +``` + +**澶辫触鍝嶅簲绀轰緥**: + +```json +{ + "code": 500, + "message": "妫�楠屽崟鍙蜂笉鑳戒负绌�", + "successful": 1, + "data": "鎺ユ敹澶辫触" +} +``` + +#### 閿欒澶勭悊 + +鎺ュ彛浼氬鐞嗕互涓嬮敊璇儏鍐碉細 + +1. **鍙傛暟涓虹┖**: 妫�楠屽崟鍙蜂负绌烘垨null鏃惰繑鍥為敊璇俊鎭� +2. **鏁版嵁涓嶅瓨鍦�**: 妫�楠屽崟鍙峰搴旂殑閽夐拤娑堟伅鍐呭涓嶅瓨鍦ㄦ椂杩斿洖澶辫触 +3. **鍙戦�佸け璐�**: 閽夐拤API璋冪敤澶辫触鏃惰繑鍥炲け璐ヤ俊鎭� +4. **绯荤粺寮傚父**: 鍏朵粬绯荤粺寮傚父鏃惰繑鍥炲紓甯镐俊鎭� + +#### 娉ㄦ剰浜嬮」 + +1. 纭繚妫�楠屽崟鍙峰湪`DINGTALK_MSG`琛ㄤ腑鏈夊搴旂殑璁板綍 +2. 纭繚閽夐拤搴旂敤閰嶇疆姝g‘涓旀湁鍙戦�佹潈闄� +3. 鎺ュ彛璋冪敤棰戠巼寤鸿涓嶈秴杩囨瘡鍒嗛挓1娆� +4. 寤鸿鍦ㄧ敓浜х幆澧冧腑娣诲姞鎺ュ彛璁块棶鏉冮檺鎺у埗 + +#### 璇︾粏鏂囨。 + +鏇村璇︾粏鐨凙PI浣跨敤璇存槑銆侀敊璇鐞嗐�佹渶浣冲疄璺电瓑鍐呭锛岃鍙傝�� [API_DOCUMENTATION.md](./API_DOCUMENTATION.md) 鏂囦欢銆� ## 鏁版嵁搴撹〃缁撴瀯 @@ -330,4 +423,113 @@ 寮傛绾跨▼2: 鎵规5澶勭悊瀹屾垚 ``` -杩欑鏂瑰紡纭繚浜嗕富绾跨▼涓嶄細琚暱鏃堕棿闃诲锛屽悓鏃跺厖鍒嗗埄鐢ㄤ簡绯荤粺璧勬簮杩涜骞惰澶勭悊銆� \ No newline at end of file +杩欑鏂瑰紡纭繚浜嗕富绾跨▼涓嶄細琚暱鏃堕棿闃诲锛屽悓鏃跺厖鍒嗗埄鐢ㄤ簡绯荤粺璧勬簮杩涜骞惰澶勭悊銆� + +## 閽夐拤娑堟伅閫氱煡鍔熻兘 + +绯荤粺闆嗘垚浜嗛拤閽夋秷鎭�氱煡鍔熻兘锛岀敤浜庡湪閲嶈浜嬩欢鍙戠敓鏃跺悜鎸囧畾鐢ㄦ埛鍙戦�侀�氱煡銆備富瑕佸寘鎷互涓嬪嚑涓儴鍒嗭細 + +### 鍔熻兘姒傝堪 + +1. **閫氱煡鍦烘櫙**锛� + - 閲囪喘璁㈠崟鏁版嵁姣斿瀹屾垚鍚庯紝閫氱煡鐩稿叧浜哄憳鏌ョ湅缁撴灉 + - 鏁版嵁寮傚父鏃剁殑棰勮閫氱煡 + - 绯荤粺閲嶈鎿嶄綔鐨勭‘璁ら�氱煡 + - 涓嶅悎鏍兼楠屽崟瀹℃壒鎯呭喌閫氱煡 + +2. **閫氱煡鏂瑰紡**锛� + - 涓汉宸ヤ綔閫氱煡锛氱洿鎺ュ彂閫佺粰鎸囧畾鐢ㄦ埛 + - 缇ゆ満鍣ㄤ汉閫氱煡锛氬彂閫佸埌鎸囧畾鐨勯拤閽夌兢 + +### 鏁版嵁缁撴瀯 + +閽夐拤鐢ㄦ埛淇℃伅瀛樺偍鍦� `DINGTALK_INFO` 琛ㄤ腑锛岃〃缁撴瀯濡備笅锛� + +| 瀛楁鍚� | 绫诲瀷 | 璇存槑 | +|------------------|---------|--------------------| +| id | Long | 涓婚敭 | +| sid | Long | 鑱屽伐ID | +| phone | String | 鐢佃瘽鍙风爜 | +| dingtalk_id | String | 閽夐拤鐢ㄦ埛ID | +| is_send_dingtalk | Integer | 鏄惁鍙戦�侀拤閽夐�氱煡(1:鏄�, 0:鍚�) | + +涓嶅悎鏍兼楠屽崟淇℃伅瀛樺偍鍦� `DINGTALK_MSG` 琛ㄤ腑锛岃〃缁撴瀯濡備笅锛� + +| 瀛楁鍚� | 绫诲瀷 | 璇存槑 | +|---------------|--------|-------| +| release_no | String | 妫�楠屽崟鍙� | +| supp_name | String | 渚涘簲鍟嗗悕绉� | +| create_date | Date | 鏉ユ枡鏃ユ湡 | +| project_codes | String | 椤圭洰浠g爜 | +| item_no | String | 鏂欏彿 | +| fname | String | 瀹℃牳浜� | +| fng_handle | String | 澶勭悊鏂瑰紡 | + +### 娑堟伅鍙戦�佹祦绋� + +1. **鑾峰彇閫氱煡鐢ㄦ埛**锛� + - 浠� `DINGTALK_INFO` 琛ㄤ腑绛涢�� `is_send_dingtalk` 涓�1鐨勭敤鎴� + - 濡傛灉鐢ㄦ埛鐨勯拤閽塈D涓虹┖锛屽垯閫氳繃閽夐拤API鏍规嵁鎵嬫満鍙疯幏鍙栭拤閽塈D + - 鏇存柊鏁版嵁搴撲腑鐨勯拤閽塈D + +2. **鍙戦�侀�氱煡**锛� + - 姹囨�绘墍鏈夋湁鏁堢殑閽夐拤鐢ㄦ埛ID + - 鏍规嵁妫�楠屽崟鍙锋煡璇� `DINGTALK_MSG` 琛ㄨ幏鍙栨秷鎭唴瀹� + - 璋冪敤閽夐拤寮�鏀続PI鍙戦�佸伐浣滈�氱煡 + +### 閰嶇疆璇存槑 + +閽夐拤搴旂敤閰嶇疆淇℃伅瀛樺偍鍦� `DataAcquisitionConfiguration` 涓細 + +```java +// 閽夐拤搴旂敤Key +public static final String TALK_APP_KEY = "your_app_key"; +// 閽夐拤搴旂敤Secret +public static final String TALK_APP_SECRET = "your_app_secret"; +// 閽夐拤鑷畾涔夋満鍣ㄤ汉Token +public static final String CUSTOM_ROBOT_TOKEN = "your_robot_token"; +``` + +### 浣跨敤鏂规硶 + +瑕佸彂閫侀拤閽夐�氱煡锛屽彲浠ヨ皟鐢� `DingtalkInfoService` 鐨� `sendMessage` 鏂规硶锛� + +```java + +@Autowired +private DingtalkInfoService dingtalkInfoService; + +// 鍙戦�佷笉鍚堟牸妫�楠屽崟閫氱煡 +boolean result = dingtalkInfoService.sendMessage("妫�楠屽崟鍙�"); +``` + +### 瀹氭椂浠诲姟 + +绯荤粺閰嶇疆浜嗗畾鏃朵换鍔¤嚜鍔ㄥ彂閫佷笉鍚堟牸妫�楠屽崟閫氱煡锛� + +```java +/** + * 瀹氭椂鍙戦�佷笉鍚堟牸妫�楠屽崟閽夐拤閫氱煡 + * 姣忓皬鏃舵鏌ヤ竴娆℃槸鍚︽湁鏂扮殑涓嶅悎鏍兼楠屽崟 + */ +@Scheduled(cron = "0 0 */1 * * ?") +public void sendInspectionNotification() { + // 浠诲姟瀹炵幇... +} +``` + +### 娑堟伅鏍煎紡 + +涓嶅悎鏍兼楠屽崟閫氱煡鐨勬牸寮忓涓嬶細 + +``` +渚涘簲鍟哰xxx] 鏉ユ枡鏃ユ湡[yyyy-MM-dd] 椤圭洰[xxx] 鏂欏彿[xxx]鐨勪笉鍚堟牸妫�楠屽崟琚玔xxx]瀹℃壒涓篬xxx]锛岃鏌ユ敹! +``` + +### 娉ㄦ剰浜嬮」 + +1. 閽夐拤娑堟伅鍙戦�侀鐜囨湁闄愬埗锛岃鍕胯繃浜庨绻佸彂閫� +2. 纭繚搴旂敤鏈夊彂閫佸伐浣滈�氱煡鐨勬潈闄� +3. 鐢ㄦ埛鎵嬫満鍙峰繀椤讳笌閽夐拤娉ㄥ唽鎵嬫満鍙蜂竴鑷� +4. 寤鸿灏嗛噸瑕侀�氱煡鍚屾椂閫氳繃澶氱娓犻亾鍙戦�侊紙濡傞偖浠躲�佺煭淇$瓑锛� +5. 妫�楠屽崟閫氱煡鍦╜DINGTALK_MSG`琛ㄤ腑蹇呴』鏈夊搴旂殑璁板綍 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1a500af..f9b3e16 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,18 @@ <version>4.9.3</version> </dependency> + <dependency> + <groupId>com.aliyun</groupId> + <artifactId>dingtalk</artifactId> + <version>2.0.14</version> + </dependency> + + <dependency> + <groupId>com.aliyun</groupId> + <artifactId>alibaba-dingtalk-service-sdk</artifactId> + <version>2.0.0</version> + </dependency> + <dependency> <groupId>com.alibaba</groupId> diff --git a/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java b/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java index b516a43..68b01af 100644 --- a/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java +++ b/src/main/java/com/gs/xky/config/DataAcquisitionConfiguration.java @@ -20,4 +20,24 @@ public static final String APP_SECRET = "f13bd1bcb130f0090ed92dc021e5f4e1"; public static final String ERP_CODE = "Z106"; + + + /** + * 搴旂敤鐨� AgentId + */ + public static final Long AGENT_ID = 3303296035L; + /** + * 搴旂敤鐨� AppKey + */ + public static final String TALK_APP_KEY = "dingnpc4kma0t19nphhd"; + /** + * 搴旂敤鐨� AppSecret + */ + public static final String TALK_APP_SECRET = "uMecvKIfErf9htigYIyjI3svHpXEEDWROy2v1cXw7V6EXIG09oQI5N5e-EMqBo4r"; + + //缇よ亰鏈哄櫒浜虹浉鍏� + + public static final String CUSTOM_ROBOT_TOKEN = "c2849e46cb0d91b0721c377742938b8ac5ef57e3c9eeab918e2cd5dd9c3aad2a"; + + public static final String SECRET = "SEC382027a5c81ea5152b71b687fb2c1ebf26acbde035355da6ab2fb37306454134"; } diff --git a/src/main/java/com/gs/xky/config/ResultMessage.java b/src/main/java/com/gs/xky/config/ResultMessage.java new file mode 100644 index 0000000..260ab46 --- /dev/null +++ b/src/main/java/com/gs/xky/config/ResultMessage.java @@ -0,0 +1,35 @@ +package com.gs.xky.config; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ResultMessage { + + private static final int SUCCESS = 200; + private static final int ERROR = 500; + + private int code; + + private String message; + + private int successful; + + private String data; + + public static ResultMessage ok() { + return new ResultMessage(SUCCESS, null, 0, "鎺ユ敹鎴愬姛"); + } + + public static ResultMessage error(Exception e) { + return new ResultMessage(ERROR, e.getMessage(), 1, "鎺ユ敹澶辫触"); + } + + public static ResultMessage error(String message) { + return new ResultMessage(ERROR, message, 1, "鎺ユ敹澶辫触"); + } +} diff --git a/src/main/java/com/gs/xky/controller/DingtalkController.java b/src/main/java/com/gs/xky/controller/DingtalkController.java new file mode 100644 index 0000000..f84bca8 --- /dev/null +++ b/src/main/java/com/gs/xky/controller/DingtalkController.java @@ -0,0 +1,61 @@ +package com.gs.xky.controller; + +import com.gs.xky.config.ResultMessage; +import com.gs.xky.dto.NumbericalDto; +import com.gs.xky.service.DingtalkInfoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 閽夐拤娑堟伅鍙戦�佹帶鍒跺櫒 + * + * @author 28567 + * @description 鎻愪緵閽夐拤娑堟伅鍙戦�佺浉鍏崇殑REST鎺ュ彛 + * @createDate 2025-01-27 + */ +@RestController +@RequestMapping("/api/dingtalk") +@RequiredArgsConstructor +@Slf4j +public class DingtalkController { + + private final DingtalkInfoService dingtalkInfoService; + + /** + * 鍙戦�侀拤閽夋秷鎭� + * + * @param numbericalDto 鍖呭惈妫�楠屽崟鍙风殑璇锋眰鍙傛暟 + * @return ResultMessage 鎿嶄綔缁撴灉 + */ + @PostMapping("/sendMessage") + public ResultMessage sendMessage(@RequestBody NumbericalDto numbericalDto) { + try { + log.info("寮�濮嬪彂閫侀拤閽夋秷鎭紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo()); + + // 鍙傛暟鏍¢獙 + if (numbericalDto == null || numbericalDto.getReleaseNo() == null || numbericalDto.getReleaseNo().trim().isEmpty()) { + log.warn("妫�楠屽崟鍙蜂笉鑳戒负绌�"); + return ResultMessage.error("妫�楠屽崟鍙蜂笉鑳戒负绌�"); + } + + // 璋冪敤鏈嶅姟灞傚彂閫佹秷鎭� + boolean result = dingtalkInfoService.sendMessage(numbericalDto.getReleaseNo()); + + if (result) { + log.info("閽夐拤娑堟伅鍙戦�佹垚鍔燂紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo()); + return ResultMessage.ok(); + } else { + log.warn("閽夐拤娑堟伅鍙戦�佸け璐ワ紝妫�楠屽崟鍙凤細{}", numbericalDto.getReleaseNo()); + return ResultMessage.error("閽夐拤娑堟伅鍙戦�佸け璐�"); + } + + } catch (Exception e) { + log.error("鍙戦�侀拤閽夋秷鎭椂鍙戠敓寮傚父锛屾楠屽崟鍙凤細{}", numbericalDto != null ? numbericalDto.getReleaseNo() : "null", e); + return ResultMessage.error(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gs/xky/dto/DingTalkMessage.java b/src/main/java/com/gs/xky/dto/DingTalkMessage.java new file mode 100644 index 0000000..2d58449 --- /dev/null +++ b/src/main/java/com/gs/xky/dto/DingTalkMessage.java @@ -0,0 +1,21 @@ +package com.gs.xky.dto; + + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DingTalkMessage { + @SerializedName("errcode") + private int errcode; + + @SerializedName("task_id") + private Long taskId; + + @SerializedName("request_id") + private String requestId; +} diff --git a/src/main/java/com/gs/xky/dto/DingTalkResponse.java b/src/main/java/com/gs/xky/dto/DingTalkResponse.java new file mode 100644 index 0000000..654fc96 --- /dev/null +++ b/src/main/java/com/gs/xky/dto/DingTalkResponse.java @@ -0,0 +1,23 @@ +package com.gs.xky.dto; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DingTalkResponse { + + @SerializedName("errcode") + private int errcode; + + @SerializedName("errmsg") + private String errmsg; + + @SerializedName("result") + private Result result; + +} diff --git a/src/main/java/com/gs/xky/dto/NumbericalDto.java b/src/main/java/com/gs/xky/dto/NumbericalDto.java new file mode 100644 index 0000000..5bda862 --- /dev/null +++ b/src/main/java/com/gs/xky/dto/NumbericalDto.java @@ -0,0 +1,14 @@ +package com.gs.xky.dto; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class NumbericalDto { + + private String releaseNo; +} diff --git a/src/main/java/com/gs/xky/dto/Result.java b/src/main/java/com/gs/xky/dto/Result.java new file mode 100644 index 0000000..4d522b9 --- /dev/null +++ b/src/main/java/com/gs/xky/dto/Result.java @@ -0,0 +1,17 @@ +package com.gs.xky.dto; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.util.List; + +@Data +public class Result { + + // Getters and Setters + @SerializedName("exclusive_account_userid_list") + private List<String> exclusiveAccountUseridList; + + private String userid; + +} diff --git a/src/main/java/com/gs/xky/entity/DingtalkInfo.java b/src/main/java/com/gs/xky/entity/DingtalkInfo.java new file mode 100644 index 0000000..7c42e5d --- /dev/null +++ b/src/main/java/com/gs/xky/entity/DingtalkInfo.java @@ -0,0 +1,39 @@ +package com.gs.xky.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @TableName DINGTALK_INFO + */ +@TableName(value = "DINGTALK_INFO") +@Data +public class DingtalkInfo implements Serializable { + @TableField(exist = false) + private static final long serialVersionUID = 1L; + /** + * SEQ_DingTalk + */ + @TableId + private Long id; + /** + * 鑱屽伐id + */ + private Long sid; + /** + * 鐢佃瘽 + */ + private String phone; + /** + * 閽夐拤id + */ + private String dingtalkId; + /** + * 閽夐拤閫氱煡 + */ + private Integer isSendDingtalk; +} \ No newline at end of file diff --git a/src/main/java/com/gs/xky/entity/DingtalkMsg.java b/src/main/java/com/gs/xky/entity/DingtalkMsg.java new file mode 100644 index 0000000..b12dbb0 --- /dev/null +++ b/src/main/java/com/gs/xky/entity/DingtalkMsg.java @@ -0,0 +1,46 @@ +package com.gs.xky.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @TableName DINGTALK_MSG + */ +@TableName(value = "DINGTALK_MSG") +@Data +public class DingtalkMsg implements Serializable { + @TableField(exist = false) + private static final long serialVersionUID = 1L; + /** + * 妫�楠屽崟鍙� + */ + private String releaseNo; + /** + * 渚涘簲鍟� + */ + private String suppName; + /** + * 鏉ユ枡鏃ユ湡 + */ + private Date createDate; + /** + * 椤圭洰 + */ + private String projectCodes; + /** + * 鏂欏彿 + */ + private String itemNo; + /** + * 瀹℃牳浜� + */ + private String fname; + /** + * 澶勭悊鏂瑰紡 + */ + private String fngHandle; +} \ No newline at end of file diff --git a/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java b/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java new file mode 100644 index 0000000..77c635e --- /dev/null +++ b/src/main/java/com/gs/xky/mapper/DingtalkInfoMapper.java @@ -0,0 +1,18 @@ +package com.gs.xky.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gs.xky.entity.DingtalkInfo; + +/** + * @author 28567 + * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淢apper + * @createDate 2025-06-20 16:12:48 + * @Entity com.gs.xky.entity.DingtalkInfo + */ +public interface DingtalkInfoMapper extends BaseMapper<DingtalkInfo> { + +} + + + + diff --git a/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java b/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java new file mode 100644 index 0000000..3dac92c --- /dev/null +++ b/src/main/java/com/gs/xky/mapper/DingtalkMsgMapper.java @@ -0,0 +1,18 @@ +package com.gs.xky.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gs.xky.entity.DingtalkMsg; + +/** + * @author 28567 + * @description 閽堝琛ㄣ�怐INGTALK_MSG銆戠殑鏁版嵁搴撴搷浣淢apper + * @createDate 2025-06-21 10:07:15 + * @Entity com.gs.xky.entity.DingtalkMsg + */ +public interface DingtalkMsgMapper extends BaseMapper<DingtalkMsg> { + +} + + + + diff --git a/src/main/java/com/gs/xky/service/DingtalkInfoService.java b/src/main/java/com/gs/xky/service/DingtalkInfoService.java new file mode 100644 index 0000000..a397591 --- /dev/null +++ b/src/main/java/com/gs/xky/service/DingtalkInfoService.java @@ -0,0 +1,14 @@ +package com.gs.xky.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.gs.xky.entity.DingtalkInfo; + +/** + * @author 28567 + * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淪ervice + * @createDate 2025-06-20 16:12:48 + */ +public interface DingtalkInfoService extends IService<DingtalkInfo> { + + boolean sendMessage(String releaseNo); +} diff --git a/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java b/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java new file mode 100644 index 0000000..7b91468 --- /dev/null +++ b/src/main/java/com/gs/xky/service/Impl/DingtalkInfoServiceImpl.java @@ -0,0 +1,155 @@ +package com.gs.xky.service.Impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request; +import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response; +import com.gs.xky.entity.DingtalkInfo; +import com.gs.xky.entity.DingtalkMsg; +import com.gs.xky.mapper.DingtalkInfoMapper; +import com.gs.xky.mapper.DingtalkMsgMapper; +import com.gs.xky.service.DingtalkInfoService; +import com.gs.xky.service.SimpleExample; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author 28567 + * @description 閽堝琛ㄣ�怐INGTALK_INFO銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇 + * @createDate 2025-06-20 16:12:48 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class DingtalkInfoServiceImpl extends ServiceImpl<DingtalkInfoMapper, DingtalkInfo> + implements DingtalkInfoService { + + private final SimpleExample simpleExample; + private final DingtalkMsgMapper dingtalkMsgMapper; + + @Override + public boolean sendMessage(String releaseNo) { + try { + // 鏌ヨ閽夐拤娑堟伅鍐呭 + LambdaQueryWrapper<DingtalkMsg> msgWrapper = new LambdaQueryWrapper<>(); + msgWrapper.eq(DingtalkMsg::getReleaseNo, releaseNo); + DingtalkMsg dingtalkMsg = dingtalkMsgMapper.selectOne(msgWrapper); + + if (dingtalkMsg == null) { + log.error("鏈壘鍒版楠屽崟鍙蜂负 {} 鐨勯拤閽夋秷鎭唴瀹�", releaseNo); + return false; + } + + // 鏍煎紡鍖栨棩鏈� + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String createDateStr = (dingtalkMsg.getCreateDate() != null) ? + dateFormat.format(dingtalkMsg.getCreateDate()) : "鏈煡"; + + // 鏋勫缓娑堟伅鍐呭 + String message = String.format("渚涘簲鍟哰%s] 鏉ユ枡鏃ユ湡[%s] 椤圭洰[%s] 鏂欏彿[%s]鐨勪笉鍚堟牸妫�楠屽崟琚玔%s]瀹℃壒涓篬%s]锛岃鏌ユ敹!", + dingtalkMsg.getSuppName(), createDateStr, dingtalkMsg.getProjectCodes(), + dingtalkMsg.getItemNo(), dingtalkMsg.getFname(), dingtalkMsg.getFngHandle()); + + // 璋冪敤getDingtalkUserIdList鏂规硶鑾峰彇UserIdList + List<String> userIdList = getDingtalkUserIdList(); + + if (userIdList == null || userIdList.isEmpty()) { + log.warn("娌℃湁闇�瑕佸彂閫侀拤閽夋秷鎭殑鐢ㄦ埛"); + return false; + } + + // 閫氳繃閽夐拤鍙戦�佹秷鎭� + String userIdListStr = String.join(",", userIdList); + + OapiMessageCorpconversationAsyncsendV2Response rsp = sendMessage(userIdListStr, message); + System.out.println(rsp.getBody()); + log.info("鎴愬姛鍙戦�侀拤閽夋秷鎭�: {}", message); + return true; + } catch (Exception e) { + log.error("鍙戦�侀拤閽夋秷鎭け璐�", e); + return false; + } + } + + private List<String> getDingtalkUserIdList() { + try { + LambdaQueryWrapper<DingtalkInfo> wrapper = new LambdaQueryWrapper<>(); + wrapper.ge(DingtalkInfo::getIsSendDingtalk, 1); + List<DingtalkInfo> list = list(wrapper); + + if (list == null || list.isEmpty()) { + return new ArrayList<>(); + } + + // 浣跨敤stream娴佽繃婊ゅ嚭list涓璬ingtalkId涓虹┖鐨勬暟鎹� + List<DingtalkInfo> emptyDingtalkIdList = list.stream() + .filter(info -> !StringUtils.hasText(info.getDingtalkId())) + .collect(Collectors.toList()); + + // 濡傛灉瀛樺湪涓虹┖鐨勬暟鎹氨閫氳繃閽夐拤鐨勬帴鍙h幏鍙栵紝涓篸ingtalkId璧嬪�硷紝骞朵笖鏇存柊鏁版嵁搴� + if (!emptyDingtalkIdList.isEmpty()) { + String accessToken = simpleExample.getAccessToken(); + + for (DingtalkInfo info : emptyDingtalkIdList) { + if (StringUtils.hasText(info.getPhone())) { + try { + // 閫氳繃鎵嬫満鍙疯幏鍙栭拤閽夌敤鎴稩D + com.dingtalk.api.response.OapiV2UserGetbymobileResponse response = + simpleExample.getOapiV2UserGetbymobileResponse(info.getPhone(), accessToken); + + if (response != null && response.getResult() != null) { + info.setDingtalkId(response.getResult().getUserid()); + // 鏇存柊鏁版嵁搴� + updateById(info); + } + } catch (Exception e) { + log.error("鑾峰彇閽夐拤鐢ㄦ埛ID澶辫触锛屾墜鏈哄彿锛歿}", info.getPhone(), e); + } + } + } + } + + // 涓嶅瓨鍦ㄤ负绌虹殑鏁版嵁鎴栬�呭鐞嗗畬绌烘暟鎹悗锛岃繑鍥炴墍鏈夋湁鏁堢殑dingtalkId鍒楄〃 + return list.stream() + .map(DingtalkInfo::getDingtalkId) + .filter(StringUtils::hasText) + .collect(Collectors.toList()); + } catch (Exception e) { + log.error("鑾峰彇閽夐拤鐢ㄦ埛鍒楄〃澶辫触", e); + return new ArrayList<>(); + } + } + + private OapiMessageCorpconversationAsyncsendV2Response sendMessage(String userIdListStr, String message) throws Exception { + + String accessToken = simpleExample.getAccessToken(); + + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"); + OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request(); + request.setAgentId(3917187842L); + request.setUseridList(userIdListStr); + request.setToAllUser(false); + + OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); + msg.setMsgtype("text"); + msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text()); + msg.getText().setContent(message); + request.setMsg(msg); + + return client.execute(request, accessToken); + + } +} + + + + diff --git a/src/main/java/com/gs/xky/service/SimpleExample.java b/src/main/java/com/gs/xky/service/SimpleExample.java new file mode 100644 index 0000000..18f7ee4 --- /dev/null +++ b/src/main/java/com/gs/xky/service/SimpleExample.java @@ -0,0 +1,239 @@ +package com.gs.xky.service; + + +import cn.hutool.core.util.StrUtil; +import com.aliyun.dingtalkoauth2_1_0.Client; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest; +import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse; +import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders; +import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest; +import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOResponse; +import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOResponseBody; +import com.aliyun.tea.TeaException; +import com.aliyun.teaopenapi.models.Config; +import com.aliyun.teautil.Common; +import com.aliyun.teautil.models.RuntimeOptions; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.DingTalkClient; +import com.dingtalk.api.request.OapiRobotSendRequest; +import com.dingtalk.api.request.OapiV2UserGetbymobileRequest; +import com.dingtalk.api.response.OapiRobotSendResponse; +import com.dingtalk.api.response.OapiV2UserGetbymobileResponse; +import com.google.gson.Gson; +import com.gs.xky.config.DataAcquisitionConfiguration; +import com.gs.xky.dto.DingTalkMessage; +import com.gs.xky.dto.DingTalkResponse; +import com.taobao.api.ApiException; +import lombok.RequiredArgsConstructor; +import org.apache.commons.codec.binary.Base64; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.List; + + +/** + * 鍙戦�佷釜浜烘秷鎭� + * + * @author tjx + * @date 2024/11/17 16:18 + */ +@Service +@RequiredArgsConstructor +@Transactional(rollbackFor = Exception.class) +public class SimpleExample { + + /** + * 缇ら噷鏈哄櫒浜哄彂閫佹秷鎭� + * + * @author tjx + * @date 2024/11/18 08:54 + */ + public DingTalkResponse chatSendMessage(String message) throws Exception { + try { + Long timestamp = System.currentTimeMillis(); + System.out.println(timestamp); + String secret = DataAcquisitionConfiguration.TALK_APP_SECRET; + String stringToSign = timestamp + "\n" + secret; + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); + byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); + String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); + System.out.println(sign); + + //sign瀛楁鍜宼imestamp瀛楁蹇呴』鎷兼帴鍒拌姹俇RL涓婏紝鍚﹀垯浼氬嚭鐜� 310000 鐨勯敊璇俊鎭� + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/robot/send?sign=" + sign + "×tamp=" + timestamp); + OapiRobotSendRequest req = new OapiRobotSendRequest(); + /** + * 鍙戦�佹枃鏈秷鎭� + */ + //瀹氫箟鏂囨湰鍐呭 + OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); + text.setContent(message); + //瀹氫箟 @ 瀵硅薄 + OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); + at.setIsAtAll(true); + //璁剧疆娑堟伅绫诲瀷 + req.setMsgtype("text"); + req.setText(text); + req.setAt(at); + OapiRobotSendResponse rsp = client.execute(req, DataAcquisitionConfiguration.CUSTOM_ROBOT_TOKEN); + + Gson gson = new Gson(); + + return gson.fromJson(rsp.getBody(), DingTalkResponse.class); + } catch (ApiException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (InvalidKeyException e) { + throw new RuntimeException(e); + } + + return null; + } + + /** + * 鍙戦�佹秷鎭� + */ + public DingTalkMessage sendMessage(String userIdListStr, String message) throws Exception { + + if (!StrUtil.isNotEmpty(userIdListStr)) { + return new DingTalkMessage(1, 0L, "null"); + } + + String[] strArray = userIdListStr.split(","); + List<String> userIdList = Arrays.asList(strArray); + + String accessToken = getAccessToken(); + + com.aliyun.dingtalkrobot_1_0.Client client1 = createClient1(); + BatchSendOTOHeaders batchSendOTOHeaders = new BatchSendOTOHeaders(); + batchSendOTOHeaders.xAcsDingtalkAccessToken = accessToken; + BatchSendOTORequest batchSendOTORequest = new BatchSendOTORequest() + .setRobotCode("ding7n8fldhylh2rt2l2") + .setUserIds(userIdList) + .setMsgKey("sampleText") + .setMsgParam("{\"content\": \"" + message + "\"}"); + + try { + BatchSendOTOResponse batchSendOTOResponse = client1.batchSendOTOWithOptions(batchSendOTORequest, batchSendOTOHeaders, new RuntimeOptions()); + + BatchSendOTOResponseBody body = batchSendOTOResponse.getBody(); + if (StrUtil.isNotEmpty(body.getProcessQueryKey())) { + return new DingTalkMessage(0, 0L, "null"); + } + + } catch (TeaException err) { + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + System.out.println(err.code); + System.out.println(err.message); + + System.out.println(err.accessDeniedDetail.toString()); + } + + } catch (Exception _err) { + TeaException err = new TeaException(_err.getMessage(), _err); + if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { + System.out.println(err.code); + System.out.println(err.message); + } + + } + + return new DingTalkMessage(1, 0L, "null"); + //return gson.fromJson(rsp.getBody(), DingTalkMessage.class); + } + + /** + * 鑾峰彇 AccessToken + * + * @return AccessToken + * @throws Exception + */ + public String getAccessToken() throws Exception { + Client client = createClient(); + GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest() + .setAppKey(DataAcquisitionConfiguration.TALK_APP_KEY) + .setAppSecret(DataAcquisitionConfiguration.TALK_APP_SECRET); + try { + GetAccessTokenResponse accessToken = client.getAccessToken(getAccessTokenRequest); + return accessToken.body.getAccessToken(); + + } catch (TeaException err) { + if (!Common.empty(err.code) && !Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + System.out.println(err.code); + System.out.println(err.message); + } + } catch (Exception exception) { + TeaException err = new TeaException(exception.getMessage(), exception); + if (!Common.empty(err.code) && !Common.empty(err.message)) { + // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰� + System.out.println(err.code); + System.out.println(err.message); + } + } + return null; + } + + public static com.aliyun.dingtalkrobot_1_0.Client createClient1() throws Exception { + Config config = new Config(); + config.protocol = "https"; + config.regionId = "central"; + return new com.aliyun.dingtalkrobot_1_0.Client(config); + } + + /** + * 浣跨敤 Token 鍒濆鍖栬处鍙稢lient + * + * @return Client + * @throws Exception + */ + public Client createClient() throws Exception { + Config config = new Config(); + config.protocol = "https"; + config.regionId = "central"; + return new Client(config); + } + + + // public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(SendDingtalk s, String accessToken) { +// DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); +// OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); +// req.setMobile(s.getTelephone()); +// req.setSupportExclusiveAccountSearch(true); +// OapiV2UserGetbymobileResponse rsp = null; +// +// try { +// rsp = client.execute(req, accessToken); +// } catch (ApiException e) { +// throw new RuntimeException(e); +// } +// return rsp; +// } + + public OapiV2UserGetbymobileResponse getOapiV2UserGetbymobileResponse(String mobile, String accessToken) { + DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); + OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); + req.setMobile(mobile); + req.setSupportExclusiveAccountSearch(true); + OapiV2UserGetbymobileResponse rsp = null; + + try { + rsp = client.execute(req, accessToken); + } catch (ApiException e) { + throw new RuntimeException(e); + } + return rsp; + } +} diff --git a/src/main/resources/mapper/DingtalkInfoMapper.xml b/src/main/resources/mapper/DingtalkInfoMapper.xml new file mode 100644 index 0000000..89e5bb2 --- /dev/null +++ b/src/main/resources/mapper/DingtalkInfoMapper.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.gs.xky.mapper.DingtalkInfoMapper"> + +</mapper> diff --git a/src/main/resources/mapper/DingtalkMsgMapper.xml b/src/main/resources/mapper/DingtalkMsgMapper.xml new file mode 100644 index 0000000..6fa3fdd --- /dev/null +++ b/src/main/resources/mapper/DingtalkMsgMapper.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="com.gs.xky.mapper.DingtalkMsgMapper"> + + <resultMap id="BaseResultMap" type="com.gs.xky.entity.DingtalkMsg"> + <result property="releaseNo" column="RELEASE_NO"/> + <result property="suppName" column="SUPP_NAME"/> + <result property="createDate" column="CREATE_DATE"/> + <result property="projectCodes" column="PROJECT_CODES"/> + <result property="itemNo" column="ITEM_NO"/> + <result property="fname" column="FNAME"/> + <result property="fngHandle" column="FNG_HANDLE"/> + </resultMap> + + <sql id="Base_Column_List"> + RELEASE_NO,SUPP_NAME,CREATE_DATE,PROJECT_CODES,ITEM_NO,FNAME, + FNG_HANDLE + </sql> +</mapper> diff --git a/src/test/java/com/gs/xky/XkyApplicationTests.java b/src/test/java/com/gs/xky/XkyApplicationTests.java index 8f2383f..9caa7ad 100644 --- a/src/test/java/com/gs/xky/XkyApplicationTests.java +++ b/src/test/java/com/gs/xky/XkyApplicationTests.java @@ -40,6 +40,8 @@ private MesInvItemArnService invItemArnService; @Autowired private PurchaseService service; + @Autowired + private DingtalkInfoService dingtalkInfoService; @Test void contextLoads() throws IOException { @@ -58,7 +60,7 @@ @Test void cs() throws IOException { - String str = "22250529195E;22250529EQHY;22250529HCM9;222505304W8Q;222505305XRK;22250530F6UC;22250530JQ31;22250531UF8T;222506013N09;222506015051;2225060152A2;2225060152EN;222506015AM7;222506015U07;2225060162K4;222506016C4C;222506017GEM;222506017YTU;222506019RWD;22250601A216;22250601C4C3;22250601GTT8;22250601GUGU;22250601H6Y7;22250601JN9X;22250601JVW5;22250601L6R5;22250601NANG;22250601NHK4;22250601NYAL;22250601Q669;22250601RGJX;22250601VCE2;22250601W6C6;22250601WFK1;22250601WH28;22250601XE2T;22250602M0MU;"; + String str = "2225060624DY;"; String[] split = str.split(";"); @@ -157,8 +159,9 @@ } @Test - void cs3() throws IOException { + void cs3() throws Exception { + dingtalkInfoService.sendMessage("CGJY20250412166"); -// service.syncPurchaseOrderDetails(); + } } \ No newline at end of file diff --git a/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java b/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java new file mode 100644 index 0000000..de0fda2 --- /dev/null +++ b/src/test/java/com/gs/xky/controller/DingtalkControllerTest.java @@ -0,0 +1,108 @@ +package com.gs.xky.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.gs.xky.dto.NumbericalDto; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * DingtalkController娴嬭瘯绫� + * + * @author 28567 + * @description 娴嬭瘯閽夐拤娑堟伅鍙戦�佹帴鍙� + * @createDate 2025-01-27 + */ +@WebMvcTest(DingtalkController.class) +public class DingtalkControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private com.gs.xky.service.DingtalkInfoService dingtalkInfoService; + + @Autowired + private ObjectMapper objectMapper; + + @Test + public void testSendMessage_Success() throws Exception { + // 鍑嗗娴嬭瘯鏁版嵁 + NumbericalDto requestDto = new NumbericalDto(); + requestDto.setReleaseNo("IQC202501270001"); + + // Mock鏈嶅姟灞傝繑鍥炴垚鍔� + when(dingtalkInfoService.sendMessage(anyString())).thenReturn(true); + + // 鎵ц娴嬭瘯 + mockMvc.perform(post("/api/dingtalk/sendMessage") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andExpect(jsonPath("$.successful").value(0)) + .andExpect(jsonPath("$.data").value("鎺ユ敹鎴愬姛")); + } + + @Test + public void testSendMessage_Failure() throws Exception { + // 鍑嗗娴嬭瘯鏁版嵁 + NumbericalDto requestDto = new NumbericalDto(); + requestDto.setReleaseNo("IQC202501270001"); + + // Mock鏈嶅姟灞傝繑鍥炲け璐� + when(dingtalkInfoService.sendMessage(anyString())).thenReturn(false); + + // 鎵ц娴嬭瘯 + mockMvc.perform(post("/api/dingtalk/sendMessage") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(500)) + .andExpect(jsonPath("$.successful").value(1)) + .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触")); + } + + @Test + public void testSendMessage_EmptyReleaseNo() throws Exception { + // 鍑嗗娴嬭瘯鏁版嵁 - 绌虹殑妫�楠屽崟鍙� + NumbericalDto requestDto = new NumbericalDto(); + requestDto.setReleaseNo(""); + + // 鎵ц娴嬭瘯 + mockMvc.perform(post("/api/dingtalk/sendMessage") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(500)) + .andExpect(jsonPath("$.message").value("妫�楠屽崟鍙蜂笉鑳戒负绌�")) + .andExpect(jsonPath("$.successful").value(1)) + .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触")); + } + + @Test + public void testSendMessage_NullReleaseNo() throws Exception { + // 鍑嗗娴嬭瘯鏁版嵁 - null妫�楠屽崟鍙� + NumbericalDto requestDto = new NumbericalDto(); + requestDto.setReleaseNo(null); + + // 鎵ц娴嬭瘯 + mockMvc.perform(post("/api/dingtalk/sendMessage") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(500)) + .andExpect(jsonPath("$.message").value("妫�楠屽崟鍙蜂笉鑳戒负绌�")) + .andExpect(jsonPath("$.successful").value(1)) + .andExpect(jsonPath("$.data").value("鎺ユ敹澶辫触")); + } +} \ No newline at end of file -- Gitblit v1.9.3