| | |
| | | package com.ruoyi.order.service.impl; |
| | | |
| | | import com.ruoyi.order.domain.pojo.Paylog; |
| | | import com.ruoyi.order.mapper.PaylogMapper; |
| | | import com.ruoyi.order.service.IPaylogService; |
| | | import static com.ruoyi.order.util.tencent.WXPay.requestRefundService; |
| | | import static com.ruoyi.order.util.tencent.WXPay.requestUnifiedorderService; |
| | | |
| | | 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.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.IOrderAuctionBondService; |
| | | 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.Signature; |
| | | import com.ruoyi.order.util.tencent.common.XMLParser; |
| | | import com.ruoyi.order.util.tencent.protocol.AppPayReqData; |
| | | import com.ruoyi.order.util.tencent.protocol.UnifiedorderReqData; |
| | | import com.ruoyi.system.api.domain.Order; |
| | | import com.ruoyi.system.api.domain.OrderAuctionBond; |
| | | import com.ruoyi.system.api.domain.dto.BondDTO; |
| | | 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.MemberClient; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.PrintWriter; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | 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 com.ruoyi.system.api.feignClient.OrderClient; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.Assert; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Service |
| | | public class PaylogServiceImpl extends ServiceImpl<PaylogMapper, Paylog> implements IPaylogService { |
| | | |
| | | |
| | | |
| | | @Resource |
| | | private OrderMapper OrderMapper; |
| | | @Resource |
| | | private AuctionClient auctionClient; |
| | | |
| | | |
| | | @Resource |
| | | private MemberClient memberClient; |
| | | |
| | | @Resource |
| | | private OrderAuctionBondMapper orderAuctionBondMapper; |
| | | |
| | | @Override |
| | | public R<Map<String, Object>> getPayInfo(Integer uid, Integer type, String orderNO,String openId, HttpServletRequest request) { |
| | | Double price = 0.0; |
| | | String subject; |
| | | String body; |
| | | try { |
| | | if(judgeContainsStr(orderNO)){ |
| | | if (orderNO.contains("BO")) { |
| | | LambdaQueryWrapper<OrderAuctionBond> 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(orderNO, subject, body, price, request); |
| | | } else { |
| | | // 微信预下单 |
| | | return this.wxpay(2, orderNO, body,openId, price, request); |
| | | } |
| | | }else{ |
| | | LambdaQueryWrapper<Order> 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<String, Object> map = new HashMap<String, Object>(); |
| | | if (type == 1) { |
| | | // 支付宝预下单 |
| | | return this.alipay(orderNO, subject, body, price, request); |
| | | } else { |
| | | // 微信预下单 |
| | | return this.wxpay(2, orderNO, body,openId, price, request); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return R.fail("获取异常"); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 服务器异步通知处理支付宝 |
| | | * |
| | | * @param request |
| | | * @param res |
| | | */ |
| | | @Override |
| | | public void notifyUrl(HttpServletRequest request, HttpServletResponse res) { |
| | | HttpServletResponse response = (HttpServletResponse) res; |
| | | response.setContentType("text/html;charset=UTF-8"); |
| | | PrintWriter out; |
| | | try { |
| | | out = response.getWriter(); |
| | | // 获取支付宝POST过来反馈信息 |
| | | Map<String, String> params = new HashMap<String, String>(); |
| | | 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<Paylog> 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<OrderAuctionBond> wrapper1= Wrappers.lambdaQuery(); |
| | | wrapper1.eq(OrderAuctionBond::getOrderNo,paylog1.getOutTradeNo()); |
| | | wrapper1.eq(OrderAuctionBond::getDelFlag,0); |
| | | OrderAuctionBond one1 = orderAuctionBondMapper.selectOne(wrapper1); |
| | | one1.setBoundStatus(BondStatusEnum.PAID); |
| | | |
| | | }else{ |
| | | LambdaQueryWrapper<Order> wrapper1= Wrappers.lambdaQuery(); |
| | | wrapper1.eq(Order::getOrderNo,paylog1.getOutTradeNo()); |
| | | wrapper1.eq(Order::getDelFlag,0); |
| | | Order page1 = OrderMapper.selectOne(wrapper1); |
| | | page1.setOrderStatus(OrderStatusEnum.GOODS_TO_BE_RECEIVED); |
| | | page1.setPayTime(LocalDateTime.now()); |
| | | OrderMapper.updateById(page1); |
| | | |
| | | 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); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— |
| | | 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"); |
| | | e.printStackTrace(); |
| | | } |
| | | // //////////////////////////////////////////////////////////////////////////////////////// |
| | | } else {// 验证失败 |
| | | log.debug("AlipayController.notifyUrl__回调处理失败!fail"); |
| | | out.println("fail"); |
| | | } |
| | | } catch ( |
| | | IOException e) { |
| | | log.debug("AlipayController.notifyUrl__支付宝服务器异步通知数据处理失败!"); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| | | |
| | | /** |
| | | * 微信支付回调(参考财付通回调接口) |
| | | * |
| | | * @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); |
| | | |
| | | // 验证签名 |
| | | if (Signature.checkIsSignValidFromResponseString(1, notityXml.toString()) |
| | | || Signature.checkIsSignValidFromResponseString(2, notityXml.toString())) { |
| | | Map<String, Object> 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<Paylog> 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<OrderAuctionBond> wrapper1= Wrappers.lambdaQuery(); |
| | | wrapper1.eq(OrderAuctionBond::getOrderNo,paylog.getOutTradeNo()); |
| | | wrapper1.eq(OrderAuctionBond::getDelFlag,0); |
| | | OrderAuctionBond one1 = orderAuctionBondMapper.selectOne(wrapper1); |
| | | one1.setBoundStatus(BondStatusEnum.PAID); |
| | | |
| | | }else{ |
| | | LambdaQueryWrapper<Order> wrapper1= Wrappers.lambdaQuery(); |
| | | wrapper1.eq(Order::getOrderNo,paylog.getOutTradeNo()); |
| | | wrapper1.eq(Order::getDelFlag,0); |
| | | Order page1 = OrderMapper.selectOne(wrapper1); |
| | | page1.setOrderStatus(OrderStatusEnum.GOODS_TO_BE_RECEIVED); |
| | | page1.setPayTime(LocalDateTime.now()); |
| | | OrderMapper.updateById(page1); |
| | | |
| | | 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); |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | } else { |
| | | log.debug("WxpayController.notify__回调处理:通知签名验证失败!"); |
| | | System.out.println("通知签名验证失败!"); |
| | | } |
| | | } 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); |
| | | // 调用成功,则处理业务逻辑 |
| | | 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<Map<String, Object>> alipay(String orderNo, String subject, String body, Double price, |
| | | HttpServletRequest request) { |
| | | try { |
| | | // 接口封装支付宝请求参数 |
| | | // Map<String, Object> mData = new HashMap<String, Object>(); |
| | | |
| | | // 构建请求支付签名参数 |
| | | Map<String, Object> pay = PayDemoActivity.appPay(subject, body, price, orderNo); |
| | | /* |
| | | * Set<Entry<String, String>> entrySet = pay.entrySet(); |
| | | * Iterator<Entry<String, String>> iterator = entrySet.iterator(); |
| | | * while (iterator.hasNext()) { Entry<String, String> next = |
| | | * iterator.next(); mData.put(next.getKey(), next.getValue()); } |
| | | */ |
| | | 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<Map<String, Object>> wxpay(Integer apptype, String outTradeNo, String body,String openId, Double price, |
| | | HttpServletRequest request) { |
| | | // 获取预支付接口返回参数 |
| | | Map<String, Object> map1 = new HashMap<String, Object>(); |
| | | Map<String, Object> appPayMap = new HashMap<String, Object>(); |
| | | 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<String, String> 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<String, String> map = PaymentKit.xmlToMap(xmlResult); |
| | | //返回状态码 |
| | | String returnCode = map.get("return_code"); |
| | | /* Assert.isTrue("SUCCESS".equals(returnCode), getMsgByCode(returnCode));*/ |
| | | |
| | | //返回给小程序端需要的参数 |
| | | Map<String, Object> 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("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<String, Object> map, String privateKey) { |
| | | try { |
| | | Set<Map.Entry<String, Object>> entries = map.entrySet(); |
| | | List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries); |
| | | // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) |
| | | Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() { |
| | | public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) { |
| | | return (o1.getKey()).toString().compareTo(o2.getKey()); |
| | | } |
| | | }); |
| | | // 构造签名键值对的格式 |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (Map.Entry<String, Object> 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) { |
| | | Map<String, Object> map = new HashMap<String, Object>(); |
| | | try { |
| | | // 构建接口请求参数 |
| | | com.tencent.protocol.RefundReqData refundReqData = new com.tencent.protocol.RefundReqData(transactionID, outTradeNo, outRefundNo, totalFee, refundFee, |
| | | pay_type); |
| | | |
| | | // 请求接口返回结果 |
| | | String result = requestRefundService(apptype, refundReqData); |
| | | System.out.println("微信退款返回内容:" + result); |
| | | // 获取预支付接口返回参数 |
| | | map = XMLParser.getMapFromXML(result); |
| | | System.out.println("微信退款返回参数:" + map); |
| | | // 退款成功处理 |
| | | if ("SUCCESS".equals(map.get("result_code"))) { |
| | | return true; |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 获取支付宝 |
| | | * |
| | | * @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(); |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> refund(List<RefundDTO> refundDTOS) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | Set<String> orderNoList = refundDTOS.stream().map(RefundDTO::getOrderNo) |
| | | .collect(Collectors.toSet()); |
| | | if (StringUtils.isNotEmpty(orderNoList)) { |
| | | Map<String, Paylog> paylogMap = this.lambdaQuery() |
| | | .in(Paylog::getOutTradeNo, orderNoList).eq(Paylog::getState, 1).list().stream() |
| | | .collect(Collectors.toMap(Paylog::getOutTradeNo, Function.identity())); |
| | | List<Paylog> 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; |
| | | } |
| | | |
| | | private Boolean handleRefund(Paylog paylog, BigDecimal amount, |
| | | String orderNo) { |
| | | boolean res = false; |
| | | if (StringUtils.isNotNull(paylog)) { |
| | | if (paylog.getPayType() == 1) { |
| | | res = this.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 = this.refundForWxpay(2, paylog.getTradeNo(), |
| | | paylog.getOutTradeNo(), orderNo, totalFee, |
| | | refundFee, "4"); |
| | | } |
| | | } |
| | | return res; |
| | | } |
| | | } |