package com.ruoyi.order.service.impl; import com.alibaba.fastjson2.JSON; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradeRefundRequest; import com.alipay.api.response.AlipayTradeRefundResponse; 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.jpay.ext.kit.PaymentKit; import com.jpay.weixin.api.WxPayApi; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.enums.BondStatusEnum; import com.ruoyi.common.core.enums.OrderStatusEnum; import com.ruoyi.common.core.enums.PaymentMethodEnum; import com.ruoyi.common.core.enums.PointStatusEnum; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.order.domain.Paylog; import com.ruoyi.order.mapper.OrderAuctionBondMapper; import com.ruoyi.order.mapper.OrderMapper; import com.ruoyi.order.mapper.PaylogMapper; import com.ruoyi.order.service.IPaylogService; import com.ruoyi.order.util.MD5AndKL; import com.ruoyi.order.util.SinataUtil; import com.ruoyi.order.util.alipay.config.AlipayConfig; import com.ruoyi.order.util.alipay.util.PayDemoActivity; import com.ruoyi.order.util.tencent.common.Configure; import com.ruoyi.order.util.tencent.common.XMLParser; import com.ruoyi.system.api.domain.GoodsGroupPurchase; import com.ruoyi.system.api.domain.GoodsGroupPurchaseInfo; import com.ruoyi.system.api.domain.GoodsSku; import com.ruoyi.system.api.domain.Member; import com.ruoyi.system.api.domain.Order; import com.ruoyi.system.api.domain.OrderAuctionBond; import com.ruoyi.system.api.domain.dto.MemberPointsDTO; import com.ruoyi.system.api.domain.dto.RefundDTO; import com.ruoyi.system.api.domain.dto.updMembeOneDTO; import com.ruoyi.system.api.feignClient.AuctionClient; import com.ruoyi.system.api.feignClient.GoodsSkuClient; import com.ruoyi.system.api.feignClient.MemberClient; import java.io.IOException; import java.io.PrintWriter; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; /** *

* 支付记录 服务实现类 *

* * @author mitao * @since 2024-05-22 */ @Slf4j @Service public class PaylogServiceImpl extends ServiceImpl implements IPaylogService { @Resource private OrderMapper OrderMapper; @Resource private AuctionClient auctionClient; @Resource private MemberClient memberClient; @Resource private OrderAuctionBondMapper orderAuctionBondMapper; @Resource private GoodsSkuClient goodsSkuClient; @Resource private PaylogMapper paylogMapper; @Override public R> getPayInfo(Long uid, Integer type, String orderNO, String openId, HttpServletRequest request) { PaymentMethodEnum paymentMethodEnum = type == 1 ? PaymentMethodEnum.ALIPAY : PaymentMethodEnum.WECHAT; Member member = memberClient.getMembeOne(uid, SecurityConstants.INNER).getData(); openId = member.getMiniOpenid(); String zfbOpenid = member.getZfbOpenid(); Double price = 0.0; String subject; String body; try { if(judgeContainsStr(orderNO)){ if (orderNO.contains("BO")) { LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(OrderAuctionBond::getOrderNo,orderNO); wrapper1.eq(OrderAuctionBond::getDelFlag,0); OrderAuctionBond one1 = orderAuctionBondMapper.selectOne(wrapper1); one1.setBoundStatus(BondStatusEnum.PAID); one1.setPaymentMethod(paymentMethodEnum); orderAuctionBondMapper.updateById(one1); if (one1.getBond()==null||one1.getBond().compareTo(new BigDecimal(0))==0){ one1.setBoundStatus(BondStatusEnum.PAID); Map returnMap = new HashMap<>(); // Type 1是否需要支付 returnMap.put("Type",1); return R.ok(returnMap); } }else{ LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(Order::getOrderNo,orderNO); wrapper1.eq(Order::getDelFlag,0); Order page1 = OrderMapper.selectOne(wrapper1); page1.setOrderStatus(OrderStatusEnum.TO_BE_SHIPPED); page1.setPaymentMethod(paymentMethodEnum); page1.setPayTime(LocalDateTime.now()); OrderMapper.updateById(page1); if (page1.getTotalAmount().compareTo(new BigDecimal(0))==0){ Map returnMap = new HashMap<>(); returnMap.put("Type",1); return R.ok(returnMap); } OrderMapper.updateById(page1); if (page1.getPoints()!=0){ MemberPointsDTO memberPointsDTO=new MemberPointsDTO(); memberPointsDTO.setMemberId(page1.getMemberId()); memberPointsDTO.setPointsType(1); memberPointsDTO.setPointsStatus(PointStatusEnum.INCREASE); memberPointsDTO.setPoints(page1.getPoints()); memberClient.addMemberPoints(memberPointsDTO); } updMembeOneDTO MembeOneDTO=new updMembeOneDTO(); MembeOneDTO.setType(1); MembeOneDTO.setMemberId(page1.getMemberId()); MembeOneDTO.setMoney(page1.getTotalAmount()); MembeOneDTO.setTotalPoints(page1.getPoints()); memberClient.updMembeOne(MembeOneDTO, SecurityConstants.INNER); } if (orderNO.contains("BO")) { LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(OrderAuctionBond::getOrderNo,orderNO); wrapper1.eq(OrderAuctionBond::getDelFlag,0); OrderAuctionBond one = orderAuctionBondMapper.selectOne(wrapper1); price=one.getBond().doubleValue(); body = " 订单支付"; subject = " 订单支付"; if (type == 1) { // 支付宝预下单 return this.alipay(zfbOpenid, orderNO, subject, body, price, request); } if (type == 2){ // 微信预下单 return this.wxpay(2 ,orderNO, body, openId, price, request); } }else{ LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(Order::getOrderNo,orderNO); wrapper1.eq(Order::getDelFlag,0); Order page1 = OrderMapper.selectOne(wrapper1); price=page1.getTotalAmount().doubleValue(); body = " 订单支付"; subject = " 订单支付"; Map map = new HashMap(); if (type == 1) { // 支付宝预下单 return this.alipay(zfbOpenid, orderNO, subject, body, price, request); } if (type == 2) { // 微信预下单 return this.wxpay(2, orderNO, body,openId, price, request); } } } } catch (Exception e) { log.info("获取异常", e); } return R.fail("获取异常"); } /** * 服务器异步通知处理支付宝 * * @param request * @param res */ @Override public void notifyUrl(HttpServletRequest request, HttpServletResponse res) { log.info("=============================支付宝回调============================="); HttpServletResponse response = (HttpServletResponse) res; response.setContentType("text/html;charset=UTF-8"); PrintWriter out; try { out = response.getWriter(); // 获取支付宝POST过来反馈信息 Map params = new HashMap(); Map requestParams = request.getParameterMap(); log.debug("AlipayController.notifyUrl__requestParams:\n" + requestParams); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } Paylog paylog1= getPayLog_alipay(request); // 验证成功 if ("TRADE_FINISHED".equals(paylog1.getTradeStatus())) { System.out.println("AlipayController.notifyUrl__验证成功:success"); // 支付失败 } else if ("TRADE_SUCCESS".equals(paylog1.getTradeStatus())) { // 支付成功 try { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(Paylog::getOutTradeNo,paylog1.getOutTradeNo()); Paylog one = this.getOne(wrapper); if(SinataUtil.isEmpty(one)) { this.save(paylog1); if (paylog1.getOutTradeNo().contains("BO")) { LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(OrderAuctionBond::getOrderNo,paylog1.getOutTradeNo()); wrapper1.eq(OrderAuctionBond::getDelFlag,0); OrderAuctionBond one1 = orderAuctionBondMapper.selectOne(wrapper1); if (one1.getOrderTimeSx().isAfter(LocalDateTime.now())){ boolean bo = refundForAlipay(paylog1.getOutTradeNo(), paylog1.getTradeNo(), paylog1.getPayMoney()); } one1.setBoundStatus(BondStatusEnum.PAID); orderAuctionBondMapper.updateById(one1); }else{ LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(Order::getOrderNo,paylog1.getOutTradeNo()); wrapper1.eq(Order::getDelFlag,0); Order page1 = OrderMapper.selectOne(wrapper1); page1.setOrderStatus(OrderStatusEnum.TO_BE_SHIPPED); page1.setPayTime(LocalDateTime.now()); if(page1.getOrderNo().contains("SP")){ GoodsSku goodsSku =new GoodsSku(); goodsSku.setId(page1.getGoodsSkuId()); goodsSku.setSoldQuantity(page1.getGoodsQuantity()); goodsSkuClient.updGoods(goodsSku, SecurityConstants.INNER); } if(page1.getOrderNo().contains("MS")){ GoodsSku goodsSku =new GoodsSku(); goodsSku.setId(page1.getGoodsSkuId()); goodsSku.setSoldQuantity(page1.getGoodsQuantity()); goodsSkuClient.updGoodsSeckill1(goodsSku, SecurityConstants.INNER); } if(page1.getOrderNo().contains("TG")){ GoodsGroupPurchase goodsSeckiGoodsGroupPurchaseOne = goodsSkuClient.getGoodsSeckiGoodsGroupPurchaseOne(page1.getGoodsSkuId(), SecurityConstants.INNER).getData(); GoodsGroupPurchaseInfo goodsSeckiGoodsGroupPurchaseInfo = goodsSkuClient.getGoodsSeckiGoodsGroupPurchaseInfo(page1.getGoodsSkuId(), SecurityConstants.INNER).getData(); if (goodsSeckiGoodsGroupPurchaseInfo!=null){ page1.setGroupNo(goodsSeckiGoodsGroupPurchaseInfo.getMubre()); OrderMapper.updateById(page1); Integer i= goodsSeckiGoodsGroupPurchaseInfo.getPurchaseNum()+page1.getGoodsQuantity(); goodsSeckiGoodsGroupPurchaseInfo.setPurchaseNum(i); goodsSkuClient.updgoodsGroupPurchaseInfo(goodsSeckiGoodsGroupPurchaseInfo, SecurityConstants.INNER); }else{ UUID uuid = UUID.randomUUID(); page1.setGroupNo(uuid.toString()); OrderMapper.updateById(page1); GoodsGroupPurchaseInfo goodsGroupPurchaseInfo=new GoodsGroupPurchaseInfo(); goodsGroupPurchaseInfo.setGroupSize(goodsSeckiGoodsGroupPurchaseOne.getGroupSize()); goodsGroupPurchaseInfo.setCurrentNumber(1); goodsGroupPurchaseInfo.setPurchaseNum(page1.getGoodsQuantity()); goodsGroupPurchaseInfo.setMubre(uuid.toString()); goodsGroupPurchaseInfo.setGroupPurchaseId(goodsSeckiGoodsGroupPurchaseOne.getId()); goodsGroupPurchaseInfo.setGroupStatus(0); goodsSkuClient.updgoodsGroupPurchaseInfo(goodsGroupPurchaseInfo, SecurityConstants.INNER); } } } } // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— log.debug("AlipayController.notifyUrl__回调处理:success"); out.println("success"); // 请不要修改或删除 // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— log.debug("AlipayController.notifyUrl__回调处理:success"); out.println("success"); // 请不要修改或删除 } catch (Exception e) { log.debug("AlipayController.notifyUrl__回调逻辑代码处理异常!fail"); // 返回失败 out.println("fail"); log.error("AlipayController.notifyUrl__回调逻辑代码处理异常!fail", e); } // //////////////////////////////////////////////////////////////////////////////////////// } else {// 验证失败 log.debug("AlipayController.notifyUrl__回调处理失败!fail"); out.println("fail"); } } catch ( IOException e) { log.debug("AlipayController.notifyUrl__支付宝服务器异步通知数据处理失败!"); log.error("AlipayController.notifyUrl__支付宝服务器异步通知数据处理失败!", e); } } /////////////////////////////////////////////////////////////////////////////////////////////////// /** * 微信支付回调(参考财付通回调接口) * * @param request * @param response */ @Override public void wxnotify(HttpServletRequest request, HttpServletResponse response) { try { System.out.println("微信支付回调!!!!!!!!!!!!!!!!!!!!!!!!!"); // 异步通知返回报文 StringBuffer notityXml = new StringBuffer(); String inputLine; while ((inputLine = request.getReader().readLine()) != null) { notityXml.append(inputLine); } request.getReader().close(); // log.debug("WxpayController.notify__notityXml:\n" + notityXml); System.out.println("WxpayController.notify__notityXml:\n" + notityXml); // 验证签名 Map map = XMLParser.getMapFromXML(notityXml.toString()); // log.debug("WxpayController.notify__map:\n" + map); // 接口返回状态 String result_code = (String) map.get("result_code"); if ("SUCCESS".equals(result_code)) { // // 商户订单号 String out_trade_no = (String) map.get("out_trade_no"); // // 微信支付交易号 String trade_no = (String) map.get("transaction_id"); // // 金额,以分为单位 String total_fee = (String) map.get("total_fee"); // // 优惠金额 // String discount = (String) map.get("discount"); // // 支付完成时间 String time_end = (String) map.get("time_end"); // // 支付者唯一Id(对应买家账号的一个加密串 ) String buyer_id = (String) map.get("buyer_id"); ///////////////////////////// 这里程序处理支付回调逻辑 ///////////////////////////// //////////////////// LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(Paylog::getOutTradeNo,out_trade_no); Paylog one = this.getOne(wrapper); if(SinataUtil.isEmpty(one)) { Paylog paylog = new Paylog(); paylog.setOutTradeNo(out_trade_no); paylog.setPayType(2); paylog.setBuyerId(buyer_id); paylog.setTradeNo(trade_no); paylog.setPayMoney(Double.parseDouble(total_fee) / 100); paylog.setState(1); System.out.println("支付完成时间" + time_end); paylog.setAddTime(LocalDateTime.now()); this.save(paylog); if (paylog.getOutTradeNo().contains("BO")) { LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(OrderAuctionBond::getOrderNo,paylog.getOutTradeNo()); wrapper1.eq(OrderAuctionBond::getDelFlag,0); OrderAuctionBond one1 = orderAuctionBondMapper.selectOne(wrapper1); if (one1.getOrderTimeSx().isAfter(LocalDateTime.now())){ String refundMoney = SinataUtil.doubleRetainTwo(paylog.getPayMoney() * 100d); Integer refundFee = Integer.parseInt(refundMoney.substring(0, refundMoney.length() - 3)); String money = SinataUtil.doubleRetainTwo(paylog.getPayMoney() * 100d); Integer totalFee = Integer.parseInt(money.substring(0, money.length() - 3)); refundFee = Integer.parseInt(money.substring(0, money.length() - 3)); String regEx = "[^0-9]"; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(paylog.getOutTradeNo()); String ma = m.replaceAll("").trim(); refundForWxpay(4, paylog.getTradeNo(), paylog.getOutTradeNo(), "R" + ma, totalFee, refundFee, "2"); } one1.setBoundStatus(BondStatusEnum.PAID); one1.setPaymentMethod(PaymentMethodEnum.WECHAT); orderAuctionBondMapper.updateById(one1); }else{ LambdaQueryWrapper wrapper1= Wrappers.lambdaQuery(); wrapper1.eq(Order::getOrderNo,paylog.getOutTradeNo()); wrapper1.eq(Order::getDelFlag,0); Order page1 = OrderMapper.selectOne(wrapper1); page1.setOrderStatus(OrderStatusEnum.TO_BE_SHIPPED); page1.setPaymentMethod(PaymentMethodEnum.WECHAT); page1.setPayTime(LocalDateTime.now()); if(page1.getOrderNo().contains("SP")){ GoodsSku goodsSku =new GoodsSku(); goodsSku.setId(page1.getGoodsSkuId()); goodsSku.setSoldQuantity(page1.getGoodsQuantity()); goodsSkuClient.updGoods(goodsSku, SecurityConstants.INNER); } if(page1.getOrderNo().contains("MS")){ GoodsSku goodsSku =new GoodsSku(); goodsSku.setId(page1.getGoodsSkuId()); goodsSku.setSoldQuantity(page1.getGoodsQuantity()); goodsSkuClient.updGoodsSeckill1(goodsSku, SecurityConstants.INNER); } if(page1.getOrderNo().contains("TG")){ GoodsGroupPurchase goodsSeckiGoodsGroupPurchaseOne = goodsSkuClient.getGoodsSeckiGoodsGroupPurchaseOne(page1.getGoodsSkuId(), SecurityConstants.INNER).getData(); GoodsGroupPurchaseInfo goodsSeckiGoodsGroupPurchaseInfo = goodsSkuClient.getGoodsSeckiGoodsGroupPurchaseInfo(page1.getGoodsSkuId(), SecurityConstants.INNER).getData(); if (goodsSeckiGoodsGroupPurchaseInfo!=null){ page1.setGroupNo(goodsSeckiGoodsGroupPurchaseInfo.getMubre()); OrderMapper.updateById(page1); Integer i= goodsSeckiGoodsGroupPurchaseInfo.getPurchaseNum()+page1.getGoodsQuantity(); goodsSeckiGoodsGroupPurchaseInfo.setPurchaseNum(i); goodsSkuClient.updgoodsGroupPurchaseInfo(goodsSeckiGoodsGroupPurchaseInfo, SecurityConstants.INNER); }else{ UUID uuid = UUID.randomUUID(); page1.setGroupNo(uuid.toString()); OrderMapper.updateById(page1); GoodsGroupPurchaseInfo goodsGroupPurchaseInfo=new GoodsGroupPurchaseInfo(); goodsGroupPurchaseInfo.setGroupSize(goodsSeckiGoodsGroupPurchaseOne.getGroupSize()); goodsGroupPurchaseInfo.setCurrentNumber(1); goodsGroupPurchaseInfo.setPurchaseNum(page1.getGoodsQuantity()); goodsGroupPurchaseInfo.setMubre(uuid.toString()); goodsGroupPurchaseInfo.setGroupPurchaseId(goodsSeckiGoodsGroupPurchaseOne.getId()); goodsGroupPurchaseInfo.setGroupStatus(0); goodsSkuClient.updgoodsGroupPurchaseInfo(goodsGroupPurchaseInfo, SecurityConstants.INNER); } } } log.debug("WxpayController.notify__回调处理成功:SUCCESS"); response.getOutputStream().print("success"); } log.debug("WxpayController.notify__回调处理成功:SUCCESS"); response.getOutputStream().print("success"); } else { log.debug("WxpayController.notify__回调处理:验证状态错误!" + result_code); System.out.println("验证状态错误!" + result_code); } } catch (Exception e) { e.printStackTrace(); } } /** * 支付宝订单退款 * * @author tzj * @param out_trade_no * 商品订单号 * @param trade_no * 支付宝交易号 * @param refund_amount * 退款金额 * @return */ public boolean refundForAlipay(String out_trade_no, String trade_no, Double refund_amount) { try { // 实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.ali_public_key,"RSA2"); // 实例化具体API对应的request类,类名称和接口名称对应 AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); // SDK已经封装掉了公共参数,这里只需要传入业务参数 // 此次只是参数展示,未进行字符串转义,实际情况下请转义 request.setBizContent("{" + "\"out_trade_no\":\"" + out_trade_no + "\", " + "\"trade_no\":\"" + trade_no + "\", " + "\"refund_amount\":" + refund_amount + ", " + "\"refund_reason\":\"正常退款\"," + "\"out_request_no\":\"HZ01RF001\"" + "}"); AlipayTradeRefundResponse response = alipayClient.execute(request); log.info("支付宝退款response:" + response.getBody()); // 调用成功,则处理业务逻辑 if (response.isSuccess()) { return true; } } catch (Exception e) { e.printStackTrace(); return false; } return false; } /** * 获取支付信息支付(签约app支付2.0) * * @param subject * @param body * @param price * @param request * @return */ public R> alipay(String zfbOpenid, String orderNo, String subject, String body, Double price, HttpServletRequest request) { try { // 接口封装支付宝请求参数 // Map mData = new HashMap(); // 构建请求支付签名参数 // Map pay = PayDemoActivity.appPay(subject, body, price, orderNo); Map pay = PayDemoActivity.jsApiPay(subject, body, price, orderNo, zfbOpenid); /* * Set> entrySet = pay.entrySet(); * Iterator> iterator = entrySet.iterator(); * while (iterator.hasNext()) { Entry next = * iterator.next(); mData.put(next.getKey(), next.getValue()); } */ log.info("支付宝预支付信息:{}", JSON.toJSONString(pay)); return R.ok(pay); } catch (Exception e) { e.printStackTrace(); return R.fail("支付异常!"); } } /** * 统一下单 * * @param apptype * @param outTradeNo * @param body * @param price * @param request * @return */ public static R> wxpay(Integer apptype,String outTradeNo, String body,String openId, Double price, HttpServletRequest request) { // 获取预支付接口返回参数 Map map1 = new HashMap(); Map appPayMap = new HashMap(); try { /* // 构建接口请求参数 UnifiedorderReqData unifiedorderReqData = new UnifiedorderReqData(outTradeNo, body, price, Configure.wx_notify_url, "JSAPI", openId); // 请求接口获取返回接口 String result = requestUnifiedorderService(2, unifiedorderReqData); System.out.println(result); System.out.println("WxpayController.createOrder__result:\n" + result); // 获取预支付接口返回参数 map1 = XMLParser.getMapFromXML(result); System.out.println("WxpayController.createOrder__result:\n" + result); // 捕获预支付接口错误提示 if ("FAIL".equals(map1.get("result_code")) || "FAIL".equals(map1.get("return_code"))) { return R.fail(String.valueOf(map1.get("return_msg"))); }*/ /* // 对获取预支付返回接口参数进行封装(生成支付订单接口数据) AppPayReqData appPay = new AppPayReqData(apptype, (String) map.get("appid"), (String) map.get("mch_id"), (String) map.get("prepay_id"), unifiedorderReqData.getNonce_str());*/ UUID uuid = UUID.randomUUID(); String nonceStr = uuid.toString().replaceAll("-", ""); //商品描述 String body = "XX商城-支付订单"; // 创建hashmap(用户获得签名) SortedMap paraMap = new TreeMap<>(); //设置请求参数(小程序ID) paraMap.put("appid", Configure.getAppid()); //设置请求参数(商户号) paraMap.put("mch_id", Configure.getMchid()); //设置请求参数(随机字符串) paraMap.put("nonce_str", nonceStr); //设置请求参数(商品描述) paraMap.put("body", body); //设置请求参数(商户订单号) paraMap.put("out_trade_no", outTradeNo); //设置请求参数(总金额) String money=SinataUtil.doubleRetainTwo(price*100d); Integer price1 = Integer.parseInt(money.substring(0,money.length()-3)); paraMap.put("total_fee", price1.toString()); //设置请求参数(通知地址) paraMap.put("notify_url", Configure.wx_notify_url); //设置请求参数(交易类型) paraMap.put("trade_type", String.valueOf(WxPayApi.TradeType.JSAPI)); paraMap.put("openid",openId); //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid) //MD5运算生成签名,这里是第一次签名,用于调用统一下单接口 String sign = PaymentKit.createSign(paraMap, "HSCEWrfSYiwxR6sesZ6De91Xh3m447sh"); paraMap.put("sign", sign); //统一下单,向微信api发送数据 //转成xml String xmlResult = WxPayApi.pushOrder(false, paraMap); Map map = PaymentKit.xmlToMap(xmlResult); //返回状态码 String returnCode = map.get("return_code"); /* Assert.isTrue("SUCCESS".equals(returnCode), getMsgByCode(returnCode));*/ //返回给小程序端需要的参数 Map returnMap = new HashMap<>(20); String prepay_id = map.get("prepay_id"); //重新进行签名后返回给前端 returnMap.put("appId", map.get("appid")); returnMap.put("nonceStr", map.get("nonce_str")); returnMap.put("package", "prepay_id=" + prepay_id); returnMap.put("timeStamp", new Date().getTime() + ""); returnMap.put("signType", "MD5"); String signature = weixinSignature(returnMap, "HSCEWrfSYiwxR6sesZ6De91Xh3m447sh"); returnMap.put("prepay_id", prepay_id); returnMap.put("mch_id", map.get("mch_id")); returnMap.put("trade_type", map.get("trade_type")); returnMap.put("sign", signature); returnMap.put("Type",2); returnMap.put("err_code_des", map.get("err_code_des")); // 对获取预支付返回接口参数进行封装(生成支付订单接口数据) return R.ok(returnMap); } catch (Exception e) { System.out.println("统一下单_API_处理异常!"); e.printStackTrace(); } return R.fail("统一下单失败"); } private static String weixinSignature(Map map, String privateKey) { try { Set> entries = map.entrySet(); List> infoIds = new ArrayList>(entries); // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) Collections.sort(infoIds, new Comparator>() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return (o1.getKey()).toString().compareTo(o2.getKey()); } }); // 构造签名键值对的格式 StringBuilder sb = new StringBuilder(); for (Map.Entry item : infoIds) { if (item.getKey() != null || item.getKey() != "") { String key = item.getKey(); Object val = item.getValue(); if (!(val == "" || val == null)) { sb.append(key + "=" + val + "&"); } } } sb.append("key=" + privateKey); String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 return sign; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 微信退款 * * @param transactionID * 【支付交易号】是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易, * 它由支付订单API支付成功时返回的数据里面获取到。建议优先使用 * @param outTradeNo * 【商品订单编号】商户系统内部的订单号,transaction_id * 、out_trade_no二选一,如果同时存在优先级:transaction_id>out_trade_no * @param outRefundNo * 【退款编号】商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 * 订单总金额,单位为分 * @param refundFee * 退款总金额,单位为分,可以做部分退款 * @return */ public static boolean refundForWxpay(Integer apptype, String transactionID, String outTradeNo, String outRefundNo, Integer totalFee, Integer refundFee, String pay_type) { //生成32位随机数 UUID uuid = UUID.randomUUID(); String nonceStr = uuid.toString().replaceAll("-", ""); //商品描述 String body = "XX商城-支付订单"; // 创建hashmap(用户获得签名) SortedMap paraMap = new TreeMap<>(); //设置请求参数(小程序ID) paraMap.put("appid", Configure.getAppid()); //设置请求参数(商户号) paraMap.put("mch_id", Configure.getMchid()); //设置请求参数(随机字符串) paraMap.put("nonce_str", nonceStr); paraMap.put("transaction_id",transactionID); paraMap.put("out_trade_no", outTradeNo); paraMap.put("out_refund_no", outRefundNo); //设置请求参数(支付的总金额) paraMap.put("total_fee", totalFee.toString()); //设置请求参数(退款的金额) paraMap.put("refund_fee", refundFee.toString()); //MD5运算生成签名 paraMap.put("sign", PaymentKit.createSign(paraMap, "HSCEWrfSYiwxR6sesZ6De91Xh3m447sh")); System.out.println("证书: " + Configure.getCertLocalPath_2()); String xmlResult = WxPayApi.orderRefund(false, paraMap,Configure.getCertLocalPath_2(), Configure.getMchid()); System.out.println("微信退款结果: " + xmlResult); return true; } /** * 获取支付宝 * * @param request * @return * @throws Exception */ private Paylog getPayLog_alipay(HttpServletRequest request) throws IOException { //////// 获取支付宝的通知返回参数,可参考技术文档中页面跳转步通知同参数列表(以下仅供参考)//////// // 商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 交易状态 String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8"); // 支付者唯一Id // String buyer_id = new String(request.getParameter("buyer_id").getBytes("ISO-8859-1"), "UTF-8"); // 支付帐号 // String buyer_email = ""; // if (SinataUtil.isNotEmpty(request.getParameter("buyer_logon_id"))) { // buyer_email = new String(request.getParameter("buyer_logon_id").getBytes("ISO-8859-1"), "UTF-8"); // } // 支付金额 String total_fee = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8"); // 支付时间 String notify_time = new String(request.getParameter("notify_time").getBytes("ISO-8859-1"), "UTF-8"); //////// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//////// Paylog paylog = new Paylog(); paylog.setOutTradeNo(out_trade_no); paylog.setPayType(1); // paylog.setBuyerId(buyer_id); paylog.setTradeNo(trade_no); paylog.setPayMoney(Double.parseDouble(total_fee)); paylog.setState(1); paylog.setAddTime(LocalDateTime.now()); paylog.setTradeStatus(trade_status.toString()); return paylog; } public boolean judgeContainsStr(String cardNum) { String regex=".*[a-zA-Z]+.*"; Matcher m= Pattern.compile(regex).matcher(cardNum); return m.matches(); } /** * @param refundDTOS 退款数据传输对象 * @return Map key :orderNo value 退款结果 */ @Override public Map refund(List refundDTOS) { Map map = new HashMap<>(); Set orderNoList = refundDTOS.stream().map(RefundDTO::getOrderNo) .collect(Collectors.toSet()); if (StringUtils.isNotEmpty(orderNoList)) { Map paylogMap = this.lambdaQuery() .in(Paylog::getOutTradeNo, orderNoList).eq(Paylog::getState, 1).list().stream() .collect(Collectors.toMap(Paylog::getOutTradeNo, Function.identity())); List updList = new ArrayList<>(); for (RefundDTO refundDTO : refundDTOS) { String orderNo = refundDTO.getOrderNo(); BigDecimal amount = refundDTO.getAmount(); Paylog paylog = paylogMap.get(orderNo); Optional.of(paylog).ifPresent(pay -> { Boolean res = handleRefund(pay, amount, orderNo); map.put(orderNo, res); if (res) { pay.setState(3); updList.add(pay); } }); } this.updateBatchById(updList); } return map; } @Override public void refund1(RefundDTO refundDTOS) { LambdaQueryWrapper paylogEntityWrapper = Wrappers.lambdaQuery(); paylogEntityWrapper.eq(Paylog::getOutTradeNo, refundDTOS.getOrderNo()); Paylog paylog = paylogMapper.selectOne(paylogEntityWrapper); if (paylog.getPayType() ==1) {//支付宝 //获取支付信息 if (paylog != null) { boolean bo = this.refundForAlipay(paylog.getOutTradeNo(), paylog.getTradeNo(), paylog.getPayMoney()); if (!bo) { System.out.println("支付宝退款失败"); } } } else if (paylog.getPayType() ==2) {//微信 //获取支付信息 if (paylog != null) { String refundMoney = SinataUtil.doubleRetainTwo(paylog.getPayMoney() * 100d); Integer refundFee = Integer.parseInt(refundMoney.substring(0, refundMoney.length() - 3)); String money = SinataUtil.doubleRetainTwo(paylog.getPayMoney() * 100d); Integer totalFee = Integer.parseInt(money.substring(0, money.length() - 3)); refundFee = Integer.parseInt(money.substring(0, money.length() - 3)); String regEx = "[^0-9]"; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(refundDTOS.getOrderNo()); String ma = m.replaceAll("").trim(); boolean bo = this.refundForWxpay(4, paylog.getTradeNo(), paylog.getOutTradeNo(), "R" + ma, totalFee, refundFee, "2"); if (!bo) { System.out.println("微信退款失败"); } } } } private Boolean handleRefund(Paylog paylog, BigDecimal amount, String orderNo) { boolean res = false; if (StringUtils.isNotNull(paylog)) { if (paylog.getPayType() == 1) { res = refundForAlipay(paylog.getOutTradeNo(), paylog.getTradeNo(), amount.doubleValue()); } if (paylog.getPayType() == 2) { String refundMoney = SinataUtil.doubleRetainTwo( amount.doubleValue() * 100d); Integer refundFee = Integer.parseInt( refundMoney.substring(0, refundMoney.length() - 3)); String money = SinataUtil.doubleRetainTwo(paylog.getPayMoney() * 100d); Integer totalFee = Integer.parseInt( money.substring(0, money.length() - 3)); res = refundForWxpay(1, paylog.getTradeNo(), paylog.getOutTradeNo(), orderNo, totalFee, refundFee, "2"); } } return res; } }