PaymentAppService.java 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package com.webchat.pay.service;
  2. import com.webchat.common.bean.APIPageResponseBean;
  3. import com.webchat.common.constants.WebConstant;
  4. import com.webchat.common.enums.CommonStatusEnum;
  5. import com.webchat.common.enums.RedisKeyEnum;
  6. import com.webchat.common.service.RedisService;
  7. import com.webchat.common.util.AkSkGenerator;
  8. import com.webchat.common.util.JsonUtil;
  9. import com.webchat.domain.vo.dto.payment.AppAkSkDTO;
  10. import com.webchat.domain.vo.request.payment.CreateAppRequestVO;
  11. import com.webchat.domain.vo.response.payment.AppBaseResponseVO;
  12. import com.webchat.domain.vo.response.payment.CreateAppResponseVO;
  13. import com.webchat.pay.repository.dao.IAppDAO;
  14. import com.webchat.pay.repository.entity.AppEntity;
  15. import org.apache.commons.collections.CollectionUtils;
  16. import org.apache.commons.lang3.ObjectUtils;
  17. import org.apache.commons.lang3.StringUtils;
  18. import org.springframework.beans.BeanUtils;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.data.domain.Page;
  21. import org.springframework.data.domain.PageRequest;
  22. import org.springframework.data.domain.Pageable;
  23. import org.springframework.data.domain.Sort;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.util.Assert;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.stream.Collectors;
  29. @Service
  30. public class PaymentAppService {
  31. @Autowired
  32. private IAppDAO appDAO;
  33. @Autowired
  34. private RedisService redisService;
  35. @Autowired
  36. private AccountService accountService;
  37. /**
  38. * 获取接入方访问凭证,走redis
  39. *
  40. * @param appId
  41. * @return
  42. */
  43. public AppAkSkDTO getAppAkSk(Long appId) {
  44. String akskCacheKey = RedisKeyEnum.PAYMENT_APP_AK_SK_CACHE.getKey();
  45. String cache = redisService.hget(akskCacheKey, String.valueOf(appId));
  46. if (StringUtils.isNotBlank(cache)) {
  47. return JsonUtil.fromJson(cache, AppAkSkDTO.class);
  48. }
  49. return this.refreshAppAkSkCache(appId);
  50. }
  51. /**
  52. * 查询应用详情信息,走redis
  53. *
  54. * @param appId
  55. * @return
  56. */
  57. public AppBaseResponseVO appInfo(Long appId) {
  58. String appCacheKey = this.appCacheKey(appId);
  59. String cache = redisService.get(appCacheKey);
  60. if (StringUtils.isNotBlank(cache)) {
  61. return JsonUtil.fromJson(cache, AppBaseResponseVO.class);
  62. }
  63. // 缓存防止击穿
  64. String defaultCache = redisService.get(defaultAppCacheKey(appId));
  65. if (ObjectUtils.equals(defaultCache, WebConstant.CACHE_NONE)) {
  66. return null;
  67. }
  68. AppBaseResponseVO appBase = this.refreshAppInfoCache(appId);
  69. if (appBase == null) {
  70. this.setDefaultAppCache(appId);
  71. }
  72. return appBase;
  73. }
  74. /**
  75. * 创建应用,接入支付平台
  76. *
  77. * @param createAppRequest
  78. * @return
  79. */
  80. public CreateAppResponseVO saveApp(CreateAppRequestVO createAppRequest) {
  81. /**
  82. * 1. 持久化:创建 Or 更新
  83. */
  84. boolean isFirstCreate = createAppRequest.getId() == null;
  85. AppEntity appEntity = convert(createAppRequest);
  86. String sk = null;
  87. if (isFirstCreate) {
  88. /**
  89. * 首次创建为应用生成支付凭证
  90. */
  91. String ak = AkSkGenerator.generateAk();
  92. sk = AkSkGenerator.generateSk();
  93. String secretHashKey = AkSkGenerator.hashKey(sk);
  94. appEntity.setAccessKey(ak);
  95. appEntity.setSecretHashKey(secretHashKey);
  96. }
  97. appEntity = appDAO.save(appEntity);
  98. /**
  99. * 2. 创建缓存
  100. */
  101. this.createOrUpdateRedisCache(appEntity);
  102. /**
  103. * 3. 构造应用信息页面响应VO
  104. */
  105. AppBaseResponseVO appBaseResponseVO = covertResponseVo(appEntity);;
  106. CreateAppResponseVO createAppResponseVO = new CreateAppResponseVO();
  107. BeanUtils.copyProperties(appBaseResponseVO, createAppResponseVO);
  108. createAppResponseVO.setSecretKey(sk);
  109. createAppResponseVO.setAdminInfo(accountService.accountInfo(appEntity.getAdmin()));
  110. return createAppResponseVO;
  111. }
  112. /**
  113. * 发布应用
  114. * @param appId
  115. */
  116. public void publishApp(Long appId) {
  117. this.updateAppStatus(appId, CommonStatusEnum.PUBLISHED);
  118. }
  119. /**
  120. * 删除应用
  121. * @param appId
  122. */
  123. public void deleteApp(Long appId) {
  124. this.updateAppStatus(appId, CommonStatusEnum.DELETED);
  125. }
  126. private void updateAppStatus(Long appId, CommonStatusEnum status) {
  127. AppEntity appEntity = appDAO.findById(appId).orElse(null);
  128. Assert.notNull(appEntity, "状态修改失败: 应用不存在");
  129. appEntity.setStatus(status.getStatusCode());
  130. appDAO.save(appEntity);
  131. // 刷新应用详情信息缓存
  132. this.refreshAppInfoCache(appEntity);
  133. }
  134. /**
  135. * 查询应用列表
  136. *
  137. * @param keywords
  138. * @param pageNo
  139. * @param pageSize
  140. * @return
  141. */
  142. public APIPageResponseBean<AppBaseResponseVO> page(String keywords, Integer pageNo, Integer pageSize) {
  143. Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));
  144. List<Integer> statusList = new ArrayList<>();
  145. statusList.add(CommonStatusEnum.NEW.getStatusCode());
  146. statusList.add(CommonStatusEnum.PUBLISHED.getStatusCode());
  147. Page<AppEntity> appEntities;
  148. if (StringUtils.isBlank(keywords)) {
  149. appEntities = appDAO.findAllByStatusIn(statusList, pageable);
  150. } else {
  151. appEntities = appDAO.findAllByNameLikeAndStatusIn("%" + keywords + "%", statusList, pageable);
  152. }
  153. List<AppBaseResponseVO> vos = new ArrayList<>();
  154. if (appEntities != null && CollectionUtils.isNotEmpty(appEntities.getContent())) {
  155. vos = appEntities.getContent().stream().map(this::covertResponseVo).collect(Collectors.toList());
  156. }
  157. return APIPageResponseBean.success(pageNo, pageSize, appEntities.getTotalElements(), vos);
  158. }
  159. private AppBaseResponseVO covertResponseVo(AppEntity appEntity) {
  160. AppBaseResponseVO response = new AppBaseResponseVO();
  161. BeanUtils.copyProperties(appEntity, response);
  162. return response;
  163. }
  164. /**
  165. * 创建或者更新应用信息Redis缓存
  166. */
  167. private void createOrUpdateRedisCache(AppEntity appEntity) {
  168. // 1. 刷新应用最新详情缓存
  169. this.refreshAppInfoCache(appEntity);
  170. // 2. 创建或更新AK-SK缓存
  171. this.refreshAppAkSkCache(appEntity.getId(), appEntity.getAccessKey(), appEntity.getSecretHashKey());
  172. }
  173. /**
  174. * 刷新应用访问支付平台凭证缓存
  175. *
  176. * @param appId
  177. * @return
  178. */
  179. private AppAkSkDTO refreshAppAkSkCache(Long appId) {
  180. AppEntity app = appDAO.findById(appId).orElse(null);
  181. return this.refreshAppAkSkCache(app.getId(), app.getAccessKey(), app.getSecretHashKey());
  182. }
  183. private AppAkSkDTO refreshAppAkSkCache(Long appId, String accessKey, String secretHashKey) {
  184. String akskCacheKey = RedisKeyEnum.PAYMENT_APP_AK_SK_CACHE.getKey();
  185. AppAkSkDTO appAkSkDTO = new AppAkSkDTO(accessKey, secretHashKey);
  186. redisService.hset(akskCacheKey,
  187. String.valueOf(appId), JsonUtil.toJsonString(appAkSkDTO),
  188. RedisKeyEnum.PAYMENT_APP_AK_SK_CACHE.getExpireTime());
  189. return appAkSkDTO;
  190. }
  191. private void setDefaultAppCache(Long appId) {
  192. String defaultKey = this.defaultAppCacheKey(appId);
  193. redisService.set(defaultKey, WebConstant.CACHE_NONE, RedisKeyEnum.PAYMENT_DEFAULT_APP_INFO_CACHE.getExpireTime());
  194. }
  195. private AppBaseResponseVO refreshAppInfoCache(Long appId) {
  196. AppEntity appEntity = appDAO.findById(appId).orElse(null);
  197. return this.refreshAppInfoCache(appEntity);
  198. }
  199. /**
  200. * 刷新应用信息详情缓存
  201. *
  202. * @param appEntity
  203. * @return
  204. */
  205. private AppBaseResponseVO refreshAppInfoCache(AppEntity appEntity) {
  206. if (appEntity == null) {
  207. return null;
  208. }
  209. AppBaseResponseVO appBaseResponseVO = this.covertResponseVo(appEntity);
  210. String appCacheKey = this.appCacheKey(appEntity.getId());
  211. redisService.set(appCacheKey, JsonUtil.toJsonString(appBaseResponseVO),
  212. RedisKeyEnum.PAYMENT_APP_INFO_CACHE.getExpireTime());
  213. return appBaseResponseVO;
  214. }
  215. private String defaultAppCacheKey(Long appId) {
  216. return RedisKeyEnum.PAYMENT_DEFAULT_APP_INFO_CACHE.getKey(String.valueOf(appId));
  217. }
  218. private String appCacheKey(Long appId) {
  219. return RedisKeyEnum.PAYMENT_APP_INFO_CACHE.getKey(String.valueOf(appId));
  220. }
  221. private AppEntity convert(CreateAppRequestVO createAppRequest) {
  222. AppEntity appEntity;
  223. if (createAppRequest.getId() != null) {
  224. appEntity = appDAO.findById(createAppRequest.getId()).orElse(null);
  225. Assert.notNull(appEntity, "应用信息更新失败:应用不存在!");
  226. } else {
  227. appEntity = new AppEntity();
  228. appEntity.setAdmin(createAppRequest.getUserId());
  229. appEntity.setCreateBy(createAppRequest.getUserId());
  230. // 后面改成默认新建状态
  231. appEntity.setStatus(CommonStatusEnum.NEW.getStatusCode());
  232. }
  233. appEntity.setLogo(createAppRequest.getLogo());
  234. appEntity.setName(createAppRequest.getName());
  235. appEntity.setDescription(createAppRequest.getDescription());
  236. appEntity.setUpdateBy(createAppRequest.getUserId());
  237. return appEntity;
  238. }
  239. }