package com.szwl.service.impl; import cn.hutool.core.util.XmlUtil; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.gson.Gson; import com.szwl.constant.ConfigConsts; import com.szwl.constant.JoinpayConstant; import com.szwl.constant.ResponseCodesEnum; import com.szwl.constant.WXPayConstants; import com.szwl.feign.bean.OrderFeign; import com.szwl.feign.bean.SzwlFeign; import com.szwl.mapper.TWechatPayConfigMapper; import com.szwl.model.bo.JsonMessage; import com.szwl.model.bo.R; import com.szwl.model.bo.ResponseModel; import com.szwl.model.entity.*; import com.szwl.model.utils.PushUtils; import com.szwl.service.*; import com.szwl.utils.HuifuUtils; import com.szwl.utils.IDGenerator; import com.szwl.utils.MyWXPay; import com.szwl.utils.WXPayUtil; import com.szwl.weixin.util.HttpUtils; import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.service.refund.model.AmountReq; import com.wechat.pay.java.service.refund.model.CreateRequest; import com.wechat.pay.java.service.refund.model.Refund; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import static com.wechat.pay.java.service.refund.model.Status.PROCESSING; /** *

* 服务实现类 *

* * @author wuhs * @since 2024-03-07 */ @Service public class TWechatPayConfigServiceImpl extends ServiceImpl implements TWechatPayConfigService { /** * 用户输入密码,尝试30秒内去查询支付结果 */ private static Integer remainingTimeMs = 40000; public static Map configMap = new HashMap<>(); @Autowired SzwlFeign szwlFeign; @Autowired OrderFeign orderFeign; @Autowired TOrderService orderService; @Resource TAlipayConfigService alipayConfigService; @Autowired TEquipmentService equipmentService; @Autowired TOrderDetailsService orderDetailsService; @Override public Config getWechatConfig(Long id) { if(configMap==null){ return null; } return configMap.get(id); } @Override public void initConfig(Long id) { TWechatPayConfig wechatPayConfig = this.getById(id); Config config = new RSAAutoCertificateConfig.Builder() .merchantId(wechatPayConfig.getMerchantId()) .privateKeyFromPath(wechatPayConfig.getPrivateKeyPath()) .merchantSerialNumber(wechatPayConfig.getMerchantSerialNumber()) .apiV3Key(wechatPayConfig.getApiv3key()) .build(); configMap.put(wechatPayConfig.getId(), config); } @Override public String decryptFromResource(Map bodyMap) { // 通知数据 Map resourceMap = (Map) bodyMap.get("resource"); // 数据密文 String ciphertext = resourceMap.get("ciphertext"); // 随机串 String nonce = resourceMap.get("nonce"); // 附加数据 String associatedData = resourceMap.get("associated_data"); List list = this.list(); String plainText = null; for (TWechatPayConfig wechatPayConfig : list) { if(StringUtils.isEmpty(plainText)){ AesUtil aesUtil1 = new AesUtil(wechatPayConfig.getApiv3key().getBytes(StandardCharsets.UTF_8)); try { plainText = aesUtil1.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext); } catch (GeneralSecurityException e) { e.printStackTrace(); } } else { break; } } return plainText; } @Override public JsonMessage carsPay(String clientId, Map productNameMap, String frpCode, HttpServletRequest request) { if(productNameMap==null){ return JsonMessage.error("数据出错"); } StringBuffer note = new StringBuffer(); StringBuffer productName = new StringBuffer(); String productNo = ""; Map productMap = new HashMap<>(); Integer productNumber = 0; TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId)); if(equipment==null||equipment.getId()==null){ return JsonMessage.error("找不到设备"); } BigDecimal price = new BigDecimal("0.00"); TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId())); if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){ for (String key : productNameMap.keySet()) { String entryValue = String.valueOf(productNameMap.get(key)); List value = JSON.parseArray(entryValue, String.class); List promoCodeList = new ArrayList<>(); //1,校验优惠码 if(value.size()>0){ for(String code:value){ if(!code.equals("0")){ TPromoCode promoCode = new TPromoCode(); ResponseModel tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString()); TPromoCode tPromoCode = tPromoCodeResponseModel.getData(); promoCode = tPromoCode; if (tPromoCode == null||tPromoCode.getId()==null) { //不存在 return JsonMessage.success("1"); } Date lastUseDate = null; if (promoCode != null) { lastUseDate = promoCode.getLastUseDate(); } if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) { promoCode.setIsUse("2"); szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2"); //过期 return JsonMessage.success("4"); } if (promoCode.getId() == null) { //不存在 return JsonMessage.success("1"); } if (promoCode.getIsUse().equals("1")) { //被使用 return JsonMessage.success("2"); } if(!promoCode.getAdminId().equals("1")){ if (String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) { } else { //不是本机 return JsonMessage.success("3"); } } if (promoCode.getDiscount() == null) { //旧优惠码 return JsonMessage.success("0"); } if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) { //0折 return JsonMessage.success("0"); } promoCodeList.add(promoCode); } } } String[] productNum = key.split("-"); String productNamea = productNum[0]; String num = productNum[1]; productMap.put(productNamea,Integer.valueOf(num)); productNumber += Integer.valueOf(num); productName.append(productNamea).append("x").append(num).append(","); TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea)); if (product == null) { return JsonMessage.error("找不到商品"); } note.append(productNamea).append("-").append(product.getNo()).append(":"); BigDecimal productPrice = product.getRmbPrice(); productNo = product.getNo(); if(promoCodeList.size()>0){ //有优惠码 BigDecimal onePrice = new BigDecimal("0.00"); int i; for( i = 0;i= 0) { return JsonMessage.error("商品价格异常"); } Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6)); String sn = orderService.initSn(client6); //获取分销 关联设备 TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId()))); String companyType = admin.getCompanyType(); JSONArray altInfo = new JSONArray(); BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN); amount = amount.multiply(new BigDecimal(100)); // String notifyUrl = JoinpayConstant.WECHAT_NOTIFY_URL; // String frpCode = "WEIXIN_NATIVE"; TOrder order = new TOrder(); order.setId(IDGenerator.orderID()); order.setCreateDate(new Date()); order.setModifyDate(new Date()); order.setAdminId(admin.getId()); order.setSn(sn); if(productNumber == 1) { productName.delete(productName.length() - 3, productName.length()); } else { productName.deleteCharAt(productName.length() - 1); } order.setProductName(productName.toString()); order.setPrice(price); order.setClientId(equipment.getClientId()); order.setEquipmentId(equipmentId); order.setFrpCode(frpCode); order.setProductNumber(productNumber); order.setAltInfo(altInfo.toString()); order.setStatus(0); String payPlatform = "3"; order.setPayPlatform(payPlatform); order.setCompanyType(companyType); order.setMachineType(equipment.getMachineType()); order.setProductNo(productNo); if(StringUtils.isNotEmpty(payPlatform)&&payPlatform.equals("1")){ order.setIsSettlement("0"); } order.setNote(note.toString()); // 订单明细表 TOrderDetails orderDetails = new TOrderDetails(); orderDetails.setAdminId(admin.getId()); orderDetails.setEquipmentId(equipmentId); orderDetails.setCreateDate(new Date()); orderDetails.setCompanyType(companyType); orderDetails.setRefundStatus("0"); orderDetails.setMachineType(equipment.getMachineType()); // 添加到订单明细表 for (String key : productMap.keySet()) { Integer productNum = productMap.get(key); TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key)); orderDetails.setProductNo(product.getNo()); orderDetails.setProductName(key); orderDetails.setPrice(product.getRmbPrice()); orderDetails.setProductNumber(productNum); orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum))); orderDetails.setId(HuifuUtils.initDetailsId()); orderDetails.setOrderSn(sn); orderDetailsService.save(orderDetails); } orderService.save(order); String productName1 = ""; if(productNumber > 1) { productName1 = "棉花糖"; } else { productName1 = productName.toString(); } String result = null; try { if (frpCode.equals(ConfigConsts.WECHAT_NATIVE)) { result = orderService.wechatPay( sn, amount, productName1, admin.getWechatPayId(), JoinpayConstant.WECHAT_NOTIFY_URL, clientId, request ); } if (frpCode.equals(ConfigConsts.ALIPAY_NATIVE)) { result = orderService.alipayPay( sn, price, productName1, admin.getAlipayId(), JoinpayConstant.ALIPAY_NOTIFY_URL, clientId ); } } catch (Exception e) { e.printStackTrace(); return JsonMessage.error("申请支付失败"); } // 微信支付支付申请返回支付二维码图片 JSONObject kindData = new JSONObject(); kindData.put("sn", sn); kindData.put("code_url", result); return JsonMessage.success(kindData.toString()); } @Override public String payNotify(HttpServletRequest request) { Gson gson = new Gson(); // 读取请求体中的数据 String body = HttpUtils.readData(request); Map bodyMap = gson.fromJson(body, HashMap.class); // 解密支付通知数据 String plainText = this.decryptFromResource(bodyMap); if(StringUtils.isNotEmpty(plainText)){ JSONObject resultJson = JSONObject.parseObject(plainText); // 根据订单号查询订单 String sn = resultJson.getString("out_trade_no"); if(StringUtils.isNotEmpty(sn)) { LambdaQueryWrapper query = Wrappers.lambdaQuery(); query.eq(TOrder::getSn, sn); query.eq(TOrder::getStatus, 0); List list = orderService.list(query); // 更新订单状态和支付信息 if (list != null && list.size() > 0) { TOrder order = list.get(0); order.setStatus(1); String success_time = resultJson.getString("success_time"); Date date = new Date(); try { date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(success_time); } catch (ParseException e) { // 忽略时间转换错误 } order.setPayDate(date); order.setTrxNo(resultJson.getString("transaction_id")); // 更新订单明细状态 LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn); List orderDetails = orderDetailsService.list(lambdaQueryWrapper); for (TOrderDetails orderDetail : orderDetails) { orderDetail.setRefundStatus("1"); orderDetailsService.updateById(orderDetail); } // 发送支付成功消息给设备 TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId())); JSONObject kindData = new JSONObject(); kindData.put("sn", order.getSn()); kindData.put("productName", order.getProductName()); if (!order.getIsNotified().equals("1")) { String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString()); if (paySuccess.equals("success")) { order.setIsNotified("1"); } // 推送微信订单 TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId()))); // 判断是否开启订单推送功能 if(admin != null && StringUtils.isNotEmpty(admin.getOrderNotice()) && admin.getOrderNotice().equals("1")) { String openId = R.getDataIfSuccess(szwlFeign.getOpenId(order.getAdminId())); // 获取openId if(StringUtils.isNotEmpty(openId)) { orderService.newSendWechatMessage(openId, equipment, order, admin.getCompanyType()); } } } orderService.updateById(order); try { // 保存订单信息到ES if(order.getProductNumber()==null||order.getProductNumber()==0){ order.setProductNumber(1); } orderFeign.saveToEs(order); }catch (Exception e) { e.printStackTrace(); } } else { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); query.eq(TOrder::getSn, sn); query.eq(TOrder::getStatus, 1); List orderList = orderService.list(queryWrapper); if (list != null && list.size() > 0) { TOrder tOrder = orderList.get(0); try { // 保存订单信息到ES if(tOrder.getProductNumber()==null||tOrder.getProductNumber()==0){ tOrder.setProductNumber(1); } orderFeign.saveToEs(tOrder); }catch (Exception e) { e.printStackTrace(); } return "success"; } return "fail"; } } } return "success"; } @Override public ResponseModel refund(TOrder torder){ // 退款金额: refusePrice BigDecimal refusePrice = torder.getPrice().setScale(2, RoundingMode.HALF_DOWN); // 退款数量: refundNumber Integer refundNumber = torder.getProductNumber(); // 退款原因: refundReason String refundReason = torder.getRefundReason(); // 退款明细:note String note = torder.getNote(); String[] refundDetails = note.split(","); Map refundMap = new HashMap<>(); for (String refundDetail : refundDetails) { String[] keyValue = refundDetail.split("-"); String key = keyValue[0]; String value = keyValue[1]; refundMap.put(key, Integer.valueOf(value)); } if(refusePrice.compareTo(new BigDecimal("0.00"))<=0){ return R.fail(ResponseCodesEnum.A0001,"退款金额非法"); } TOrder order = orderService.getById(torder.getId()); if(order.getRefundQuantity() != null && order.getRefundQuantity()>0) { order.setRefundQuantity(refundNumber + order.getRefundQuantity()); } else { order.setRefundQuantity(refundNumber); } if(refusePrice.compareTo(order.getPrice()) > 0) { return R.fail(ResponseCodesEnum.A0001,"退款金额非法"); } if(order.getRefundAmount() != null && order.getRefundAmount().add(refusePrice).compareTo(order.getPrice()) > 0) { return R.fail(ResponseCodesEnum.A0001,"退款金额非法"); } if (order.getStatus().equals("0")) { return R.fail(ResponseCodesEnum.A0002,"订单非支付状态"); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(TOrderDetails::getOrderSn, order.getSn()); List orderDetails = orderDetailsService.list(wrapper); // 微信支付 TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(order.getAdminId()))); if (order.getFrpCode().equals("WEIXIN_PAYCODE") || order.getFrpCode().equals("WEIXIN_NATIVE")) { CreateRequest createRequest = new CreateRequest(); createRequest.setOutTradeNo(order.getSn()); AmountReq amount = new AmountReq(); amount.setRefund(refusePrice.multiply(new BigDecimal(100)).longValue()); BigDecimal multiply = order.getPrice().multiply(new BigDecimal(100)); amount.setTotal(multiply.longValue()); amount.setCurrency("CNY"); createRequest.setAmount(amount); String refundNo = orderService.initSn(order.getEquipmentId()); createRequest.setOutRefundNo(refundNo); // 上线需要修改回调url createRequest.setNotifyUrl(JoinpayConstant.WECHAT_NOTIFY_REFUND_URL); Refund refund = orderService.weixinRefundApi(createRequest, admin.getWechatPayId()); System.out.println("退款参数"+refund.toString()); if(refund.getStatus() == PROCESSING){ order.setStatus(2); order.setRefundReason(refundReason); orderService.updateById(order); // 修改订单明细 for (TOrderDetails orderDetail : orderDetails) { String productNo = orderDetail.getProductNo(); Integer productNumber = refundMap.get(productNo); if(productNumber != null) { // 退款中 orderDetail.setRefundStatus("4"); // 退款数量 orderDetail.setRefundQuantity(productNumber); // 退款金额 orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber))); orderDetailsService.updateById(orderDetail); } } return R.ok("申请退款已成功"); } } // 支付宝支付 if(order.getFrpCode().equals("ALIPAY_NATIVE")) { // 随机生成退款交易号 String refundTrxNo = HuifuUtils.initRefundTrxNo(); String refundAlipay = alipayConfigService.refundAlipay(refusePrice, order.getSn(), refundTrxNo, admin.getAlipayId()); if(refundAlipay.equals("success")) { order.setRefundReason(refundReason); // 已退款 if(order.getRefundQuantity() < order.getProductNumber()) { order.setStatus(1); } else { order.setStatus(3); } // 退款金额 BigDecimal refundAmount = order.getRefundAmount(); BigDecimal price = order.getPrice(); if(refundAmount != null) { if (price.compareTo(refundAmount) == 0) { order.setRefundAmount(refundAmount); } else { order.setRefundAmount(refundAmount.add(refusePrice)); } } else { order.setRefundAmount(refusePrice); } order.setRefundDate(new Date()); order.setModifyDate(new Date()); order.setRefundTrxNo(refundTrxNo); // 修改订单明细 for (TOrderDetails orderDetail : orderDetails) { String productNo = orderDetail.getProductNo(); Integer productNumber = refundMap.get(productNo); if(productNumber != null) { // 退款数量 orderDetail.setRefundQuantity(productNumber); // 退款状态 if(productNumber < orderDetail.getProductNumber()) { // 部分退款 orderDetail.setRefundStatus("2"); } else { // 全部退款 orderDetail.setRefundStatus("3"); } // 退款金额 orderDetail.setRefundAmount(orderDetail.getPrice().multiply(new BigDecimal(productNumber))); orderDetailsService.updateById(orderDetail); } } try { orderFeign.saveToEs(order); }catch (Exception e) { e.printStackTrace(); }finally { orderService.updateById(order); } return R.ok("申请退款已成功"); } } return R.fail(ResponseCodesEnum.B0001,"申请退款失败,请重试"); } @Override public String refundNotify(HttpServletRequest request, HttpServletResponse response) { Gson gson = new Gson(); Map hashMap = new HashMap<>(3); try { // 处理退款通知参数 String body = HttpUtils.readData(request); Map bodyMap = gson.fromJson(body, HashMap.class); String eventType = (String)bodyMap.get("event_type"); if (eventType.equals("REFUND.SUCCESS")) { // 处理退款单 processRefund(bodyMap); //成功应答 response.setStatus(HttpStatus.SC_OK); hashMap.put("code", "SUCCESS"); } else { response.setStatus(HttpStatus.SC_BAD_GATEWAY); hashMap.put("code", "FAIL"); hashMap.put("message", "系统错误"); } return gson.toJson(hashMap); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public JsonMessage cardPay(String authCode, String clientId, Map productNameMap, HttpServletRequest request) { if(productNameMap==null){ return JsonMessage.error("数据出错"); } StringBuilder note = new StringBuilder(); StringBuilder productName = new StringBuilder(); String productNo = ""; Map productMap = new HashMap<>(); int productNumber = 0; TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(clientId)); if(equipment==null||equipment.getId()==null){ return JsonMessage.error("找不到设备"); } BigDecimal price = new BigDecimal("0.00"); TEquipmentDesc equipmentDesc = R.getDataIfSuccess(szwlFeign.findEquipmentById(equipment.getId())); if(equipmentDesc==null||equipmentDesc.getEquipmentId()==null||equipmentDesc.getPayType()==null||equipmentDesc.getPayType().equals("0")){ for (String key : productNameMap.keySet()) { String entryValue = String.valueOf(productNameMap.get(key)); List value = JSON.parseArray(entryValue, String.class); List promoCodeList = new ArrayList<>(); //1,校验优惠码 if(value.size()>0){ for(String code:value){ if(!code.equals("0")){ TPromoCode promoCode = new TPromoCode(); ResponseModel tPromoCodeResponseModel = szwlFeign.selectTPromoCode(code, equipment.getAdminId().toString()); TPromoCode tPromoCode = tPromoCodeResponseModel.getData(); promoCode = tPromoCode; if (tPromoCode == null||tPromoCode.getId()==null) { //不存在 return JsonMessage.success("1"); } Date lastUseDate = null; if (promoCode != null) { lastUseDate = promoCode.getLastUseDate(); } if (lastUseDate != null && lastUseDate.getTime() < ((new Date()).getTime())) { promoCode.setIsUse("2"); szwlFeign.updatePromoCode(String.valueOf(promoCode.getId()),"2"); //过期 return JsonMessage.success("4"); } if (promoCode.getId() == null) { //不存在 return JsonMessage.success("1"); } if (promoCode.getIsUse().equals("1")) { //被使用 return JsonMessage.success("2"); } if(!promoCode.getAdminId().equals("1")){ if (!String.valueOf(equipment.getAdminId()).equals(promoCode.getAdminId())) { return JsonMessage.success("3"); } } if (promoCode.getDiscount() == null) { //旧优惠码 return JsonMessage.success("0"); } if (promoCode.getDiscount() != null && promoCode.getDiscount() == 0) { //0折 return JsonMessage.success("0"); } promoCodeList.add(promoCode); } } } String[] productNum = key.split("-"); String productNamea = productNum[0]; String num = productNum[1]; productMap.put(productNamea,Integer.valueOf(num)); productNumber += Integer.parseInt(num); productName.append(productNamea).append("x").append(num).append(","); TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), productNamea)); if (product == null) { return JsonMessage.error("找不到商品"); } note.append(productNamea).append("-").append(product.getNo()).append(":"); BigDecimal productPrice = product.getRmbPrice(); productNo = product.getNo(); if(promoCodeList.size()>0){ //有优惠码 BigDecimal onePrice = new BigDecimal("0.00"); int i; for( i = 0;i= 0) { return JsonMessage.error("商品价格异常"); } Long client6 = Long.parseLong(clientId.substring(clientId.length() - 6)); String sn = orderService.initSn(client6); //获取分销 关联设备 TAdmin admin = R.getDataIfSuccess(szwlFeign.getAdmin(String.valueOf(equipment.getAdminId()))); String companyType = admin.getCompanyType(); BigDecimal amount = price.setScale(2, RoundingMode.HALF_DOWN); amount = amount.multiply(new BigDecimal(100)).setScale(0); String frpCode = "WEIXIN_PAYCODE"; TOrder order = new TOrder(); order.setId(IDGenerator.orderID()); order.setCreateDate(new Date()); order.setModifyDate(new Date()); order.setAdminId(admin.getId()); order.setSn(sn); if(productNumber == 1) { productName.delete(productName.length() - 3, productName.length()); } else { productName.deleteCharAt(productName.length() - 1); } order.setProductName(productName.toString()); order.setPrice(price); order.setClientId(equipment.getClientId()); order.setEquipmentId(equipmentId); order.setFrpCode(frpCode); order.setProductNumber(productNumber); order.setStatus(0); String payPlatform = "3"; order.setPayPlatform(payPlatform); order.setCompanyType(companyType); order.setMachineType(equipment.getMachineType()); order.setProductNo(productNo); order.setNote(note.toString()); // 订单明细表 TOrderDetails orderDetails = new TOrderDetails(); orderDetails.setAdminId(admin.getId()); orderDetails.setEquipmentId(equipmentId); orderDetails.setCreateDate(new Date()); orderDetails.setCompanyType(companyType); orderDetails.setRefundStatus("0"); orderDetails.setMachineType(equipment.getMachineType()); // 添加到订单明细表 for (String key : productMap.keySet()) { Integer productNum = productMap.get(key); TProduct product = R.getDataIfSuccess(szwlFeign.getProduct(String.valueOf(equipment.getId()), key)); orderDetails.setProductNo(product.getNo()); orderDetails.setProductName(key); orderDetails.setPrice(product.getRmbPrice()); orderDetails.setProductNumber(productNum); orderDetails.setAmount(product.getRmbPrice().multiply(new BigDecimal(productNum))); orderDetails.setId(HuifuUtils.initDetailsId()); orderDetails.setOrderSn(sn); orderDetailsService.save(orderDetails); } orderService.save(order); String productName1 = ""; if(productNumber > 1) { productName1 = "棉花糖"; } else { productName1 = productName.toString(); } String result; try { result = wechatCardPay( sn, amount, authCode, productName1, admin.getWechatPayId(), clientId, request ); } catch (Exception e) { e.printStackTrace(); return JsonMessage.error("申请支付失败"); } // 微信支付支付申请返回支付二维码图片 if (result.equals(WXPayConstants.SUCCESS)) { JSONObject kindData = new JSONObject(); kindData.put("sn", sn); return JsonMessage.success(kindData.toString()); } else { return JsonMessage.error(result); } } private String wechatCardPay(String sn, BigDecimal amount, String authCode, String productName, Long wechatPayId, String clientId, HttpServletRequest request) throws Exception { TWechatPayConfig wechatPayConfig = getById(wechatPayId); Map resData = new HashMap<>(); resData.put("appid", wechatPayConfig.getAppId()); resData.put("auth_code", authCode); resData.put("body", productName); resData.put("device_info", clientId); resData.put("mch_id", wechatPayConfig.getMerchantId()); resData.put("nonce_str", WXPayUtil.generateNonceStr()); resData.put("out_trade_no", sn); resData.put("spbill_create_ip", "127.0.0.1"); resData.put("total_fee", amount.toString()); String sign = WXPayUtil.generateSignature(resData, wechatPayConfig.getApiv2key()); // 参数转换成xml的String字符串 resData.put("sign", sign); String xmlStr = WXPayUtil.mapToXml(resData); System.out.println("请求参数:" + xmlStr); // 开始时间(毫秒) long startTimestampMs = System.currentTimeMillis(); String responseXml = HttpUtil.post("https://api.mch.weixin.qq.com/pay/micropay", xmlStr); System.out.println("返回参数:" + responseXml); // 再把响应的xml转换成map Map responseMap = XmlUtil.xmlToMap(responseXml); // 先判断 协议字段返回(return_code),再判断 业务返回,最后判断 交易状态(trade_state) // 通信标识,非交易标识 String returnCode = responseMap.get("return_code").toString(); if (WXPayConstants.SUCCESS.equals(returnCode)) { // String errCode = responseMap.get("err_code").toString(); // 余额不足,信用卡失效 // if ("USERPAYING".equals(errCode) || "SYSTEMERROR".equals(errCode) || "BANKERROR".equals(errCode)) { // 查询订单 Map orderQueryMap = null; Map requestData =new HashMap<>(); requestData.put("appid", wechatPayConfig.getAppId()); requestData.put("mch_id", wechatPayConfig.getMerchantId()); requestData.put("out_trade_no", sn); requestData.put("nonce_str", WXPayUtil.generateNonceStr()); String sign1 = WXPayUtil.generateSignature(requestData, wechatPayConfig.getApiv2key()); requestData.put("sign", sign1); String xmlStr1 = WXPayUtil.mapToXml(requestData); // 用户支付中,需要输入密码或系统错误则去重新查询订单API // 每次循环时的当前系统时间 - 开始时记录的时间 > 设定的30秒时间就退出 while (System.currentTimeMillis() - startTimestampMs < remainingTimeMs) { // 商户收银台得到USERPAYING状态后,经过商户后台系统调用【查询订单API】查询实际支付结果。 String responseXml1 = HttpUtil.post("https://api.mch.weixin.qq.com/pay/orderquery", xmlStr1); orderQueryMap = XmlUtil.xmlToMap(responseXml1); String returnCodeForQuery = orderQueryMap.get("return_code").toString(); if (WXPayConstants.SUCCESS.equals(returnCodeForQuery)) { // 通讯成功 String tradeState = orderQueryMap.get("trade_state").toString(); if (WXPayConstants.SUCCESS.equals(tradeState)) { String transactionId = orderQueryMap.get("transaction_id").toString(); String timeEnd = orderQueryMap.get("time_end").toString(); LambdaQueryWrapper query = Wrappers.lambdaQuery(); query.eq(TOrder::getSn, sn); query.eq(TOrder::getStatus, 0); List list = orderService.list(query); // 更新订单状态和支付信息 if (list != null && list.size() > 0) { TOrder order = list.get(0); order.setStatus(1); order.setTrxNo(transactionId); Date date = new Date(); try { date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timeEnd); } catch (ParseException e) { // 忽略时间转换错误 } order.setPayDate(date); // 更新订单明细状态 LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(TOrderDetails::getOrderSn,sn); List orderDetails = orderDetailsService.list(lambdaQueryWrapper); for (TOrderDetails orderDetail : orderDetails) { orderDetail.setRefundStatus("1"); orderDetailsService.updateById(orderDetail); } // 发送支付成功消息给设备 TEquipment equipment = R.getDataIfSuccess(szwlFeign.findEquipmentByClientId(order.getClientId())); JSONObject kindData = new JSONObject(); kindData.put("sn", order.getSn()); kindData.put("productName", order.getProductName()); if (!order.getIsNotified().equals("1")) { String paySuccess = equipmentService.sentMessage(equipment.getClientId(), PushUtils.buildJson("pay_success", kindData.toString()).toString()); if (paySuccess.equals("success")) { order.setIsNotified("1"); } } orderService.updateById(order); try { // 保存订单信息到ES if(order.getProductNumber()==null||order.getProductNumber()==0){ order.setProductNumber(1); } orderFeign.saveToEs(order); }catch (Exception e) { e.printStackTrace(); } // 如果成功了直接将查询结果返回 return tradeState; } } // 如果支付结果仍为USERPAYING,则每隔5秒循环调用【查询订单API】判断实际支付结果 Thread.sleep(5000); } } // 如果用户取消支付或累计90秒用户都未支付,商户收银台退出查询流程后继续调用【撤销订单API】撤销支付交易。 String tradeState = orderQueryMap.get("trade_state").toString(); if ("NOTPAY".equals(tradeState) || "PAYERROR".equals(tradeState)) { String result = ""; // 调用撤销订单接口,并接受返回的结果 try{ result = MyWXPay.cancelOrder(wechatPayConfig.getMerchantId(), wechatPayConfig.getApiCertPath(), "https://api.mch.weixin.qq.com/secapi/pay/reverse", xmlStr1); System.out.println("=======================撤销订单返回数据:" + result); }catch (Exception e){ e.printStackTrace(); } Map reverseMap = XmlUtil.xmlToMap(result); String returnCodeForReverse = reverseMap.get("return_code").toString(); String resultCode = reverseMap.get("result_code").toString(); if (WXPayConstants.SUCCESS.equals(returnCodeForReverse) && WXPayConstants.SUCCESS.equals(resultCode)) { // 如果撤销成功,需要告诉客户端已经撤销订单了 return "用户取消支付或尚未支付,后台已经撤销该订单,请重新支付!"; } } // } } return WXPayConstants.FAIL; } public void processRefund(Map bodyMap) { String decrypt = this.decryptFromResource(bodyMap); Gson gson = new Gson(); Map map = gson.fromJson(decrypt, HashMap.class); String sn = map.get("out_trade_no").toString(); String refundNo = map.get("out_refund_no").toString(); String amount =map.get("amount").toString(); Map amountMap = gson.fromJson(amount, HashMap.class); String refundPrice = amountMap.get("refund").toString(); if(StringUtils.isNotEmpty(sn)){ LambdaQueryWrapper query = Wrappers.lambdaQuery(); query.eq(TOrder::getSn,sn); TOrder order = orderService.getOne(query); if (StringUtils.isNotEmpty(order.getRefundTrxNo()) && order.getRefundTrxNo().equals(refundNo)) { return; } // 已退款 if(order.getRefundQuantity() < order.getProductNumber()) { order.setStatus(1); } else { order.setStatus(3); } // 更改订单明细表 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(TOrderDetails::getOrderSn, sn); // 处理退款中状态的明细 queryWrapper.eq(TOrderDetails::getRefundStatus, "4"); List tOrderDetails = orderDetailsService.list(queryWrapper); for (TOrderDetails tOrderDetail : tOrderDetails) { Integer refundQuantity = tOrderDetail.getRefundQuantity(); Integer productNumber = tOrderDetail.getProductNumber(); if(refundQuantity < productNumber) { // 部分退款 tOrderDetail.setRefundStatus("2"); orderDetailsService.updateById(tOrderDetail); } else { // 全部退款 tOrderDetail.setRefundStatus("3"); orderDetailsService.updateById(tOrderDetail); } } //退款金额要除以100 BigDecimal r4_refundAmount = new BigDecimal(refundPrice).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).setScale(2, RoundingMode.HALF_DOWN); BigDecimal refundAmount = order.getRefundAmount(); BigDecimal price = order.getPrice(); if(refundAmount != null) { if (price.compareTo(refundAmount) == 0) { order.setRefundAmount(refundAmount); } else { order.setRefundAmount(refundAmount.add(r4_refundAmount)); } } else { order.setRefundAmount(r4_refundAmount); } order.setRefundDate(new Date()); order.setModifyDate(new Date()); order.setRefundTrxNo(refundNo); try { orderFeign.saveToEs(order); }catch (Exception e) { e.printStackTrace(); }finally { orderService.updateById(order); } } } }