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 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 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.findEnumByOutTradeNo(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); } }