TransferFuncServiceImpl.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package com.cyksj.service.pay.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import cn.hutool.json.JSONObject;
  6. import com.alipay.api.AlipayClient;
  7. import com.alipay.api.AlipayRequest;
  8. import com.alipay.api.AlipayResponse;
  9. import com.alipay.api.domain.AlipayFundTransUniTransferModel;
  10. import com.alipay.api.domain.Participant;
  11. import com.alipay.api.request.AlipayFundTransUniTransferRequest;
  12. import com.baomidou.mybatisplus.core.toolkit.Assert;
  13. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  14. import com.cyksj.common.EnvCommonService;
  15. import com.cyksj.common.constant.Constant;
  16. import com.cyksj.common.constant.TransferConstant;
  17. import com.cyksj.common.exception.BusinessRuntimeException;
  18. import com.cyksj.common.snowflake.Sequence;
  19. import com.cyksj.common.util.Jsons;
  20. import com.cyksj.common.util.SmsUtil;
  21. import com.cyksj.config.zfb.AliPayClientFactory;
  22. import com.cyksj.config.zfb.ZfbProductCode;
  23. import com.cyksj.dto.Result;
  24. import com.cyksj.enums.GatewayResponse;
  25. import com.cyksj.mapper.TransferAccountsRecordMapper;
  26. import com.cyksj.mapper.UserMapper;
  27. import com.cyksj.mapper.manage.distribute.DistributeMoneyApplyMapper;
  28. import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
  29. import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
  30. import com.cyksj.mapper.shop.YhShopDistributeMoneyApplyMapper;
  31. import com.cyksj.mapper.shop.YhShopMapper;
  32. import com.cyksj.model.entity.*;
  33. import com.cyksj.model.request.ApplyMoneyReq;
  34. import com.cyksj.model.request.TransferAccountsReq;
  35. import com.cyksj.model.request.YhShopApplyMoneyReq;
  36. import com.cyksj.service.pay.TransferFuncService;
  37. import com.cyksj.service.user.UserBenefitsService;
  38. import lombok.RequiredArgsConstructor;
  39. import lombok.extern.slf4j.Slf4j;
  40. import org.springframework.stereotype.Service;
  41. import java.math.BigDecimal;
  42. import java.math.RoundingMode;
  43. import java.util.Optional;
  44. /*
  45. *项目名: yhlxj
  46. *文件名: TransferFuncServiceImpl
  47. *创建者: JavaZou
  48. *创建时间:2023/9/20 18:55
  49. */
  50. @Service
  51. @RequiredArgsConstructor
  52. @Slf4j
  53. public class TransferFuncServiceImpl implements TransferFuncService {
  54. private static final Sequence SEQUENCE = new Sequence(0);
  55. private final TransferAccountsRecordMapper transferAccountsRecordMapper;
  56. private final YhShopMapper yhShopMapper;
  57. private final UserMapper userMapper;
  58. private final UserBenefitsService userBenefitsService;
  59. private final YhShopDistributeMoneyApplyMapper yhShopDistributeMoneyApplyMapper;
  60. private final EnvCommonService envCommonService;
  61. private final UserDistributeMapper userDistributeMapper;
  62. private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
  63. private final DistributeMoneyApplyMapper distributeMoneyApplyMapper;
  64. @Override
  65. public Result distributeApply(ApplyMoneyReq applyMoneyReq) throws Exception {
  66. applyMoneyReq.setMType(DistributeMoneyApply.MType.ds);
  67. return commonApplyMoney(applyMoneyReq);
  68. }
  69. @Override
  70. public Result yhShopDistributeApply(YhShopApplyMoneyReq applyMoneyReq) throws Exception {
  71. Long userId = applyMoneyReq.getUserId();
  72. User user = userMapper.selectById(userId);
  73. if (user == null) {
  74. throw BusinessRuntimeException.getInstance("请先授权登录");
  75. }
  76. Boolean isTakeAll = applyMoneyReq.getIsTakeAll();
  77. YhShopDistributeMoneyApply.Type type = applyMoneyReq.getType();
  78. if (type == null) type = YhShopDistributeMoneyApply.Type.zfb;
  79. if (type == YhShopDistributeMoneyApply.Type.zfb) {
  80. if (ObjectUtil.hasEmpty(applyMoneyReq.getAccount(), applyMoneyReq.getRealName())) {
  81. throw BusinessRuntimeException.getInstance("必填项不能为空");
  82. }
  83. if (applyMoneyReq.getAccount().length() > 255 || applyMoneyReq.getRealName().length() > 32) {
  84. throw BusinessRuntimeException.getInstance("请输入正确的账户信息");
  85. }
  86. }
  87. if (type == YhShopDistributeMoneyApply.Type.usdt) {
  88. if (StrUtil.isEmpty(applyMoneyReq.getWalletAddr())) {
  89. throw BusinessRuntimeException.getInstance("USDT提现钱包地址不能为空");
  90. }
  91. if (applyMoneyReq.getWalletAddr().length() > 1000) {
  92. throw BusinessRuntimeException.getInstance("请输入正确的钱包地址");
  93. }
  94. if (StrUtil.isNotBlank(applyMoneyReq.getRemark()) && applyMoneyReq.getRemark().length() > 512) {
  95. throw BusinessRuntimeException.getInstance("备注过多");
  96. }
  97. isTakeAll = true;
  98. }
  99. YhShopDistributeMoneyApply distributeMoneyApply = null;
  100. if (type == YhShopDistributeMoneyApply.Type.pwdRed) {
  101. distributeMoneyApply = yhShopMapper.selectRelationBusiness(userId);
  102. isTakeAll = true;
  103. }
  104. BigDecimal needApplyMoney = user.getYhsMoney();
  105. BigDecimal fourHundred = BigDecimal.valueOf(4 * 10000);
  106. if (isTakeAll == null || !isTakeAll) {
  107. if (needApplyMoney.compareTo(fourHundred) > 0) {
  108. needApplyMoney = fourHundred;
  109. }
  110. }
  111. Integer update = userMapper.subYhsMoney(user.getId(), needApplyMoney);
  112. if (update == 1) {
  113. distributeMoneyApply = Optional.ofNullable(distributeMoneyApply).orElse(new YhShopDistributeMoneyApply());
  114. distributeMoneyApply.setUserId(userId);
  115. distributeMoneyApply.setMoney(needApplyMoney);
  116. distributeMoneyApply.setAccount(applyMoneyReq.getAccount());
  117. distributeMoneyApply.setRealName(applyMoneyReq.getRealName());
  118. distributeMoneyApply.setWalletAddr(applyMoneyReq.getWalletAddr());
  119. distributeMoneyApply.setRemark(applyMoneyReq.getRemark());
  120. distributeMoneyApply.setType(applyMoneyReq.getType());
  121. if (isTakeAll != null && isTakeAll) {
  122. distributeMoneyApply.setVerifyStatus(YhShopDistributeMoneyApply.Status.verifying);
  123. } else {
  124. TransferAccountsReq req = new TransferAccountsReq();
  125. req.setMoney(needApplyMoney);
  126. req.setAccount(applyMoneyReq.getAccount());
  127. req.setName(applyMoneyReq.getRealName());
  128. req.setChannelType(2);
  129. req.setUserId(userId);
  130. req.setRemark("小店提现");
  131. AlipayResponse alipayResponse = transferAccounts(req);
  132. if (alipayResponse.isSuccess()) {
  133. distributeMoneyApply.setVerifyStatus(YhShopDistributeMoneyApply.Status.success);
  134. } else {
  135. distributeMoneyApply.setVerifyStatus(YhShopDistributeMoneyApply.Status.fail);
  136. distributeMoneyApply.setReason(alipayResponse.getSubMsg());
  137. userBenefitsService.addYhsMoney(userId, distributeMoneyApply.getMoney());
  138. if (StrUtil.equals(alipayResponse.getSubCode(), "SECURITY_CHECK_FAILED")) {
  139. return GatewayResponse.FAIL.newBuilder().setMsg("当前支付宝提现人数较多,请稍后再试").toResult();
  140. }
  141. return GatewayResponse.FAIL.newBuilder().setMsg("目前财务清账中,48小时后可提现").toResult();
  142. }
  143. }
  144. try {
  145. yhShopDistributeMoneyApplyMapper.insert(distributeMoneyApply);
  146. //大额提现 超过400
  147. if (envCommonService.isPrdEnv() && distributeMoneyApply.getVerifyStatus() == YhShopDistributeMoneyApply.Status.verifying && distributeMoneyApply.getMoney().compareTo(fourHundred) > 0) {
  148. SmsUtil.sendLuoKey2Msg(Constant.ZK_MOBILE, "小店店铺有大额提现申请【银河录像局】");
  149. }
  150. } catch (Exception e) {
  151. userBenefitsService.addYhsMoney(userId, distributeMoneyApply.getMoney());
  152. return GatewayResponse.FAIL.newBuilder().setMsg("网络错误,请重试").toResult();
  153. }
  154. return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply);
  155. }
  156. throw BusinessRuntimeException.getInstance("系统异常,请重新提交提现申请");
  157. }
  158. @Override
  159. public AlipayResponse transferAccounts(TransferAccountsReq transferAccountsReq) throws Exception {
  160. Long userId = transferAccountsReq.getUserId();
  161. String account = transferAccountsReq.getAccount();
  162. String name = transferAccountsReq.getName();
  163. BigDecimal money = transferAccountsReq.getMoney();
  164. String type = transferAccountsReq.getType();
  165. BigDecimal points = transferAccountsReq.getPoints();
  166. Integer channelType = transferAccountsReq.getChannelType();
  167. String remark = transferAccountsReq.getRemark();
  168. /* 生成商户转账订单号 */
  169. String donNo = SEQUENCE.nextId().toString();
  170. if (StrUtil.isEmpty(type)) {
  171. type = TransferConstant.ALIPAY;
  172. }
  173. if (!envCommonService.isPrdEnv()) {
  174. name += "xx";
  175. }
  176. Integer scope = transferAccountsReq.getScope();
  177. AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(ShopConfig.DISTRIBUTE_ZFB_DEFAULT_APP_ID);
  178. AlipayRequest alipayRequest = aliPayTransferAccountsRequest(donNo, account, name, money, remark);
  179. AlipayResponse response = alipayClient.certificateExecute(alipayRequest);
  180. if (response.isSuccess()) {
  181. log.info("支付宝转账金额:{}至用户:{}成功", money.divide(BigDecimal.valueOf(100)), userId);
  182. saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), null, channelType);
  183. return response;
  184. }
  185. log.info("支付宝转账金额:{}至用户:{}失败", money.divide(BigDecimal.valueOf(100)), userId);
  186. saveTransferRecord(userId, donNo, account, name, money, points, type, scope, response.getBody(), response.getSubMsg(), channelType);
  187. return response;
  188. }
  189. @Override
  190. public Result<String> subApplyMoney(ApplyMoneyReq applyMoneyReq) throws Exception {
  191. applyMoneyReq.setMType(DistributeMoneyApply.MType.sub);
  192. return commonApplyMoney(applyMoneyReq);
  193. }
  194. private AlipayRequest aliPayTransferAccountsRequest(String donNo, String account, String name, BigDecimal money, String remark) {
  195. //支付宝转账
  196. AlipayFundTransUniTransferRequest transUniTransferRequest = new AlipayFundTransUniTransferRequest();
  197. //转账参数
  198. AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
  199. model.setOutBizNo(donNo);
  200. //单位元
  201. model.setTransAmount(money.divide(BigDecimal.valueOf(100)).toString());
  202. model.setProductCode(ZfbProductCode.STD_RED_PACKET.getProductCode());
  203. model.setBizScene(TransferConstant.DIRECT_TRANSFER);
  204. model.setOrderTitle(remark);
  205. //红包业务必传,取值REDPACKET
  206. JSONObject businessParams = new JSONObject();
  207. businessParams.putOpt(TransferConstant.SUB_BIZ_SCENE, TransferConstant.RED_PACKET);
  208. model.setBusinessParams(businessParams.toString());
  209. Participant payeeInfo = new Participant();
  210. payeeInfo.setIdentity(account);
  211. payeeInfo.setIdentityType(TransferConstant.ALIPAY_LOGON_ID);
  212. payeeInfo.setName(name);
  213. model.setPayeeInfo(payeeInfo);
  214. model.setRemark("分销提现转账");
  215. transUniTransferRequest.setBizModel(model);
  216. return transUniTransferRequest;
  217. }
  218. public void saveTransferRecord(Long userId, String donNo, String account, String name, BigDecimal money, BigDecimal points, String type, Integer scope, String body, String error, Integer channelType) throws Exception {
  219. TransferAccountsRecord record = new TransferAccountsRecord();
  220. JSONObject re = Jsons.parseObject(body, JSONObject.class);
  221. JSONObject response = Jsons.parseObject(re.get("alipay_fund_trans_uni_transfer_response"), JSONObject.class);
  222. String transactionId = response.getStr("order_id");
  223. String transDate = response.getStr("trans_date");
  224. record.setUserId(userId);
  225. record.setAccount(account);
  226. record.setName(name);
  227. record.setMoney(money);
  228. record.setType(type);
  229. record.setScope(scope);
  230. Optional.ofNullable(error).ifPresent(msg -> {
  231. record.setErrorMsg(msg);
  232. record.setStatus(0);
  233. });
  234. record.setPoints(points);
  235. record.setTransferOutNo(donNo);
  236. record.setTransactionId(transactionId);
  237. Optional.ofNullable(transDate).ifPresent(transferTime -> record.setTransferTime(DateTime.of(transferTime, "yyyy-MM-dd HH:mm:ss")));
  238. transferAccountsRecordMapper.insert(record);
  239. }
  240. public Result commonApplyMoney(ApplyMoneyReq applyMoneyReq) throws Exception {
  241. Long userId = applyMoneyReq.getUserId();
  242. User user = userMapper.selectById(userId);
  243. if (user == null) {
  244. throw BusinessRuntimeException.getInstance("请先授权登录");
  245. }
  246. if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
  247. Boolean isTakeAll = applyMoneyReq.getIsTakeAll();
  248. DistributeMoneyApply.Type type = applyMoneyReq.getType();
  249. if (type == null) type = DistributeMoneyApply.Type.zfb;
  250. if (type == DistributeMoneyApply.Type.zfb) {
  251. if (ObjectUtil.hasEmpty(applyMoneyReq.getAccount(), applyMoneyReq.getRealName())) {
  252. throw BusinessRuntimeException.getInstance("必填项不能为空");
  253. }
  254. if (applyMoneyReq.getAccount().length() > 255 || applyMoneyReq.getRealName().length() > 32) {
  255. throw BusinessRuntimeException.getInstance("请输入正确的账户信息");
  256. }
  257. }
  258. if (type == DistributeMoneyApply.Type.usdt) {
  259. if (StrUtil.isEmpty(applyMoneyReq.getWalletAddr())) {
  260. throw BusinessRuntimeException.getInstance("USDT提现钱包地址不能为空");
  261. }
  262. if (applyMoneyReq.getWalletAddr().length() > 1000) {
  263. throw BusinessRuntimeException.getInstance("请输入正确的钱包地址");
  264. }
  265. if (StrUtil.isNotBlank(applyMoneyReq.getRemark()) && applyMoneyReq.getRemark().length() > 512) {
  266. throw BusinessRuntimeException.getInstance("备注过多");
  267. }
  268. isTakeAll = true;
  269. }
  270. DistributeMoneyApply.MType mType = applyMoneyReq.getMType();
  271. Assert.notNull(mType, "系统异常..");
  272. DistributeMoneyApply distributeMoneyApply = null;
  273. if (type == DistributeMoneyApply.Type.pwdRed) {
  274. distributeMoneyApply = userDistributeMapper.selectRelationBusiness(userId);
  275. isTakeAll = true;
  276. }
  277. // //今日是否已提现
  278. // DistributeMoneyApply apply = distributeMoneyApplyMapper.selectOne(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getUserId, userId).between(DistributeMoneyApply::getCreatedTime, DateUtil.beginOfDay(DateTime.now()), DateUtil.endOfDay(DateTime.now())).last("limit 1"));
  279. // if (apply != null) {
  280. // throw BusinessRuntimeException.getInstance("今日已提现,请明日再进行操作");
  281. // }
  282. BigDecimal userPoints = null;
  283. BigDecimal needSubPoints = null;
  284. BigDecimal needApplyMoney = null;
  285. BigDecimal fourHundred = null;
  286. if (mType == DistributeMoneyApply.MType.ds) {
  287. userPoints = user.getPoints();
  288. DistributePointsExchangeMoney distributePointsExchangeMoney = distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).orderByDesc(DistributePointsExchangeMoney::getPoints).last("limit 1"));
  289. BigDecimal minPoints = BigDecimal.valueOf(distributePointsExchangeMoney.getMinPoints());
  290. BigDecimal ratePoints = BigDecimal.valueOf(distributePointsExchangeMoney.getPoints());
  291. BigDecimal minMoney = distributePointsExchangeMoney.getMoney();
  292. if (userPoints.compareTo(minPoints) < 0) {
  293. throw BusinessRuntimeException.getInstance("您当前积分未达到积分门槛,无法提现");
  294. }
  295. BigDecimal num = userPoints.divide(ratePoints, 0, RoundingMode.DOWN);
  296. needApplyMoney = num.multiply(minMoney);
  297. needSubPoints = num.multiply(ratePoints);
  298. fourHundred = BigDecimal.valueOf(4 * 100 * 100);
  299. if (isTakeAll == null || !isTakeAll) {
  300. if (needApplyMoney.compareTo(fourHundred) > 0) {
  301. needApplyMoney = fourHundred;
  302. needSubPoints = fourHundred.divide(minMoney).multiply(ratePoints);
  303. }
  304. }
  305. }
  306. if (mType == DistributeMoneyApply.MType.sub) {
  307. needApplyMoney = user.getSubApplyMoney();
  308. if (needApplyMoney.compareTo(BigDecimal.ZERO) <= 0) {
  309. throw BusinessRuntimeException.getInstance("您暂无可提现金额..");
  310. }
  311. }
  312. Integer update = 0;
  313. String zfbRemark = StrUtil.EMPTY;
  314. if (mType == DistributeMoneyApply.MType.ds) {
  315. update = userMapper.subPoints(user.getId(), needSubPoints);
  316. zfbRemark = Constant.APPLY_MONEY_DS;
  317. }
  318. if (mType == DistributeMoneyApply.MType.sub) {
  319. update = userMapper.suUserSubApplyMoney(user.getId(), needApplyMoney);
  320. zfbRemark = Constant.APPLY_MONEY_SUB;
  321. }
  322. if (update == 1) {
  323. distributeMoneyApply = Optional.ofNullable(distributeMoneyApply).orElse(new DistributeMoneyApply());
  324. distributeMoneyApply.setUserId(userId);
  325. distributeMoneyApply.setPoints(needSubPoints);
  326. distributeMoneyApply.setMoney(needApplyMoney);
  327. distributeMoneyApply.setAccount(applyMoneyReq.getAccount());
  328. distributeMoneyApply.setRealName(applyMoneyReq.getRealName());
  329. distributeMoneyApply.setWalletAddr(applyMoneyReq.getWalletAddr());
  330. distributeMoneyApply.setRemark(applyMoneyReq.getRemark());
  331. distributeMoneyApply.setType(applyMoneyReq.getType());
  332. distributeMoneyApply.setMType(applyMoneyReq.getMType());
  333. if (isTakeAll != null && isTakeAll) {
  334. distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.verifying);
  335. } else {
  336. TransferAccountsReq req = new TransferAccountsReq();
  337. req.setMoney(needApplyMoney);
  338. req.setAccount(applyMoneyReq.getAccount());
  339. req.setName(applyMoneyReq.getRealName());
  340. req.setPoints(needSubPoints);
  341. req.setUserId(userId);
  342. req.setChannelType(1);
  343. req.setRemark(zfbRemark);
  344. AlipayResponse alipayResponse = transferAccounts(req);
  345. if (alipayResponse.isSuccess()) {
  346. distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.success);
  347. } else {
  348. distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.fail);
  349. distributeMoneyApply.setReason(alipayResponse.getSubMsg());
  350. if (mType == DistributeMoneyApply.MType.ds){
  351. userBenefitsService.addDistributePoints(userId, distributeMoneyApply.getPoints());
  352. }
  353. if (mType == DistributeMoneyApply.MType.sub) {
  354. userBenefitsService.addDistributeSubMoney(userId, needApplyMoney);
  355. }
  356. if (StrUtil.equals(alipayResponse.getSubCode(), "SECURITY_CHECK_FAILED")) {
  357. return GatewayResponse.FAIL.newBuilder().setMsg("当前支付宝提现人数较多,请稍后再试").toResult();
  358. }
  359. return GatewayResponse.FAIL.newBuilder().setMsg("目前财务清账中,48小时后可提现").toResult();
  360. }
  361. }
  362. try {
  363. distributeMoneyApplyMapper.insert(distributeMoneyApply);
  364. //大额提现 超过400
  365. if (envCommonService.isPrdEnv() && distributeMoneyApply.getVerifyStatus() == DistributeMoneyApply.Status.verifying && distributeMoneyApply.getMoney().compareTo(fourHundred) > 0) {
  366. SmsUtil.sendLuoKey2Msg(Constant.ZK_MOBILE, "推广有大额提现申请【银河录像局】");
  367. }
  368. } catch (Exception e) {
  369. userBenefitsService.addDistributePoints(userId, distributeMoneyApply.getPoints());
  370. return GatewayResponse.FAIL.newBuilder().setMsg("网络错误,请重试").toResult();
  371. }
  372. return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply);
  373. }
  374. throw BusinessRuntimeException.getInstance("系统异常,请重新提交提现申请");
  375. }
  376. }