AdapayMerchantService.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package com.izouma.nineth.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.alibaba.fastjson.serializer.SerializerFeature;
  5. import com.huifu.adapay.Adapay;
  6. import com.huifu.adapay.core.exception.BaseAdaPayException;
  7. import com.huifu.adapay.model.*;
  8. import com.izouma.nineth.config.AdapayProperties;
  9. import com.izouma.nineth.config.EventNames;
  10. import com.izouma.nineth.config.GeneralProperties;
  11. import com.izouma.nineth.domain.AdapayMerchant;
  12. import com.izouma.nineth.dto.PageQuery;
  13. import com.izouma.nineth.dto.adapay.MemberInfo;
  14. import com.izouma.nineth.dto.adapay.PaymentItem;
  15. import com.izouma.nineth.dto.adapay.PaymentList;
  16. import com.izouma.nineth.dto.adapay.SettleAccountsItem;
  17. import com.izouma.nineth.exception.BusinessException;
  18. import com.izouma.nineth.repo.AdapayMerchantRepo;
  19. import com.izouma.nineth.utils.DateTimeUtils;
  20. import com.izouma.nineth.utils.JpaUtils;
  21. import com.izouma.nineth.utils.ObjUtils;
  22. import com.izouma.nineth.utils.SnowflakeIdWorker;
  23. import lombok.AllArgsConstructor;
  24. import lombok.extern.slf4j.Slf4j;
  25. import org.apache.commons.collections.MapUtils;
  26. import org.apache.rocketmq.spring.core.RocketMQTemplate;
  27. import org.springframework.data.domain.Page;
  28. import org.springframework.stereotype.Service;
  29. import javax.annotation.PostConstruct;
  30. import java.time.LocalDate;
  31. import java.util.HashMap;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.concurrent.atomic.AtomicReference;
  35. @Service
  36. @AllArgsConstructor
  37. @Slf4j
  38. public class AdapayMerchantService {
  39. private final AdapayMerchantRepo adapayMerchantRepo;
  40. private final AdapayProperties adapayProperties;
  41. private final RocketMQTemplate rocketMQTemplate;
  42. private final GeneralProperties generalProperties;
  43. @PostConstruct
  44. public void init() {
  45. log.info("init AdapayMerchantService");
  46. for (AdapayMerchant merchant : adapayMerchantRepo.findAll()) {
  47. addMerchant(merchant);
  48. if (merchant.isSelected()) {
  49. try {
  50. select(merchant.getId());
  51. log.info("select merchant success={}", merchant.getName());
  52. } catch (Exception e) {
  53. log.error("select merchant error", e);
  54. }
  55. }
  56. }
  57. }
  58. public Page<AdapayMerchant> all(PageQuery pageQuery) {
  59. return adapayMerchantRepo.findAll(JpaUtils.toSpecification(pageQuery, AdapayMerchant.class), JpaUtils.toPageRequest(pageQuery));
  60. }
  61. public AdapayMerchant save(AdapayMerchant record) {
  62. record = adapayMerchantRepo.save(record);
  63. addMerchant(record);
  64. return record;
  65. }
  66. public AdapayMerchant update(AdapayMerchant record) {
  67. if (record.getId() == null) {
  68. throw new BusinessException("id不能为空");
  69. }
  70. AdapayMerchant orig = adapayMerchantRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
  71. ObjUtils.merge(orig, record);
  72. record = adapayMerchantRepo.save(orig);
  73. addMerchant(record);
  74. return record;
  75. }
  76. public void sendSelectEvent(Long id) {
  77. JSONObject jsonObject = new JSONObject();
  78. jsonObject.put("name", EventNames.SWITCH_ACCOUNT);
  79. jsonObject.put("data", id);
  80. rocketMQTemplate.convertAndSend(generalProperties.getBroadcastEventTopic(), jsonObject);
  81. try {
  82. Thread.sleep(500);
  83. } catch (InterruptedException e) {
  84. e.printStackTrace();
  85. }
  86. }
  87. public void select(Long id) throws Exception {
  88. AdapayMerchant merchant = adapayMerchantRepo.findById(id).orElseThrow(new BusinessException("商户不存在"));
  89. MerConfig merConfig = new MerConfig();
  90. merConfig.setApiKey(merchant.getApiKey());
  91. merConfig.setApiMockKey(merchant.getMockKey());
  92. merConfig.setRSAPrivateKey(merchant.getPrivKey());
  93. merConfig.setRSAPublicKey(merchant.getPublicKey());
  94. Adapay.initWithMerConfig(merConfig);
  95. adapayProperties.setApiKey(merchant.getApiKey());
  96. adapayProperties.setMockKey(merchant.getMockKey());
  97. adapayProperties.setPrivKey(merchant.getPrivKey());
  98. adapayProperties.setPublicKey(merchant.getPublicKey());
  99. adapayProperties.setMerchant(merchant.getName());
  100. adapayProperties.setAppId(merchant.getAppId());
  101. List<AdapayMerchant> list = adapayMerchantRepo.findAll();
  102. list.forEach(m -> m.setSelected(m.getId().equals(id)));
  103. adapayMerchantRepo.saveAll(list);
  104. }
  105. public void addMerchant(AdapayMerchant merchant) {
  106. try {
  107. MerConfig merConfig = new MerConfig();
  108. merConfig.setApiKey(merchant.getApiKey());
  109. merConfig.setApiMockKey(merchant.getMockKey());
  110. merConfig.setRSAPrivateKey(merchant.getPrivKey());
  111. merConfig.setRSAPublicKey(merchant.getPublicKey());
  112. Adapay.addMerConfig(merConfig, merchant.getName());
  113. } catch (Exception e) {
  114. log.error("add Merchant Error", e);
  115. }
  116. }
  117. public void createMemberForAll(String memberId, String tel, String realName, String idno) throws BaseAdaPayException {
  118. AtomicReference<BaseAdaPayException> ex = new AtomicReference<>();
  119. adapayMerchantRepo.findAll().parallelStream().forEach(merchant -> {
  120. try {
  121. createMember(merchant.getName(), merchant.getAppId(), memberId, tel, realName, idno);
  122. } catch (BaseAdaPayException e) {
  123. log.error("createMemberForAll", e);
  124. ex.set(e);
  125. }
  126. });
  127. if (ex.get() != null) {
  128. throw ex.get();
  129. }
  130. }
  131. public void createMember(String merchant, String appId, String memberId, String tel, String realName, String idno) throws BaseAdaPayException {
  132. Map<String, Object> memberParams = new HashMap<>();
  133. memberParams.put("adapay_func_code", "members.realname");
  134. memberParams.put("member_id", memberId);
  135. memberParams.put("app_id", appId);
  136. memberParams.put("tel_no", tel);
  137. memberParams.put("user_name", realName);
  138. memberParams.put("cert_type", "00");
  139. memberParams.put("cert_id", idno);
  140. Map<String, Object> res = AdapayCommon.requestAdapay(memberParams, merchant);
  141. log.info("createMember merchant={} response={}", merchant, JSON.toJSONString(res, SerializerFeature.PrettyFormat));
  142. if (!("succeeded".equals(MapUtils.getString(res, "status"))
  143. || "member_id_exists".equals(MapUtils.getString(res, "error_code")))) {
  144. String errMsg = MapUtils.getString(res, "error_msg");
  145. String errCode = MapUtils.getString(res, "error_code");
  146. log.error("createMember error merchant={} memberId={}", merchant, memberId);
  147. throw new BusinessException(errMsg + "(" + errCode + ")");
  148. }
  149. }
  150. public String createSettleAccountForAll(String memberId, String realName, String idNo, String phone, String bankNo) throws BaseAdaPayException {
  151. String id = null;
  152. for (AdapayMerchant merchant : adapayMerchantRepo.findAll()) {
  153. id = createSettleAccount(merchant.getName(), merchant.getAppId(), memberId, realName, idNo, phone, bankNo);
  154. }
  155. return id;
  156. }
  157. public String createSettleAccount(String merchant, String appId, String memberId, String realName, String idNo, String phone, String bankNo) throws BaseAdaPayException {
  158. Map<String, Object> settleCountParams = new HashMap<>();
  159. Map<String, Object> accountInfo = new HashMap<>();
  160. accountInfo.put("card_id", bankNo);
  161. accountInfo.put("card_name", realName);
  162. accountInfo.put("cert_id", idNo);
  163. accountInfo.put("cert_type", "00");
  164. accountInfo.put("tel_no", phone);
  165. accountInfo.put("bank_acct_type", "2");
  166. settleCountParams.put("member_id", memberId);
  167. settleCountParams.put("app_id", appId);
  168. settleCountParams.put("channel", "bank_account");
  169. settleCountParams.put("account_info", accountInfo);
  170. Map<String, Object> res = SettleAccount.create(settleCountParams, merchant);
  171. log.info("createSettleAccount merchant={} response={}", merchant, JSON.toJSONString(res, SerializerFeature.PrettyFormat));
  172. if (!("succeeded".equals(MapUtils.getString(res, "status"))
  173. || "account_exists".equals(MapUtils.getString(res, "error_code")))) {
  174. String errMsg = MapUtils.getString(res, "error_msg");
  175. String errCode = MapUtils.getString(res, "error_code");
  176. log.error("createSettleAccount error merchant={} memberId={}", merchant, memberId);
  177. throw new BusinessException(errMsg + "(" + errCode + ")");
  178. }
  179. return MapUtils.getString(res, "id");
  180. }
  181. public void delSettleAccountForAll(String memberId) throws BaseAdaPayException {
  182. for (AdapayMerchant merchant : adapayMerchantRepo.findAll()) {
  183. delSettleAccount(merchant.getName(), merchant.getAppId(), memberId);
  184. }
  185. }
  186. public void delSettleAccount(String merchant, String appId, String memberId) throws BaseAdaPayException {
  187. Map<String, Object> memberParams = new HashMap<>();
  188. memberParams.put("member_id", memberId);
  189. memberParams.put("app_id", appId);
  190. Map<String, Object> member = Member.query(memberParams, merchant);
  191. log.info("query member, merchant={} member={} res={}",
  192. merchant, memberId, JSON.toJSONString(member, SerializerFeature.PrettyFormat));
  193. MemberInfo memberInfo = JSON.parseObject(JSON.toJSONString(member), MemberInfo.class);
  194. if ("succeeded".equals(memberInfo.getStatus())) {
  195. if (memberInfo.getSettleAccounts() != null && memberInfo.getSettleAccounts().size() > 0) {
  196. SettleAccountsItem settleAccountsItem = memberInfo.getSettleAccounts().get(0);
  197. Map<String, Object> settleCountParams = new HashMap<>();
  198. settleCountParams.put("settle_account_id", settleAccountsItem.getId());
  199. settleCountParams.put("member_id", memberId);
  200. settleCountParams.put("app_id", appId);
  201. Map<String, Object> settleCount = SettleAccount.delete(settleCountParams, merchant);
  202. log.info("delSettleAccount, merchant={} member={} res={}",
  203. merchant, memberId, JSON.toJSONString(settleCount, SerializerFeature.PrettyFormat));
  204. checkSuccess(settleCount);
  205. }
  206. } else if ("member_not_exists".equals(memberInfo.getErrorCode())) {
  207. log.info("delSettleAccount member_not_exists, merchant={} member={}", merchant, memberId);
  208. } else {
  209. throw new BusinessException(memberInfo.getErrorMsg() + memberInfo.getErrorCode());
  210. }
  211. }
  212. public void queryMembers(String merchant, String appId) {
  213. boolean hasMore = true;
  214. while (hasMore) {
  215. try {
  216. Map<String, Object> memberParams = new HashMap<>(2);
  217. memberParams.put("page_index", "1");
  218. memberParams.put("app_id", appId);
  219. memberParams.put("page_size", "20");
  220. memberParams.put("created_gte", String.valueOf(System.currentTimeMillis() - 5 * 60 * 1000));
  221. memberParams.put("created_lte", String.valueOf(System.currentTimeMillis()));
  222. Map<String, Object> member = Member.queryList(memberParams);
  223. MapUtils.getBoolean(member, "has_more", false);
  224. } catch (Exception e) {
  225. log.error("queryMembers error", e);
  226. hasMore = false;
  227. }
  228. }
  229. }
  230. public Object query(Long merchantId, String id) throws BaseAdaPayException {
  231. AdapayMerchant merchant = adapayMerchantRepo.findById(merchantId).orElseThrow(new BusinessException("商户不存在"));
  232. Map<String, Object> paymentParams = new HashMap<>();
  233. paymentParams.put("app_id", merchant.getAppId());
  234. paymentParams.put("payment_id", id);
  235. Map<String, Object> paymentList = Payment.queryList(paymentParams, merchant.getName());
  236. log.info(JSON.toJSONString(paymentList, SerializerFeature.PrettyFormat));
  237. return paymentList;
  238. }
  239. public Object refund(Long merchantId, String id) throws BaseAdaPayException {
  240. AdapayMerchant merchant = adapayMerchantRepo.findById(merchantId).orElseThrow(new BusinessException("商户不存在"));
  241. Map<String, Object> paymentParams = new HashMap<>();
  242. paymentParams.put("app_id", merchant.getAppId());
  243. paymentParams.put("payment_id", id);
  244. Map<String, Object> res = Payment.queryList(paymentParams, merchant.getName());
  245. log.info(JSON.toJSONString(res, SerializerFeature.PrettyFormat));
  246. PaymentList paymentList = JSON.parseObject(JSON.toJSONString(res), PaymentList.class);
  247. if (paymentList.getPayments() != null && paymentList.getPayments().size() == 1) {
  248. PaymentItem paymentItem = paymentList.getPayments().get(0);
  249. Map<String, Object> refundParams = new HashMap<>();
  250. refundParams.put("refund_amt", paymentItem.getPayAmt());
  251. refundParams.put("refund_order_no", new SnowflakeIdWorker(0, 0).nextId() + "");
  252. Map<String, Object> response = Refund.create(id, refundParams, merchant.getName());
  253. log.info(JSON.toJSONString(response, SerializerFeature.PrettyFormat));
  254. return response;
  255. }
  256. return res;
  257. }
  258. public static void checkSuccess(Map<String, Object> map) {
  259. if (!"succeeded".equals(MapUtils.getString(map, "status"))) {
  260. String errMsg = MapUtils.getString(map, "error_msg");
  261. String errCode = MapUtils.getString(map, "error_code");
  262. throw new BusinessException(errMsg + "(" + errCode + ")");
  263. }
  264. }
  265. public Object querySettle(Long merchantId, LocalDate start, LocalDate end, Long userId) throws BaseAdaPayException {
  266. AdapayMerchant merchant = adapayMerchantRepo.findById(merchantId).orElseThrow(new BusinessException("商户不存在"));
  267. Map<String, Object> queryParams = new HashMap<>(5);
  268. queryParams.put("member_id", userId.toString());
  269. queryParams.put("app_id", merchant.getAppId());
  270. queryParams.put("begin_date", DateTimeUtils.format(start, "yyyyMMdd"));
  271. queryParams.put("end_date", DateTimeUtils.format(end, "yyyyMMdd"));
  272. Map<String, Object> settleCount = SettleAccount.detail(queryParams, merchant.getName());
  273. log.info(JSON.toJSONString(settleCount, SerializerFeature.PrettyFormat));
  274. return settleCount;
  275. }
  276. }