| 
					
				 | 
			
			
				@@ -26,6 +26,8 @@ import com.google.gson.JsonParser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.tencent.wework.Finance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.json.JSONObject; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.redisson.api.RLock; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.redisson.api.RedissonClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.slf4j.LoggerFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.beans.factory.annotation.Autowired; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.scheduling.annotation.Async; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -82,6 +84,9 @@ public class QwDataCallbackService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private IQwDeptService qwDeptService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private RedissonClient redissonClient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Autowired 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private RedisCache redisCache; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -202,11 +207,39 @@ public class QwDataCallbackService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             if(WelcomeCodeList.getLength() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                 WelcomeCode = WelcomeCodeList.item(0).getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            String qwApiExternal=redisCache.getCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            if (StringUtil.strIsNullOrEmpty(qwApiExternal)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                redisCache.setCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent() ,"1",10, TimeUnit.MINUTES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            String userId = root.getElementsByTagName("UserID").item(0).getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            String externalUserId = root.getElementsByTagName("ExternalUserID").item(0).getTextContent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            String cacheKey = "qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            String lockKey = "lock:qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; // 锁Key(Hash类型,加前缀lock:) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 2. 获取 Redisson 分布式锁 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            RLock lock = redissonClient.getLock(lockKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            boolean isLocked = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 3. 尝试加锁:最多等待 5 秒,锁自动释放时间 15 分钟 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                isLocked = lock.tryLock(5, 15, TimeUnit.MINUTES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if (isLocked) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    // 4. 加锁成功后,再次检查缓存(避免多线程竞争时重复执行业务) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    String qwApiExternal = redisCache.getCacheObject(cacheKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    if (StringUtil.strIsNullOrEmpty(qwApiExternal)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 5. 新增用户 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        } catch (Exception e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            // 7. 业务逻辑失败时,删除缓存 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            redisCache.deleteObject(cacheKey); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } catch (InterruptedException e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                logger.error("中断异常"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } finally { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                // 4. 确保锁最终被释放(只有加锁成功的线程才需要释放) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                if (isLocked && lock.isHeldByCurrentThread()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    lock.unlock(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             break; 
			 |