TWechatPayConfigServiceImpl.java 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. package com.szwl.service.impl;
  2. import cn.hutool.core.util.XmlUtil;
  3. import cn.hutool.http.HttpUtil;
  4. import com.alibaba.fastjson.JSON;
  5. import com.alibaba.fastjson.JSONArray;
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  8. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  10. import com.google.gson.Gson;
  11. import com.szwl.constant.ConfigConsts;
  12. import com.szwl.constant.JoinpayConstant;
  13. import com.szwl.constant.ResponseCodesEnum;
  14. import com.szwl.constant.WXPayConstants;
  15. import com.szwl.feign.bean.OrderFeign;
  16. import com.szwl.feign.bean.SzwlFeign;
  17. import com.szwl.mapper.TWechatPayConfigMapper;
  18. import com.szwl.model.bo.JsonMessage;
  19. import com.szwl.model.bo.R;
  20. import com.szwl.model.bo.ResponseModel;
  21. import com.szwl.model.entity.*;
  22. import com.szwl.model.utils.PushUtils;
  23. import com.szwl.service.*;
  24. import com.szwl.utils.HuifuUtils;
  25. import com.szwl.utils.IDGenerator;
  26. import com.szwl.utils.MyWXPay;
  27. import com.szwl.utils.WXPayUtil;
  28. import com.szwl.weixin.util.HttpUtils;
  29. import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
  30. import com.wechat.pay.java.core.Config;
  31. import com.wechat.pay.java.core.RSAAutoCertificateConfig;
  32. import com.wechat.pay.java.service.refund.model.AmountReq;
  33. import com.wechat.pay.java.service.refund.model.CreateRequest;
  34. import com.wechat.pay.java.service.refund.model.Refund;
  35. import org.apache.commons.lang.StringUtils;
  36. import org.apache.http.HttpStatus;
  37. import org.springframework.beans.factory.annotation.Autowired;
  38. import org.springframework.stereotype.Service;
  39. import javax.annotation.Resource;
  40. import javax.servlet.http.HttpServletRequest;
  41. import javax.servlet.http.HttpServletResponse;
  42. import java.math.BigDecimal;
  43. import java.math.RoundingMode;
  44. import java.nio.charset.StandardCharsets;
  45. import java.security.GeneralSecurityException;
  46. import java.text.ParseException;
  47. import java.text.SimpleDateFormat;
  48. import java.util.*;
  49. import static com.wechat.pay.java.service.refund.model.Status.PROCESSING;
  50. /**
  51. * <p>
  52. * 服务实现类
  53. * </p>
  54. *
  55. * @author wuhs
  56. * @since 2024-03-07
  57. */
  58. @Service
  59. public class TWechatPayConfigServiceImpl extends ServiceImpl<TWechatPayConfigMapper, TWechatPayConfig> implements TWechatPayConfigService {
  60. /**
  61. * 用户输入密码,尝试30秒内去查询支付结果
  62. */
  63. private static Integer remainingTimeMs = 40000;
  64. public static Map<Long, Config> configMap = new HashMap<>();
  65. @Autowired
  66. SzwlFeign szwlFeign;
  67. @Autowired
  68. OrderFeign orderFeign;
  69. @Autowired
  70. TOrderService orderService;
  71. @Resource
  72. TAlipayConfigService alipayConfigService;
  73. @Autowired
  74. TEquipmentService equipmentService;
  75. @Autowired
  76. TOrderDetailsService orderDetailsService;
  77. @Override
  78. public Config getWechatConfig(Long id) {
  79. if(configMap==null){
  80. return null;
  81. }
  82. return configMap.get(id);
  83. }
  84. @Override
  85. public void initConfig(Long id) {
  86. TWechatPayConfig wechatPayConfig = this.getById(id);
  87. Config config =
  88. new RSAAutoCertificateConfig.Builder()
  89. .merchantId(wechatPayConfig.getMerchantId())
  90. .privateKeyFromPath(wechatPayConfig.getPrivateKeyPath())
  91. .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber())
  92. .apiV3Key(wechatPayConfig.getApiv3key())
  93. .build();
  94. configMap.put(wechatPayConfig.getId(), config);
  95. }
  96. @Override
  97. public String decryptFromResource(Map<String, Object> bodyMap) {
  98. // 通知数据
  99. Map<String, String> resourceMap = (Map) bodyMap.get("resource");
  100. // 数据密文
  101. String ciphertext = resourceMap.get("ciphertext");
  102. // 随机串
  103. String nonce = resourceMap.get("nonce");
  104. // 附加数据
  105. String associatedData = resourceMap.get("associated_data");
  106. List<TWechatPayConfig> list = this.list();
  107. String plainText = null;
  108. for (TWechatPayConfig wechatPayConfig : list) {
  109. if(StringUtils.isEmpty(plainText)){
  110. AesUtil aesUtil1 = new
  111. AesUtil(wechatPayConfig.getApiv3key().getBytes(StandardCharsets.UTF_8));
  112. try {
  113. plainText = aesUtil1.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
  114. nonce.getBytes(StandardCharsets.UTF_8),
  115. ciphertext);
  116. } catch (GeneralSecurityException e) {
  117. e.printStackTrace();
  118. }
  119. } else {
  120. break;
  121. }
  122. }
  123. return plainText;
  124. }
  125. @Override
  126. public JsonMessage carsPay(String clientId, Map<String, String> productNameMap, String frpCode, HttpServletRequest request) {
  127. if(productNameMap==null){
  128. return JsonMessage.error("数据出错");
  129. }
  130. StringBuffer note = new StringBuffer();
  131. StringBuffer productName = new StringBuffer();
  132. String productNo = "";
  133. Map<String, Integer> productMap = new HashMap<>();
  134. Integer productNumber = 0;
  135. TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
  136. if(equipment==null||equipment.getId()==null){
  137. return JsonMessage.error("找不到设备");
  138. }
  139. BigDecimal price = new BigDecimal("0.00");
  140. TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
  141. if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
  142. for (String key : productNameMap.keySet()) {
  143. String entryValue = String.valueOf(productNameMap.get(key));
  144. List<String> value = JSON.parseArray(entryValue, String.class);
  145. List<TPromoCode> promoCodeList = new ArrayList<>();
  146. //1,校验优惠码
  147. if(value.size()>0){
  148. for(String code:value){
  149. if(!code.equals("0")){
  150. TPromoCode promoCode = new TPromoCode();
  151. ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
  152. TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
  153. promoCode = tPromoCode;
  154. if (tPromoCode == null||tPromoCode.getId()==null) {
  155. //不存在
  156. return JsonMessage.success("1");
  157. }
  158. Date lastUseDate = null;
  159. if (promoCode != null) {
  160. lastUseDate = promoCode.getLastUseDate();
  161. }
  162. if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
  163. promoCode.setIsUse("2");
  164. szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
  165. //过期
  166. return JsonMessage.success("4");
  167. }
  168. if (promoCode.getId() == null) {
  169. //不存在
  170. return JsonMessage.success("1");
  171. }
  172. if (promoCode.getIsUse().equals("1")) {
  173. //被使用
  174. return JsonMessage.success("2");
  175. }
  176. if(!promoCode.getAdminId().equals("1")){
  177. if (String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
  178. } else {
  179. //不是本机
  180. return JsonMessage.success("3");
  181. }
  182. }
  183. if (promoCode.getDiscount() == null) {
  184. //旧优惠码
  185. return JsonMessage.success("0");
  186. }
  187. if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
  188. //0折
  189. return JsonMessage.success("0");
  190. }
  191. promoCodeList.add(promoCode);
  192. }
  193. }
  194. }
  195. String[] productNum = key.split("-");
  196. String productNamea = productNum[0];
  197. String num = productNum[1];
  198. productMap.put(productNamea,Integer.valueOf(num));
  199. productNumber += Integer.valueOf(num);
  200. productName.append(productNamea).append("x").append(num).append(",");
  201. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
  202. if (product == null) {
  203. return JsonMessage.error("找不到商品");
  204. }
  205. note.append(productNamea).append("-").append(product.getNo()).append(":");
  206. BigDecimal productPrice = product.getRmbPrice();
  207. productNo = product.getNo();
  208. if(promoCodeList.size()>0){
  209. //有优惠码
  210. BigDecimal onePrice = new BigDecimal("0.00");
  211. int i;
  212. for( i = 0;i<promoCodeList.size();i++){
  213. BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
  214. BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
  215. price = price.add(price1);
  216. onePrice = onePrice.add(price1);
  217. }
  218. if(i<Integer.valueOf(num)){
  219. int a = Integer.valueOf(num)-i;
  220. BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
  221. price =price.add(price2);
  222. onePrice = onePrice.add(price2);
  223. }
  224. note.append(onePrice).append("-").append(num).append(",");
  225. }else {
  226. //1,type=0,原始设定,没有第二件半价
  227. int a = Integer.valueOf(num);
  228. BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
  229. price =price.add(price2);
  230. note.append(price2).append("-").append(num).append(",");
  231. }
  232. }
  233. }else {
  234. for (String key : productNameMap.keySet()) {
  235. String[] productNum = key.split("-");
  236. String productNamea = productNum[0];
  237. String num = productNum[1];
  238. productMap.put(productNamea,Integer.valueOf(num));
  239. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
  240. productNo = product.getNo();
  241. BigDecimal productPrice = product.getRmbPrice();
  242. productName.append(productNamea).append("x").append(num).append(",");
  243. note.append(productNamea).append("-").append(product.getNo()).append(":");
  244. switch (num) {
  245. case "1":
  246. //1个 0个半价
  247. price =price.add(productPrice);
  248. note.append(price).append("-").append(num).append(",");
  249. break;
  250. case "2":
  251. //2个 1个半价
  252. price =price.add(productPrice);
  253. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  254. note.append(price).append("-").append(num).append(",");
  255. break;
  256. case "3":
  257. //3个 1个半价
  258. price =price.add(productPrice);
  259. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  260. price =price.add(productPrice);
  261. note.append(price).append("-").append(num).append(",");
  262. break;
  263. case "4":
  264. //4个 2个半价
  265. price =price.add(productPrice);
  266. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  267. price =price.add(productPrice);
  268. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  269. note.append(price).append("-").append(num).append(",");
  270. break;
  271. case "5":
  272. //5个 2个半价
  273. price =price.add(productPrice);
  274. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  275. price =price.add(productPrice);
  276. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  277. price =price.add(productPrice);
  278. note.append(price).append("-").append(num).append(",");
  279. break;
  280. }
  281. }
  282. }
  283. Long equipmentId = equipment.getId();
  284. //查找商品
  285. if (BigDecimal.ZERO.compareTo(price) >= 0) {
  286. return JsonMessage.error("商品价格异常");
  287. }
  288. Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
  289. String sn = orderService.initSn(client6);
  290. //获取分销 关联设备
  291. TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
  292. String companyType = admin.getCompanyType();
  293. JSONArray altInfo = new JSONArray();
  294. BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
  295. amount = amount.multiply(new BigDecimal(100));
  296. // String notifyUrl = JoinpayConstant.WECHAT_NOTIFY_URL;
  297. // String frpCode = "WEIXIN_NATIVE";
  298. TOrder order = new TOrder();
  299. order.setId(IDGenerator.orderID());
  300. order.setCreateDate(new Date());
  301. order.setModifyDate(new Date());
  302. order.setAdminId(admin.getId());
  303. order.setSn(sn);
  304. if(productNumber == 1) {
  305. productName.delete(productName.length() - 3, productName.length());
  306. } else {
  307. productName.deleteCharAt(productName.length() - 1);
  308. }
  309. order.setProductName(productName.toString());
  310. order.setPrice(price);
  311. order.setClientId(equipment.getClientId());
  312. order.setEquipmentId(equipmentId);
  313. order.setFrpCode(frpCode);
  314. order.setProductNumber(productNumber);
  315. order.setAltInfo(altInfo.toString());
  316. order.setStatus(0);
  317. String payPlatform = "3";
  318. order.setPayPlatform(payPlatform);
  319. order.setCompanyType(companyType);
  320. order.setMachineType(equipment.getMachineType());
  321. order.setProductNo(productNo);
  322. if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){
  323. order.setIsSettlement("0");
  324. }
  325. order.setNote(note.toString());
  326. // 订单明细表
  327. TOrderDetails orderDetails = new TOrderDetails();
  328. orderDetails.setAdminId(admin.getId());
  329. orderDetails.setEquipmentId(equipmentId);
  330. orderDetails.setCreateDate(new Date());
  331. orderDetails.setCompanyType(companyType);
  332. orderDetails.setRefundStatus("0");
  333. orderDetails.setMachineType(equipment.getMachineType());
  334. // 添加到订单明细表
  335. for (String key : productMap.keySet()) {
  336. Integer productNum = productMap.get(key);
  337. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
  338. orderDetails.setProductNo(product.getNo());
  339. orderDetails.setProductName(key);
  340. orderDetails.setPrice(product.getRmbPrice());
  341. orderDetails.setProductNumber(productNum);
  342. orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
  343. orderDetails.setId(HuifuUtils.initDetailsId());
  344. orderDetails.setOrderSn(sn);
  345. orderDetailsService.save(orderDetails);
  346. }
  347. orderService.save(order);
  348. String productName1 = "";
  349. if(productNumber > 1) {
  350. productName1 = "棉花糖";
  351. } else {
  352. productName1 = productName.toString();
  353. }
  354. String result = null;
  355. try {
  356. if (frpCode.equals(ConfigConsts.WECHAT_NATIVE)) {
  357. result = orderService.wechatPay(
  358. sn, amount, productName1, admin.getWechatPayId(), JoinpayConstant.WECHAT_NOTIFY_URL, clientId, request
  359. );
  360. }
  361. if (frpCode.equals(ConfigConsts.ALIPAY_NATIVE)) {
  362. result = orderService.alipayPay(
  363. sn, price, productName1, admin.getAlipayId(), JoinpayConstant.ALIPAY_NOTIFY_URL, clientId
  364. );
  365. }
  366. } catch (Exception e) {
  367. e.printStackTrace();
  368. return JsonMessage.error("申请支付失败");
  369. }
  370. // 微信支付支付申请返回支付二维码图片
  371. JSONObject kindData = new JSONObject();
  372. kindData.put("sn", sn);
  373. kindData.put("code_url", result);
  374. return JsonMessage.success(kindData.toString());
  375. }
  376. @Override
  377. public String payNotify(HttpServletRequest request) {
  378. Gson gson = new Gson();
  379. // 读取请求体中的数据
  380. String body = HttpUtils.readData(request);
  381. Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
  382. // 解密支付通知数据
  383. String plainText = this.decryptFromResource(bodyMap);
  384. if(StringUtils.isNotEmpty(plainText)){
  385. JSONObject resultJson = JSONObject.parseObject(plainText);
  386. // 根据订单号查询订单
  387. String sn = resultJson.getString("out_trade_no");
  388. if(StringUtils.isNotEmpty(sn)) {
  389. LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
  390. query.eq(TOrder::getSn, sn);
  391. query.eq(TOrder::getStatus, 0);
  392. List<TOrder> list = orderService.list(query);
  393. // 更新订单状态和支付信息
  394. if (list != null && list.size() > 0) {
  395. TOrder order = list.get(0);
  396. order.setStatus(1);
  397. String success_time = resultJson.getString("success_time");
  398. Date date = new Date();
  399. try {
  400. date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(success_time);
  401. } catch (ParseException e) {
  402. // 忽略时间转换错误
  403. }
  404. order.setPayDate(date);
  405. order.setTrxNo(resultJson.getString("transaction_id"));
  406. // 更新订单明细状态
  407. LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
  408. lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
  409. List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
  410. for (TOrderDetails orderDetail : orderDetails) {
  411. orderDetail.setRefundStatus("1");
  412. orderDetailsService.updateById(orderDetail);
  413. }
  414. // 发送支付成功消息给设备
  415. TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
  416. JSONObject kindData = new JSONObject();
  417. kindData.put("sn", order.getSn());
  418. kindData.put("productName", order.getProductName());
  419. if (!order.getIsNotified().equals("1")) {
  420. String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
  421. if (paySuccess.equals("success")) {
  422. order.setIsNotified("1");
  423. }
  424. // 推送微信订单
  425. TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId())));
  426. // 判断是否开启订单推送功能
  427. if(admin != null && StringUtils.isNotEmpty(admin.getOrderNotice()) && admin.getOrderNotice().equals("1")) {
  428. String openId = R.getDataIfSuccess(szwlFeign.getOpenId(order.getAdminId()));
  429. // 获取openId
  430. if(StringUtils.isNotEmpty(openId)) {
  431. orderService.newSendWechatMessage(openId, equipment, order, admin.getCompanyType());
  432. }
  433. }
  434. }
  435. orderService.updateById(order);
  436. try {
  437. // 保存订单信息到ES
  438. if(order.getProductNumber()==null||order.getProductNumber()==0){
  439. order.setProductNumber(1);
  440. }
  441. orderFeign.saveToEs(order);
  442. }catch (Exception e) {
  443. e.printStackTrace();
  444. }
  445. } else {
  446. LambdaQueryWrapper<TOrder> queryWrapper = Wrappers.lambdaQuery();
  447. query.eq(TOrder::getSn, sn);
  448. query.eq(TOrder::getStatus, 1);
  449. List<TOrder> orderList = orderService.list(queryWrapper);
  450. if (list != null && list.size() > 0) {
  451. TOrder tOrder = orderList.get(0);
  452. try {
  453. // 保存订单信息到ES
  454. if(tOrder.getProductNumber()==null||tOrder.getProductNumber()==0){
  455. tOrder.setProductNumber(1);
  456. }
  457. orderFeign.saveToEs(tOrder);
  458. }catch (Exception e) {
  459. e.printStackTrace();
  460. }
  461. return "success";
  462. }
  463. return "fail";
  464. }
  465. }
  466. }
  467. return "success";
  468. }
  469. @Override
  470. public ResponseModel refund(TOrder torder){
  471. // 退款金额: refusePrice
  472. BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN);
  473. // 退款数量: refundNumber
  474. Integer refundNumber = torder.getProductNumber();
  475. // 退款原因: refundReason
  476. String refundReason = torder.getRefundReason();
  477. // 退款明细:note
  478. String note = torder.getNote();
  479. String[] refundDetails = note.split(",");
  480. Map<String, Integer> refundMap = new HashMap<>();
  481. for (String refundDetail : refundDetails) {
  482. String[] keyValue = refundDetail.split("-");
  483. String key = keyValue[0];
  484. String value = keyValue[1];
  485. refundMap.put(key, Integer.valueOf(value));
  486. }
  487. if(refusePrice.compareTo(new BigDecimal("0.00"))<=0){
  488. return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
  489. }
  490. TOrder order = orderService.getById(torder.getId());
  491. if(order.getRefundQuantity() != null && order.getRefundQuantity()>0) {
  492. order.setRefundQuantity(refundNumber + order.getRefundQuantity());
  493. } else {
  494. order.setRefundQuantity(refundNumber);
  495. }
  496. if(refusePrice.compareTo(order.getPrice()) > 0) {
  497. return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
  498. }
  499. if(order.getRefundAmount() != null && order.getRefundAmount().add(refusePrice).compareTo(order.getPrice()) > 0) {
  500. return R.fail(ResponseCodesEnum.A0001,"退款金额非法");
  501. }
  502. if (order.getStatus().equals("0")) {
  503. return R.fail(ResponseCodesEnum.A0002,"订单非支付状态");
  504. }
  505. LambdaQueryWrapper<TOrderDetails> wrapper = new LambdaQueryWrapper<>();
  506. wrapper.eq(TOrderDetails::getOrderSn, order.getSn());
  507. List<TOrderDetails> orderDetails = orderDetailsService.list(wrapper);
  508. // 微信支付
  509. TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId())));
  510. if (order.getFrpCode().equals("WEIXIN_PAYCODE") || order.getFrpCode().equals("WEIXIN_NATIVE")) {
  511. CreateRequest createRequest = new CreateRequest();
  512. createRequest.setOutTradeNo(order.getSn());
  513. AmountReq amount = new AmountReq();
  514. amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue());
  515. BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100));
  516. amount.setTotal(multiply.longValue());
  517. amount.setCurrency("CNY");
  518. createRequest.setAmount(amount);
  519. String refundNo = orderService.initSn(order.getEquipmentId());
  520. createRequest.setOutRefundNo(refundNo);
  521. // 上线需要修改回调url
  522. createRequest.setNotifyUrl(JoinpayConstant.WECHAT_NOTIFY_REFUND_URL);
  523. Refund refund = orderService.weixinRefundApi(createRequest, admin.getWechatPayId());
  524. System.out.println("退款参数"+refund.toString());
  525. if(refund.getStatus() == PROCESSING){
  526. order.setStatus(2);
  527. order.setRefundReason(refundReason);
  528. orderService.updateById(order);
  529. // 修改订单明细
  530. for (TOrderDetails orderDetail : orderDetails) {
  531. String productNo = orderDetail.getProductNo();
  532. Integer productNumber = refundMap.get(productNo);
  533. if(productNumber != null) {
  534. // 退款中
  535. orderDetail.setRefundStatus("4");
  536. // 退款数量
  537. orderDetail.setRefundQuantity(productNumber);
  538. // 退款金额
  539. orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber)));
  540. orderDetailsService.updateById(orderDetail);
  541. }
  542. }
  543. return R.ok("申请退款已成功");
  544. }
  545. }
  546. // 支付宝支付
  547. if(order.getFrpCode().equals("ALIPAY_NATIVE")) {
  548. // 随机生成退款交易号
  549. String refundTrxNo = HuifuUtils.initRefundTrxNo();
  550. String refundAlipay = alipayConfigService.refundAlipay(refusePrice, order.getSn(), refundTrxNo, admin.getAlipayId());
  551. if(refundAlipay.equals("success")) {
  552. order.setRefundReason(refundReason);
  553. // 已退款
  554. if(order.getRefundQuantity() < order.getProductNumber()) {
  555. order.setStatus(1);
  556. } else {
  557. order.setStatus(3);
  558. }
  559. // 退款金额
  560. BigDecimal refundAmount = order.getRefundAmount();
  561. BigDecimal price = order.getPrice();
  562. if(refundAmount != null) {
  563. if (price.compareTo(refundAmount) == 0) {
  564. order.setRefundAmount(refundAmount);
  565. } else {
  566. order.setRefundAmount(refundAmount.add(refusePrice));
  567. }
  568. } else {
  569. order.setRefundAmount(refusePrice);
  570. }
  571. order.setRefundDate(new Date());
  572. order.setModifyDate(new Date());
  573. order.setRefundTrxNo(refundTrxNo);
  574. // 修改订单明细
  575. for (TOrderDetails orderDetail : orderDetails) {
  576. String productNo = orderDetail.getProductNo();
  577. Integer productNumber = refundMap.get(productNo);
  578. if(productNumber != null) {
  579. // 退款数量
  580. orderDetail.setRefundQuantity(productNumber);
  581. // 退款状态
  582. if(productNumber < orderDetail.getProductNumber()) {
  583. // 部分退款
  584. orderDetail.setRefundStatus("2");
  585. } else {
  586. // 全部退款
  587. orderDetail.setRefundStatus("3");
  588. }
  589. // 退款金额
  590. orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber)));
  591. orderDetailsService.updateById(orderDetail);
  592. }
  593. }
  594. try {
  595. orderFeign.saveToEs(order);
  596. }catch (Exception e) {
  597. e.printStackTrace();
  598. }finally {
  599. orderService.updateById(order);
  600. }
  601. return R.ok("申请退款已成功");
  602. }
  603. }
  604. return R.fail(ResponseCodesEnum.B0001,"申请退款失败,请重试");
  605. }
  606. @Override
  607. public String refundNotify(HttpServletRequest request, HttpServletResponse response) {
  608. Gson gson = new Gson();
  609. Map<String, Object> hashMap = new HashMap<>(3);
  610. try {
  611. // 处理退款通知参数
  612. String body = HttpUtils.readData(request);
  613. Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
  614. String eventType = (String)bodyMap.get("event_type");
  615. if (eventType.equals("REFUND.SUCCESS")) {
  616. // 处理退款单
  617. processRefund(bodyMap);
  618. //成功应答
  619. response.setStatus(HttpStatus.SC_OK);
  620. hashMap.put("code", "SUCCESS");
  621. } else {
  622. response.setStatus(HttpStatus.SC_BAD_GATEWAY);
  623. hashMap.put("code", "FAIL");
  624. hashMap.put("message", "系统错误");
  625. }
  626. return gson.toJson(hashMap);
  627. } catch (Exception e) {
  628. e.printStackTrace();
  629. }
  630. return null;
  631. }
  632. @Override
  633. public JsonMessage cardPay(String authCode, String clientId, Map<String, String> productNameMap, HttpServletRequest request) {
  634. if(productNameMap==null){
  635. return JsonMessage.error("数据出错");
  636. }
  637. StringBuilder note = new StringBuilder();
  638. StringBuilder productName = new StringBuilder();
  639. String productNo = "";
  640. Map<String, Integer> productMap = new HashMap<>();
  641. int productNumber = 0;
  642. TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId));
  643. if(equipment==null||equipment.getId()==null){
  644. return JsonMessage.error("找不到设备");
  645. }
  646. BigDecimal price = new BigDecimal("0.00");
  647. TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId()));
  648. if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){
  649. for (String key : productNameMap.keySet()) {
  650. String entryValue = String.valueOf(productNameMap.get(key));
  651. List<String> value = JSON.parseArray(entryValue, String.class);
  652. List<TPromoCode> promoCodeList = new ArrayList<>();
  653. //1,校验优惠码
  654. if(value.size()>0){
  655. for(String code:value){
  656. if(!code.equals("0")){
  657. TPromoCode promoCode = new TPromoCode();
  658. ResponseModel<TPromoCode> tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString());
  659. TPromoCode tPromoCode = tPromoCodeResponseModel.getData();
  660. promoCode = tPromoCode;
  661. if (tPromoCode == null||tPromoCode.getId()==null) {
  662. //不存在
  663. return JsonMessage.success("1");
  664. }
  665. Date lastUseDate = null;
  666. if (promoCode != null) {
  667. lastUseDate = promoCode.getLastUseDate();
  668. }
  669. if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) {
  670. promoCode.setIsUse("2");
  671. szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2");
  672. //过期
  673. return JsonMessage.success("4");
  674. }
  675. if (promoCode.getId() == null) {
  676. //不存在
  677. return JsonMessage.success("1");
  678. }
  679. if (promoCode.getIsUse().equals("1")) {
  680. //被使用
  681. return JsonMessage.success("2");
  682. }
  683. if(!promoCode.getAdminId().equals("1")){
  684. if (!String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) {
  685. return JsonMessage.success("3");
  686. }
  687. }
  688. if (promoCode.getDiscount() == null) {
  689. //旧优惠码
  690. return JsonMessage.success("0");
  691. }
  692. if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) {
  693. //0折
  694. return JsonMessage.success("0");
  695. }
  696. promoCodeList.add(promoCode);
  697. }
  698. }
  699. }
  700. String[] productNum = key.split("-");
  701. String productNamea = productNum[0];
  702. String num = productNum[1];
  703. productMap.put(productNamea,Integer.valueOf(num));
  704. productNumber += Integer.parseInt(num);
  705. productName.append(productNamea).append("x").append(num).append(",");
  706. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
  707. if (product == null) {
  708. return JsonMessage.error("找不到商品");
  709. }
  710. note.append(productNamea).append("-").append(product.getNo()).append(":");
  711. BigDecimal productPrice = product.getRmbPrice();
  712. productNo = product.getNo();
  713. if(promoCodeList.size()>0){
  714. //有优惠码
  715. BigDecimal onePrice = new BigDecimal("0.00");
  716. int i;
  717. for( i = 0;i<promoCodeList.size();i++){
  718. BigDecimal discount = BigDecimal.valueOf(promoCodeList.get(i).getDiscount()).setScale(2, RoundingMode.HALF_DOWN);
  719. BigDecimal price1 = productPrice.multiply(discount).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN);
  720. price = price.add(price1);
  721. onePrice = onePrice.add(price1);
  722. }
  723. if(i<Integer.parseInt(num)){
  724. int a = Integer.parseInt(num)-i;
  725. BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
  726. price =price.add(price2);
  727. onePrice = onePrice.add(price2);
  728. }
  729. note.append(onePrice).append("-").append(num).append(",");
  730. }else {
  731. //1,type=0,原始设定,没有第二件半价
  732. int a = Integer.parseInt(num);
  733. BigDecimal price2 = productPrice.multiply(new BigDecimal(a)).setScale(2, RoundingMode.HALF_DOWN);
  734. price =price.add(price2);
  735. note.append(price2).append("-").append(num).append(",");
  736. }
  737. }
  738. }else {
  739. for (String key : productNameMap.keySet()) {
  740. String[] productNum = key.split("-");
  741. String productNamea = productNum[0];
  742. String num = productNum[1];
  743. productMap.put(productNamea,Integer.valueOf(num));
  744. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea));
  745. productNo = product.getNo();
  746. BigDecimal productPrice = product.getRmbPrice();
  747. productName.append(productNamea).append("x").append(num).append(",");
  748. note.append(productNamea).append("-").append(product.getNo()).append(":");
  749. switch (num) {
  750. case "1":
  751. //1个 0个半价
  752. price =price.add(productPrice);
  753. note.append(price).append("-").append(num).append(",");
  754. break;
  755. case "2":
  756. //2个 1个半价
  757. price =price.add(productPrice);
  758. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  759. note.append(price).append("-").append(num).append(",");
  760. break;
  761. case "3":
  762. //3个 1个半价
  763. price =price.add(productPrice);
  764. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  765. price =price.add(productPrice);
  766. note.append(price).append("-").append(num).append(",");
  767. break;
  768. case "4":
  769. //4个 2个半价
  770. price =price.add(productPrice);
  771. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  772. price =price.add(productPrice);
  773. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  774. note.append(price).append("-").append(num).append(",");
  775. break;
  776. case "5":
  777. //5个 2个半价
  778. price =price.add(productPrice);
  779. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  780. price =price.add(productPrice);
  781. price =price.add(productPrice.multiply(new BigDecimal(5)).divide(new BigDecimal(10)).setScale(2, RoundingMode.HALF_DOWN));
  782. price =price.add(productPrice);
  783. note.append(price).append("-").append(num).append(",");
  784. break;
  785. }
  786. }
  787. }
  788. Long equipmentId = equipment.getId();
  789. //查找商品
  790. if (BigDecimal.ZERO.compareTo(price) >= 0) {
  791. return JsonMessage.error("商品价格异常");
  792. }
  793. Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6));
  794. String sn = orderService.initSn(client6);
  795. //获取分销 关联设备
  796. TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId())));
  797. String companyType = admin.getCompanyType();
  798. BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN);
  799. amount = amount.multiply(new BigDecimal(100)).setScale(0);
  800. String frpCode = "WEIXIN_PAYCODE";
  801. TOrder order = new TOrder();
  802. order.setId(IDGenerator.orderID());
  803. order.setCreateDate(new Date());
  804. order.setModifyDate(new Date());
  805. order.setAdminId(admin.getId());
  806. order.setSn(sn);
  807. if(productNumber == 1) {
  808. productName.delete(productName.length() - 3, productName.length());
  809. } else {
  810. productName.deleteCharAt(productName.length() - 1);
  811. }
  812. order.setProductName(productName.toString());
  813. order.setPrice(price);
  814. order.setClientId(equipment.getClientId());
  815. order.setEquipmentId(equipmentId);
  816. order.setFrpCode(frpCode);
  817. order.setProductNumber(productNumber);
  818. order.setStatus(0);
  819. String payPlatform = "3";
  820. order.setPayPlatform(payPlatform);
  821. order.setCompanyType(companyType);
  822. order.setMachineType(equipment.getMachineType());
  823. order.setProductNo(productNo);
  824. order.setNote(note.toString());
  825. // 订单明细表
  826. TOrderDetails orderDetails = new TOrderDetails();
  827. orderDetails.setAdminId(admin.getId());
  828. orderDetails.setEquipmentId(equipmentId);
  829. orderDetails.setCreateDate(new Date());
  830. orderDetails.setCompanyType(companyType);
  831. orderDetails.setRefundStatus("0");
  832. orderDetails.setMachineType(equipment.getMachineType());
  833. // 添加到订单明细表
  834. for (String key : productMap.keySet()) {
  835. Integer productNum = productMap.get(key);
  836. TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key));
  837. orderDetails.setProductNo(product.getNo());
  838. orderDetails.setProductName(key);
  839. orderDetails.setPrice(product.getRmbPrice());
  840. orderDetails.setProductNumber(productNum);
  841. orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum)));
  842. orderDetails.setId(HuifuUtils.initDetailsId());
  843. orderDetails.setOrderSn(sn);
  844. orderDetailsService.save(orderDetails);
  845. }
  846. orderService.save(order);
  847. String productName1 = "";
  848. if(productNumber > 1) {
  849. productName1 = "棉花糖";
  850. } else {
  851. productName1 = productName.toString();
  852. }
  853. String result;
  854. try {
  855. result = wechatCardPay(
  856. sn, amount, authCode, productName1, admin.getWechatPayId(), clientId, request
  857. );
  858. } catch (Exception e) {
  859. e.printStackTrace();
  860. return JsonMessage.error("申请支付失败");
  861. }
  862. // 微信支付支付申请返回支付二维码图片
  863. if (result.equals(WXPayConstants.SUCCESS)) {
  864. JSONObject kindData = new JSONObject();
  865. kindData.put("sn", sn);
  866. return JsonMessage.success(kindData.toString());
  867. } else {
  868. return JsonMessage.error(result);
  869. }
  870. }
  871. private String wechatCardPay(String sn, BigDecimal amount, String authCode, String productName, Long wechatPayId, String clientId, HttpServletRequest request) throws Exception {
  872. TWechatPayConfig wechatPayConfig = getById(wechatPayId);
  873. Map<String, String> resData = new HashMap<>();
  874. resData.put("appid", wechatPayConfig.getAppId());
  875. resData.put("auth_code", authCode);
  876. resData.put("body", productName);
  877. resData.put("device_info", clientId);
  878. resData.put("mch_id", wechatPayConfig.getMerchantId());
  879. resData.put("nonce_str", WXPayUtil.generateNonceStr());
  880. resData.put("out_trade_no", sn);
  881. resData.put("spbill_create_ip", "127.0.0.1");
  882. resData.put("total_fee", amount.toString());
  883. String sign = WXPayUtil.generateSignature(resData, wechatPayConfig.getApiv2key());
  884. // 参数转换成xml的String字符串
  885. resData.put("sign", sign);
  886. String xmlStr = WXPayUtil.mapToXml(resData);
  887. System.out.println("请求参数:" + xmlStr);
  888. // 开始时间(毫秒)
  889. long startTimestampMs = System.currentTimeMillis();
  890. String responseXml = HttpUtil.post("https://api.mch.weixin.qq.com/pay/micropay", xmlStr);
  891. System.out.println("返回参数:" + responseXml);
  892. // 再把响应的xml转换成map
  893. Map<String, Object> responseMap = XmlUtil.xmlToMap(responseXml);
  894. // 先判断 协议字段返回(return_code),再判断 业务返回,最后判断 交易状态(trade_state)
  895. // 通信标识,非交易标识
  896. String returnCode = responseMap.get("return_code").toString();
  897. if (WXPayConstants.SUCCESS.equals(returnCode)) {
  898. // String errCode = responseMap.get("err_code").toString();
  899. // 余额不足,信用卡失效
  900. // if ("USERPAYING".equals(errCode) || "SYSTEMERROR".equals(errCode) || "BANKERROR".equals(errCode)) {
  901. // 查询订单
  902. Map<String, Object> orderQueryMap = null;
  903. Map<String, String> requestData =new HashMap<>();
  904. requestData.put("appid", wechatPayConfig.getAppId());
  905. requestData.put("mch_id", wechatPayConfig.getMerchantId());
  906. requestData.put("out_trade_no", sn);
  907. requestData.put("nonce_str", WXPayUtil.generateNonceStr());
  908. String sign1 = WXPayUtil.generateSignature(requestData, wechatPayConfig.getApiv2key());
  909. requestData.put("sign", sign1);
  910. String xmlStr1 = WXPayUtil.mapToXml(requestData);
  911. // 用户支付中,需要输入密码或系统错误则去重新查询订单API
  912. // 每次循环时的当前系统时间 - 开始时记录的时间 > 设定的30秒时间就退出
  913. while (System.currentTimeMillis() - startTimestampMs < remainingTimeMs) {
  914. // 商户收银台得到USERPAYING状态后,经过商户后台系统调用【查询订单API】查询实际支付结果。
  915. String responseXml1 = HttpUtil.post("https://api.mch.weixin.qq.com/pay/orderquery", xmlStr1);
  916. orderQueryMap = XmlUtil.xmlToMap(responseXml1);
  917. String returnCodeForQuery = orderQueryMap.get("return_code").toString();
  918. if (WXPayConstants.SUCCESS.equals(returnCodeForQuery)) {
  919. // 通讯成功
  920. String tradeState = orderQueryMap.get("trade_state").toString();
  921. if (WXPayConstants.SUCCESS.equals(tradeState)) {
  922. String transactionId = orderQueryMap.get("transaction_id").toString();
  923. String timeEnd = orderQueryMap.get("time_end").toString();
  924. LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
  925. query.eq(TOrder::getSn, sn);
  926. query.eq(TOrder::getStatus, 0);
  927. List<TOrder> list = orderService.list(query);
  928. // 更新订单状态和支付信息
  929. if (list != null && list.size() > 0) {
  930. TOrder order = list.get(0);
  931. order.setStatus(1);
  932. order.setTrxNo(transactionId);
  933. Date date = new Date();
  934. try {
  935. date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeEnd);
  936. } catch (ParseException e) {
  937. // 忽略时间转换错误
  938. }
  939. order.setPayDate(date);
  940. // 更新订单明细状态
  941. LambdaQueryWrapper<TOrderDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
  942. lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn);
  943. List<TOrderDetails> orderDetails = orderDetailsService.list(lambdaQueryWrapper);
  944. for (TOrderDetails orderDetail : orderDetails) {
  945. orderDetail.setRefundStatus("1");
  946. orderDetailsService.updateById(orderDetail);
  947. }
  948. // 发送支付成功消息给设备
  949. TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId()));
  950. JSONObject kindData = new JSONObject();
  951. kindData.put("sn", order.getSn());
  952. kindData.put("productName", order.getProductName());
  953. if (!order.getIsNotified().equals("1")) {
  954. String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString());
  955. if (paySuccess.equals("success")) {
  956. order.setIsNotified("1");
  957. }
  958. }
  959. orderService.updateById(order);
  960. try {
  961. // 保存订单信息到ES
  962. if(order.getProductNumber()==null||order.getProductNumber()==0){
  963. order.setProductNumber(1);
  964. }
  965. orderFeign.saveToEs(order);
  966. }catch (Exception e) {
  967. e.printStackTrace();
  968. }
  969. // 如果成功了直接将查询结果返回
  970. return tradeState;
  971. }
  972. }
  973. // 如果支付结果仍为USERPAYING,则每隔5秒循环调用【查询订单API】判断实际支付结果
  974. Thread.sleep(5000);
  975. }
  976. }
  977. // 如果用户取消支付或累计90秒用户都未支付,商户收银台退出查询流程后继续调用【撤销订单API】撤销支付交易。
  978. String tradeState = orderQueryMap.get("trade_state").toString();
  979. if ("NOTPAY".equals(tradeState) || "PAYERROR".equals(tradeState)) {
  980. String result = "";
  981. // 调用撤销订单接口,并接受返回的结果
  982. try{
  983. result =
  984. MyWXPay.cancelOrder(wechatPayConfig.getMerchantId(), wechatPayConfig.getApiCertPath(),
  985. "https://api.mch.weixin.qq.com/secapi/pay/reverse", xmlStr1);
  986. System.out.println("=======================撤销订单返回数据:" + result);
  987. }catch (Exception e){
  988. e.printStackTrace();
  989. }
  990. Map<String, Object> reverseMap = XmlUtil.xmlToMap(result);
  991. String returnCodeForReverse = reverseMap.get("return_code").toString();
  992. String resultCode = reverseMap.get("result_code").toString();
  993. if (WXPayConstants.SUCCESS.equals(returnCodeForReverse) && WXPayConstants.SUCCESS.equals(resultCode)) {
  994. // 如果撤销成功,需要告诉客户端已经撤销订单了
  995. return "用户取消支付或尚未支付,后台已经撤销该订单,请重新支付!";
  996. }
  997. }
  998. // }
  999. }
  1000. return WXPayConstants.FAIL;
  1001. }
  1002. public void processRefund(Map<String, Object> bodyMap) {
  1003. String decrypt = this.decryptFromResource(bodyMap);
  1004. Gson gson = new Gson();
  1005. Map<String,Object> map = gson.fromJson(decrypt, HashMap.class);
  1006. String sn = map.get("out_trade_no").toString();
  1007. String refundNo = map.get("out_refund_no").toString();
  1008. String amount =map.get("amount").toString();
  1009. Map<String,Object> amountMap = gson.fromJson(amount, HashMap.class);
  1010. String refundPrice = amountMap.get("refund").toString();
  1011. if(StringUtils.isNotEmpty(sn)){
  1012. LambdaQueryWrapper<TOrder> query = Wrappers.lambdaQuery();
  1013. query.eq(TOrder::getSn,sn);
  1014. TOrder order = orderService.getOne(query);
  1015. if (StringUtils.isNotEmpty(order.getRefundTrxNo()) && order.getRefundTrxNo().equals(refundNo)) {
  1016. return;
  1017. }
  1018. // 已退款
  1019. if(order.getRefundQuantity() < order.getProductNumber()) {
  1020. order.setStatus(1);
  1021. } else {
  1022. order.setStatus(3);
  1023. }
  1024. // 更改订单明细表
  1025. LambdaQueryWrapper<TOrderDetails> queryWrapper = new LambdaQueryWrapper<>();
  1026. queryWrapper.eq(TOrderDetails::getOrderSn, sn);
  1027. // 处理退款中状态的明细
  1028. queryWrapper.eq(TOrderDetails::getRefundStatus, "4");
  1029. List<TOrderDetails> tOrderDetails = orderDetailsService.list(queryWrapper);
  1030. for (TOrderDetails tOrderDetail : tOrderDetails) {
  1031. Integer refundQuantity = tOrderDetail.getRefundQuantity();
  1032. Integer productNumber = tOrderDetail.getProductNumber();
  1033. if(refundQuantity < productNumber) {
  1034. // 部分退款
  1035. tOrderDetail.setRefundStatus("2");
  1036. orderDetailsService.updateById(tOrderDetail);
  1037. } else {
  1038. // 全部退款
  1039. tOrderDetail.setRefundStatus("3");
  1040. orderDetailsService.updateById(tOrderDetail);
  1041. }
  1042. }
  1043. //退款金额要除以100
  1044. BigDecimal r4_refundAmount = new BigDecimal(refundPrice).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).setScale(2, RoundingMode.HALF_DOWN);
  1045. BigDecimal refundAmount = order.getRefundAmount();
  1046. BigDecimal price = order.getPrice();
  1047. if(refundAmount != null) {
  1048. if (price.compareTo(refundAmount) == 0) {
  1049. order.setRefundAmount(refundAmount);
  1050. } else {
  1051. order.setRefundAmount(refundAmount.add(r4_refundAmount));
  1052. }
  1053. } else {
  1054. order.setRefundAmount(r4_refundAmount);
  1055. }
  1056. order.setRefundDate(new Date());
  1057. order.setModifyDate(new Date());
  1058. order.setRefundTrxNo(refundNo);
  1059. try {
  1060. orderFeign.saveToEs(order);
  1061. }catch (Exception e) {
  1062. e.printStackTrace();
  1063. }finally {
  1064. orderService.updateById(order);
  1065. }
  1066. }
  1067. }
  1068. }