You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					154 lines
				
				5.9 KiB
			
		
		
			
		
	
	
					154 lines
				
				5.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								package com.ynxbd.common.service.cache;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.bean.enums.MerchantEnum;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.bean.pay.Order;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.bean.pay.Recipe;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.config.EhCacheConfig;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.helper.common.DateHelper;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.helper.timer.TimerManager;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.service.PayService;
							 | 
						||
| 
								 | 
							
								import com.ynxbd.common.service.RecipeService;
							 | 
						||
| 
								 | 
							
								import lombok.extern.slf4j.Slf4j;
							 | 
						||
| 
								 | 
							
								import org.apache.commons.lang3.ObjectUtils;
							 | 
						||
| 
								 | 
							
								import org.ehcache.Cache;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import java.util.Timer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								@Slf4j
							 | 
						||
| 
								 | 
							
								public class PayCache {
							 | 
						||
| 
								 | 
							
								    private PayCache() {
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    static {
							 | 
						||
| 
								 | 
							
								        createAccessTokenCache();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // 缓存
							 | 
						||
| 
								 | 
							
								    private static Cache<String, Recipe> RECIPE_ORDER_CACHE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private static Timer RECIPE_TIMER = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private synchronized static void createAccessTokenCache() {
							 | 
						||
| 
								 | 
							
								        if (RECIPE_ORDER_CACHE == null) {
							 | 
						||
| 
								 | 
							
								            RECIPE_ORDER_CACHE = EhCacheConfig.createCacheTTL(String.class, Recipe.class, "recipe_order_cache", (60 * 30L)); // 半小时
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public synchronized static void putRecipeCache(String tradeNo, Recipe recipe) {
							 | 
						||
| 
								 | 
							
								        if (RECIPE_ORDER_CACHE == null) {
							 | 
						||
| 
								 | 
							
								            createAccessTokenCache();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (ObjectUtils.isEmpty(tradeNo)) {
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (recipe == null) {
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (RECIPE_ORDER_CACHE.containsKey(tradeNo)) {
							 | 
						||
| 
								 | 
							
								            log.info("[处方]定时器-新增超时订单 tradeNo={}", tradeNo);
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        recipe.setCacheNum(2); // 调用3次
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        log.info("[处方]定时器-新增超时订单 tradeNo={}", tradeNo);
							 | 
						||
| 
								 | 
							
								        RECIPE_ORDER_CACHE.put(tradeNo, recipe);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (RECIPE_TIMER == null) { // 定时器(初始化|被销毁),重新生成
							 | 
						||
| 
								 | 
							
								            init();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    public synchronized static void removeRecipe(String tradeNo) {
							 | 
						||
| 
								 | 
							
								        if (RECIPE_ORDER_CACHE.containsKey(tradeNo)) {
							 | 
						||
| 
								 | 
							
								            RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    private synchronized static void init() {
							 | 
						||
| 
								 | 
							
								        if (RECIPE_TIMER != null) { // 防止定时器重复创建
							 | 
						||
| 
								 | 
							
								            return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        RECIPE_TIMER = TimerManager.setInterval(new TimerManager.TimerMethod() {
							 | 
						||
| 
								 | 
							
								            @Override
							 | 
						||
| 
								 | 
							
								            public void run() {
							 | 
						||
| 
								 | 
							
								                if (DateHelper.inTimeRangeH_m_s("23:55:00", "23:59:59")) {
							 | 
						||
| 
								 | 
							
								                    RECIPE_ORDER_CACHE.clear();
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                RecipeService recipeService = new RecipeService();
							 | 
						||
| 
								 | 
							
								                Recipe errorRecipe;
							 | 
						||
| 
								 | 
							
								                String outTradeNo, tradeNo;
							 | 
						||
| 
								 | 
							
								                Recipe resp;
							 | 
						||
| 
								 | 
							
								                int size = 0;
							 | 
						||
| 
								 | 
							
								                for (Cache.Entry<String, Recipe> cache : RECIPE_ORDER_CACHE) {
							 | 
						||
| 
								 | 
							
								                    size++;
							 | 
						||
| 
								 | 
							
								                    if (size == 200) { // 防止过多请求导致HIS阻塞
							 | 
						||
| 
								 | 
							
								                        log.info("[处方][定时器]超时订单数量超过200,清除当前任务");
							 | 
						||
| 
								 | 
							
								                        RECIPE_ORDER_CACHE.clear();
							 | 
						||
| 
								 | 
							
								                        break;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    errorRecipe = cache.getValue();
							 | 
						||
| 
								 | 
							
								                    tradeNo = cache.getKey();
							 | 
						||
| 
								 | 
							
								                    outTradeNo = errorRecipe.getOutTradeNo();
							 | 
						||
| 
								 | 
							
								                    if (outTradeNo == null || !"500".equals(errorRecipe.getErrorCode())) {
							 | 
						||
| 
								 | 
							
								                        RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								                        continue;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    Order order = PayService.queryOrderByOutTradeNo(outTradeNo, null);
							 | 
						||
| 
								 | 
							
								                    if (!order.isSuccess() || order.isRefund()) { // 订单未找到 | 订单发生退款
							 | 
						||
| 
								 | 
							
								                        log.info("[处方][定时器]订单未找到或发生过退款 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo);
							 | 
						||
| 
								 | 
							
								                        RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								                        continue;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    // HIS处方缴费
							 | 
						||
| 
								 | 
							
								                    MerchantEnum merchantEnum = MerchantEnum.getMerchantEnumByOutTradeNo(outTradeNo);
							 | 
						||
| 
								 | 
							
								                    if (MerchantEnum.ALI.equals(merchantEnum)) {
							 | 
						||
| 
								 | 
							
								                        log.info("[处方]定时器,支付宝订单不处理");
							 | 
						||
| 
								 | 
							
								                        RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								                        continue;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    log.info("[处方][定时器]HIS请求开始 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo);
							 | 
						||
| 
								 | 
							
								                    resp = recipeService.recipeSinglePay(errorRecipe,
							 | 
						||
| 
								 | 
							
								                            DateHelper.getCurDate(), DateHelper.getCurTime(), merchantEnum);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if (resp.isSuccess()) {
							 | 
						||
| 
								 | 
							
								                        RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								                        continue;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if ("500".equals(resp.getErrorCode())) { // 500调用超时
							 | 
						||
| 
								 | 
							
								                        log.info("[处方][定时器]HIS请求超时 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo);
							 | 
						||
| 
								 | 
							
								                        int cacheNum = errorRecipe.getCacheNum();
							 | 
						||
| 
								 | 
							
								                        if (cacheNum <= 0) {
							 | 
						||
| 
								 | 
							
								                            RECIPE_ORDER_CACHE.remove(tradeNo);
							 | 
						||
| 
								 | 
							
								                        } else {
							 | 
						||
| 
								 | 
							
								                            cacheNum--;
							 | 
						||
| 
								 | 
							
								                            errorRecipe.setCacheNum(cacheNum);
							 | 
						||
| 
								 | 
							
								                            RECIPE_ORDER_CACHE.replace(tradeNo, errorRecipe);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    } else {
							 | 
						||
| 
								 | 
							
								                        log.info("[处方][定时器]检测到需手动退费订单 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    try {
							 | 
						||
| 
								 | 
							
								                        Thread.sleep(500);
							 | 
						||
| 
								 | 
							
								                    } catch (Exception e) {
							 | 
						||
| 
								 | 
							
								                        e.printStackTrace();
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (size == 0) { // 数据处理完成,清除定时器
							 | 
						||
| 
								 | 
							
								                    TimerManager.closeTimer(RECIPE_TIMER);
							 | 
						||
| 
								 | 
							
								                    RECIPE_TIMER = null;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }, 120);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |