cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminCallBack.java
@@ -80,7 +80,7 @@ @PostMapping("/aliPayHuiminCallback") public void aliPayHuiminCallback(HttpServletRequest request, HttpServletResponse response) { try { System.err.println("==========回调"); System.err.println("支付宝回调"); Map<String, String> map = payMoneyUtil.alipayCallback(request); if (null != map) { String out_trade_no = map.get("out_trade_no"); @@ -92,11 +92,20 @@ out.write("success"); out.flush(); out.close(); }else{ }else if (one.getStatus()==1){ one.setOrderNumber(transaction_id); one.setStatus(2); one.setPaymentTime(new Date()); payHuiminService.updateById(one); PrintWriter out = response.getWriter(); out.write("success"); out.flush(); out.close(); }else{ PrintWriter out = response.getWriter(); out.write("success"); out.flush(); out.close(); } } } @@ -110,6 +119,7 @@ @PostMapping("/weixinPayHuiminCallback") public void weixinPayHuiminCallback(HttpServletRequest request, HttpServletResponse response) { try { System.err.println("微信回调"); Map<String, String> map = payMoneyUtil.weixinpayCallback(request); if (null != map) { String out_trade_no = map.get("out_trade_no"); @@ -122,11 +132,20 @@ out.write(result); out.flush(); out.close(); }else{ }else if (one.getStatus()==1){ one.setOrderNumber(transaction_id); one.setStatus(2); one.setPaymentTime(new Date()); payHuiminService.updateById(one); PrintWriter out = response.getWriter(); out.write(result); out.flush(); out.close(); }else{ PrintWriter out = response.getWriter(); out.write(result); out.flush(); out.close(); } } } cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminController.java
@@ -326,6 +326,13 @@ huiminCardVO1.setHuiminName(huiminCard.getHuiMinName()); huiminCardVO1.setCover(huiminCard.getBuyCover()); huiminCardVO1.setIsBuy(1); int count = huiminRecordService.list(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getPayId, payHuimin.getId())).size(); if (count>0){ huiminCardVOS.add(huiminCardVO1); integers.add(payHuimin.getCardId()); continue; } String siteIds = ""; if (huiminCard.getUseScope() == 2) { siteIds = huiminCard.getUseIds(); @@ -388,7 +395,7 @@ if (tStudent!=null){ huiminCardVO1.setStudentName(tStudent.getName()); } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + payHuimin.getStudentId().split(",")[0] + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; String temp = "{\"id\":"+payHuimin.getId() + ","+"\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + payHuimin.getStudentId() + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; huiminCardVO1.setQrCode(temp); huiminCardVOS.add(huiminCardVO1); integers.add(payHuimin.getCardId()); @@ -425,14 +432,14 @@ int startIndex = (pageNo - 1) * pageSize; int endIndex = Math.min(startIndex + pageSize, huiminCardVOS.size()); // 防止 startIndex 超过 huiminCardVOS.size() // 防止 startIndex 超过 huiminCardVOS.size() if (startIndex > huiminCardVOS.size()) { startIndex = huiminCardVOS.size(); } List<HuiminCardVO> paginatedHuiminCardVOS = huiminCardVOS.subList(startIndex, endIndex); // 将分页后的数据设置到 huiminAgreementVO 中 // 将分页后的数据设置到 huiminAgreementVO 中 huiminAgreementVO.setCardList(paginatedHuiminCardVOS); // 将分页后的数据设置到 huiminAgreementVO 中 // 将分页后的数据设置到 huiminAgreementVO 中 huiminAgreementVO.setCardList(paginatedHuiminCardVOS); // huiminAgreementVO.setCardList(huiminCardVOS); return ResultUtil.success(huiminAgreementVO); @@ -638,7 +645,7 @@ } } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + studentId + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; String temp = "{\"id\":"+tPayHuimin.getId() + ","+"\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + tPayHuimin.getStudentId() + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; huiminCardStudentVO.setQrCode(temp); TStudent tStudent = tStudents.stream().filter(e -> e.getId().equals(studentId)).findFirst().orElse(null); if (tStudent!=null){ @@ -678,15 +685,20 @@ myHuiminCardVO.setEndTime(byId.getEndTime()); myHuiminCardVO.setSalesMoney(byId.getSalesMoney()); int count = huiminRecordService.count(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getHuiminCardId, myHuiminCardVO.getCardId())); .eq(THuiminRecord::getPayId, byId.getId())); // 购卡7日内没有使用记录可退款。超过7日不管有没有使用记录都不能退款 if (new Date().after(DateUtil.addDay(myHuiminCardVO.getPaymentTime(), 7))) { // 超过七天不可退款 myHuiminCardVO.setIsRefund(0); } else if (count >= 7) { } else if (count > 0) { myHuiminCardVO.setIsRefund(0); } else { myHuiminCardVO.setIsRefund(1); } if (byId.getStatus()==4){ // 退款中 myHuiminCardVO.setIsRefund(2); } THuiminCard huiminCard = list.stream().filter(e -> e.getId().equals(myHuiminCardVO.getCardId())).findFirst().orElse(null); if (null != huiminCard) { @@ -735,19 +747,22 @@ if (tPayHuimin.getStatus() == 3 && tPayHuimin.getRefundStatus() != 1) { return ResultUtil.error("不可重复退款"); } if (tPayHuimin.getEndTime().before(new Date())) { // 已过期 return ResultUtil.error("惠民卡已过期,不可退款"); } int count = huiminRecordService.count(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getHuiminCardId, tPayHuimin.getCardId())); tPayHuimin.setStatus(4); payHuiminService.updateById(tPayHuimin); int count = huiminRecordService.list(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getPayId, tPayHuimin.getId())).size(); // 购卡7日内没有使用记录可退款。超过7日不管有没有使用记录都不能退款 if (new Date().after(DateUtil.addDay(tPayHuimin.getPaymentTime(), 7))) { // 超过七天不可退款 return ResultUtil.error("惠民卡购买超过七天,不可退款"); } else if (count >= 7) { // 使用记录大于等于7次不可退款 return ResultUtil.error("惠民卡使用记录大于等于7次,不可退款"); } else if (count > 0) { return ResultUtil.error("惠民卡已使用,不可退款"); } if (tPayHuimin.getPaymentType() == 1) { Map<String, String> map = payMoneyUtil.wxRefund(tPayHuimin.getOrderNumber(), tPayHuimin.getCode(), @@ -778,68 +793,7 @@ } } public static void main(String[] args) { // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // LocalDateTime localDateTime = LocalDateTime.now().plusDays(365); // // 将LocalDateTime转换为Date类型 // Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); // String format = simpleDateFormat.format(date); // System.err.println(format); // String storeIds = "1001,1002"; // JSONArray jsonArray = JSONArray.parseArray(Arrays.toString(storeIds.split(","))); // System.err.println(jsonArray); // // // 获取当前日期 // LocalDate today = LocalDate.now(); // // // 获取当前日期是周几 // DayOfWeek dayOfWeek = today.getDayOfWeek(); // // // 输出当前是周几,使用中文显示 // System.out.println("今天是: " + dayOfWeek.getValue()); Date start = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.err.println(simpleDateFormat.format(start)); start.setTime(start.getTime() + 30 * 1000); System.err.println(simpleDateFormat.format(start)); // String temp = "[{\"days\":[{\"value\":\"1\",\"label\":\"星期一\",\"checked\":true},{\"value\":\"2\",\"label\":\"星期二\",\"checked\":true},{\"value\":\"3\",\"label\":\"星期三\",\"checked\":true},{\"value\":\"4\",\"label\":\"星期四\",\"checked\":true},{\"value\":\"5\",\"label\":\"星期五\",\"checked\":true},{\"value\":\"6\",\"label\":\"星期六\",\"checked\":false},{\"value\":\"7\",\"label\":\"星期日\",\"checked\":false}],\"startTime\":\"00:00\",\"endTime\":\"23:59\"}]"; // // 可用时间 // LocalDate today = LocalDate.now(); // // int week = today.getDayOfWeek().getValue(); // // JSONArray time = JSONArray.parseArray(temp); // int i = 0; // JSONArray jsonArray = new JSONArray(); // // StringBuilder startTime = new StringBuilder(); // StringBuilder endTime = new StringBuilder(); // // String string = LocalDate.now().toString(); // // for (Object o : time) { // JSONObject jsonObject = (JSONObject) o; // for (Object days : jsonObject.getJSONArray("days")) { // JSONObject jsonObject1 = (JSONObject) days; // if (jsonObject1.getString("value").equals(String.valueOf(week))&&jsonObject1.getBoolean("checked")){ // JSONObject jsonObject2 = new JSONObject(); // String s1 = string+" "+jsonObject.getString("startTime")+":00"; // String e1 = string+" "+jsonObject.getString("endTime")+":00"; // // 转化为Date类型 // Date start = DateUtil.parse(s1,"yyyy-MM-dd HH:mm:ss"); // Date end = DateUtil.parse(e1,"yyyy-MM-dd HH:mm:ss"); // jsonObject2.put("startTime",start.getTime()); // jsonObject2.put("endTime",end.getTime()); // jsonArray.add(jsonObject2); // } // // // } // i++; // } // System.err.println(jsonArray); } /** * 个人中心-我的惠民卡-查看详情 @@ -928,7 +882,7 @@ } } String temp = "{\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + tPayHuimin.getStudentId() + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; String temp = "{\"id\":"+tPayHuimin.getId() + ","+"\"sid\":" + sid.toJSONString() + "," + "\"rid\":" + rid + "," + "\"uid\":\"" + tPayHuimin.getStudentId() + "\"," + "\"time\":" + jsonArray.toJSONString() + ",\"type\":" + 2 + "}"; myHuiminCardDetailVO.setQrCode(temp); myHuiminCardDetailVO.setCardId(tPayHuimin.getCardId()); myHuiminCardDetailVO.setHuiminCard(byId); cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminRecordController.java
New file @@ -0,0 +1,43 @@ package com.dsh.activity.controller; import com.dsh.activity.entity.THuiminRecord; import com.dsh.activity.entity.TPayHuimin; import com.dsh.activity.service.*; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.Date; /** * 硬件方调用 存储惠民卡使用记录 * @author zhibing.pu * @date 2023/6/24 11:27 */ @RestController @RequestMapping("/base/huimin") public class HuiminRecordController { @Resource private HuiminRecordService huiminRecordService; @Resource private PayHuiminService payHuiminService; /** * 硬件开门后回调 存储惠民卡使用记录 */ @PostMapping("/record") public void aliPayHuiminCallback(Integer id,Integer uid) { System.err.println("硬件开门后回调 存储惠民卡使用记录"); System.err.println("id:"+id); System.err.println("uid:"+uid); if (id!=null){ THuiminRecord huiminRecord = new THuiminRecord(); TPayHuimin payHuimin = payHuiminService.getById(id); huiminRecord.setPayId(id); huiminRecord.setHuiminCardId(payHuimin.getCardId()); huiminRecord.setInsertTime(new Date()); huiminRecord.setAppUserId(uid); huiminRecordService.save(huiminRecord); } } } cloud-server-activity/src/main/java/com/dsh/activity/controller/WeiXinV3Controller.java
@@ -1,76 +1,76 @@ package com.dsh.activity.controller; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.dsh.activity.entity.*; import com.dsh.activity.feignclient.account.StudentClient; import com.dsh.activity.feignclient.other.SiteClient; import com.dsh.activity.feignclient.other.StoreClient; import com.dsh.activity.feignclient.other.model.Site; import com.dsh.activity.feignclient.other.model.Store; import com.dsh.activity.model.response.*; import com.dsh.activity.service.*; import com.dsh.activity.util.*; //import com.dsh.activity.util.wx.WechatPaymentService; import com.dsh.activity.util.wx.WxAppPayService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.*; import java.util.stream.Collectors; /** * @author zhibing.pu * @date 2023/6/24 11:27 */ @RestController @RequestMapping("/base") public class WeiXinV3Controller { // @Resource // private WechatPaymentService wechatPaymentService; @Autowired private WxAppPayService wxAppPayService; @ResponseBody @PostMapping("/testWeiXinV3") @ApiOperation(value = "获取添加人员、选择人员说明文案") @ApiImplicitParams({ @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") }) public ResultUtil getContentForStudent() throws Exception { // Map<String, Object> stringObjectMap = wechatPaymentService.weChatDoUnifiedOrder(); // ... 在你的下单方法中调用 ... try { String description = "商品描述"; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String outTradeNo =sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); BigDecimal amount = new BigDecimal("0.01"); // 支付金额,例如1分钱 Map<String, String> payParams = wxAppPayService.createOrder(description, outTradeNo, amount); return ResultUtil.success(payParams); // 将 payParams 返回给你的APP前端,前端使用这些参数调起微信支付SDK // return ResponseEntity.ok(payParams); // 示例 } catch (Exception e) { // 处理异常 // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("下单失败"); } return ResultUtil.success(); } } //package com.dsh.activity.controller; // //import cn.hutool.core.collection.CollUtil; //import com.alibaba.fastjson.JSONArray; //import com.alibaba.fastjson.JSONObject; //import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; //import com.dsh.activity.entity.*; //import com.dsh.activity.feignclient.account.StudentClient; //import com.dsh.activity.feignclient.other.SiteClient; //import com.dsh.activity.feignclient.other.StoreClient; //import com.dsh.activity.feignclient.other.model.Site; //import com.dsh.activity.feignclient.other.model.Store; //import com.dsh.activity.model.response.*; //import com.dsh.activity.service.*; //import com.dsh.activity.util.*; ////import com.dsh.activity.util.wx.WechatPaymentService; //import com.dsh.activity.util.wx.WxAppPayService; //import io.swagger.annotations.Api; //import io.swagger.annotations.ApiImplicitParam; //import io.swagger.annotations.ApiImplicitParams; //import io.swagger.annotations.ApiOperation; //import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.web.bind.annotation.PostMapping; //import org.springframework.web.bind.annotation.RequestMapping; //import org.springframework.web.bind.annotation.ResponseBody; //import org.springframework.web.bind.annotation.RestController; // //import javax.annotation.Resource; //import java.math.BigDecimal; //import java.text.SimpleDateFormat; //import java.time.LocalDate; //import java.time.LocalDateTime; //import java.time.ZoneId; //import java.util.*; //import java.util.stream.Collectors; // ///** // * @author zhibing.pu // * @date 2023/6/24 11:27 // */ //@RestController //@RequestMapping("/base") //public class WeiXinV3Controller { // //// @Resource //// private WechatPaymentService wechatPaymentService; // @Autowired // private WxAppPayService wxAppPayService; // @ResponseBody // @PostMapping("/testWeiXinV3") // @ApiOperation(value = "获取添加人员、选择人员说明文案") // @ApiImplicitParams({ // @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....") // }) // public ResultUtil getContentForStudent() throws Exception { //// Map<String, Object> stringObjectMap = wechatPaymentService.weChatDoUnifiedOrder(); // // ... 在你的下单方法中调用 ... // try { // String description = "商品描述"; // SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); // String outTradeNo =sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); // BigDecimal amount = new BigDecimal("0.01"); // 支付金额,例如1分钱 // Map<String, String> payParams = wxAppPayService.createOrder(description, outTradeNo, amount); // return ResultUtil.success(payParams); // // // 将 payParams 返回给你的APP前端,前端使用这些参数调起微信支付SDK // // return ResponseEntity.ok(payParams); // 示例 // // } catch (Exception e) { // // 处理异常 // // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("下单失败"); // } // return ResultUtil.success(); // } // //} cloud-server-activity/src/main/java/com/dsh/activity/entity/THuiminRecord.java
@@ -45,6 +45,12 @@ @ApiModelProperty(value = "惠民卡id") private Integer huiminCardId; /** * 惠民卡id */ @TableField("payId") @ApiModelProperty(value = "惠民卡支付记录id") private Integer payId; /** *使用时间 */ @ApiModelProperty(value = "使用时间") cloud-server-activity/src/main/java/com/dsh/activity/model/response/MyHuiminCardVO.java
@@ -25,7 +25,7 @@ private String cover; @ApiModelProperty("是否过期 0否1是") private Integer isExpire; @ApiModelProperty("是否可以退款 0否1是") @ApiModelProperty("是否可以退款 0否1是 2退款中") private Integer isRefund; @ApiModelProperty("状态1待支付2使用中3已退款") private Integer status; cloud-server-activity/src/main/java/com/dsh/activity/service/impl/PayHuiminServiceImpl.java
@@ -50,8 +50,7 @@ List<SalesDetailVO> records = salesDetailVOPage.getRecords(); for (SalesDetailVO record : records) { List<THuiminRecord> list = huiminRecordService.list(new LambdaQueryWrapper<THuiminRecord>() .eq(THuiminRecord::getAppUserId, record.getAppUserId()) .eq(THuiminRecord::getHuiminCardId, record.getCarId())); .eq(THuiminRecord::getPayId, record.getId())); record.setUseTimes(list.size()); } if (CollUtil.isNotEmpty(records)){ @@ -82,9 +81,8 @@ public ResultUtil<?> refund(Integer id) throws AlipayApiException { TPayHuimin payHuimin = this.getById(id); if (Objects.nonNull(payHuimin)) { Integer count = huiminRecordService.lambdaQuery().eq(THuiminRecord::getAppUserId, payHuimin.getAppUserId()) .eq(THuiminRecord::getHuiminCardId, payHuimin.getCardId()) .lt(THuiminRecord::getInsertTime, DateUtil.addDay(payHuimin.getPaymentTime(),7)) Integer count = huiminRecordService.lambdaQuery() .eq(THuiminRecord::getPayId, payHuimin.getId()) .count(); if (count > 0 || new Date().after(DateUtil.addDay(payHuimin.getPaymentTime(),7))) { //超过七日或者七日内有使用记录的退款:更改状态,实际退款线下操作。 @@ -92,7 +90,7 @@ } else { if (payHuimin.getPaymentType() == 1) { Map<String, String> map = payMoneyUtil.wxRefund(payHuimin.getOrderNumber(), payHuimin.getCode(), payHuimin.getSalesMoney().toString(), payHuimin.getSalesMoney().toString(), "/base/worldCup/wxRefundWorldCupCallback"); payHuimin.getSalesMoney().toString(), payHuimin.getSalesMoney().toString(), "/base/huimin/callBack/wxRefundHuiminCallback"); if (!"SUCCESS".equals(map.get("return_code"))) { System.err.println("-------------微信退款失败---------"); System.err.println(map.get("return_msg")); cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java
@@ -62,7 +62,6 @@ private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号 private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 // private String callbackPath = "http://vbef9arg13uu.guyubao.com/activity";//支付回调网关地址 private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径 @@ -243,7 +242,7 @@ extendParams.setRoyaltyFreeze("false");// 冻结资金 用于后续分账处理 model.setExtendParams(extendParams); request.setBizModel(model); request.setNotifyUrl(callbackPath + notifyUrl); request.setNotifyUrl("http://8.137.22.229:5002" + notifyUrl); try { //这里和普通的接口调用不同,使用的是sdkExecute @@ -408,7 +407,7 @@ Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); map.put("sub_mch_id", "123456"); // map.put("sub_mch_id", "123456"); map.put("nonce_str", nonce_str); String temp = ""; if (body.split("-").length>1){ cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WeChatPaymentServiceImpl.java
File was deleted cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WechatPaymentService.java
File was deleted cloud-server-activity/src/main/java/com/dsh/activity/util/wx/WxAppPayService.java
@@ -1,221 +1,222 @@ package com.dsh.activity.util.wx; import com.dsh.activity.util.wx.WXPayConstants; import com.dsh.activity.util.wx.WXPaySignatureCertificateUtil; import com.dsh.activity.util.wx.WxV3PayConfig; import com.fasterxml.jackson.databind.JsonNode; // 引入Jackson库处理JSON import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @Service public class WxAppPayService { private static final Logger log = LoggerFactory.getLogger(WxAppPayService.class); private final ObjectMapper objectMapper; // 用于JSON序列化和反序列化 private final CloseableHttpClient wechatPayClient; // 注入通过工具类创建的HTTP客户端 @Autowired public WxAppPayService(ObjectMapper objectMapper) throws IOException { this.objectMapper = objectMapper; // 在构造函数中初始化带有签名验证功能的HTTP客户端 this.wechatPayClient = WXPaySignatureCertificateUtil.getWechatPayClient(); log.info("微信支付V3 HTTP客户端初始化完成。"); } /** * 创建APP支付预付单 (统一下单) * * @param description 商品描述 * @param outTradeNo 商户订单号 (要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一) * @param totalAmount 支付总金额 (单位:元) * @return 用于调起APP支付的参数 Map (appid, partnerid, prepayid, package, noncestr, timestamp, sign) * @throws IOException 网络或IO异常 * @throws RuntimeException 支付请求失败或处理异常 */ public Map<String, String> createOrder(String description, String outTradeNo, BigDecimal totalAmount) throws IOException { // 1. 构建请求URL String url = WXPayConstants.DOMAIN_API + WXPayConstants.PAY_TRANSACTIONS_APP; HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // 2. 构建请求体 JSON ObjectNode rootNode = objectMapper.createObjectNode(); // rootNode.put("appid", WxV3PayConfig.APP_ID);//服务商不需要该字段 // rootNode.put("mchid", WxV3PayConfig.Mch_ID);//服务商不需要该字段 rootNode.put("description", description); rootNode.put("out_trade_no", outTradeNo); rootNode.put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL); // 使用常量中的回调地址 ObjectNode amountNode = objectMapper.createObjectNode(); // 微信支付金额单位为分,需要转换 amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); amountNode.put("currency", "CNY"); // 货币类型,默认人民币 rootNode.set("amount", amountNode); // 如果你是服务商模式,需要添加子商户信息 rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); rootNode.put("sub_mchid", "123"); rootNode.put("sp_appid", "wx41d32f362ba0f911"); // rootNode.put("sub_appid", "子商户AppID"); // 如果子商户需要用自己的AppID拉起支付 String requestBody = rootNode.toString(); log.info("微信APP支付下单请求体: {}", requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // 3. 发送请求 try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("微信APP支付下单响应状态码: {}, 响应体: {}", statusCode, responseBody); if (statusCode == 200) { // HTTP状态码 200 表示成功 JsonNode responseNode = objectMapper.readTree(responseBody); String prepayId = responseNode.get("prepay_id").asText(); log.info("成功获取预支付交易会话标识 (prepay_id): {}", prepayId); // 4. 生成调起支付所需的参数 Map<String, String> payParams = WXPaySignatureCertificateUtil.buildAppPayParams(prepayId); log.info("生成APP支付参数: {}", payParams); return payParams; } else { // 处理错误情况 log.error("微信APP支付下单失败,状态码: {}, 响应: {}", statusCode, responseBody); // 可以根据 responseBody 中的 code 和 message 进一步分析错误 throw new RuntimeException("微信APP支付下单失败: " + responseBody); } } catch (Exception e) { log.error("微信APP支付下单请求执行异常", e); throw new IOException("微信APP支付下单请求执行异常", e); } } /** * 关闭订单 (根据商户订单号) * * @param outTradeNo 商户订单号 * @return true 如果关闭成功或订单已关闭/不存在 (根据微信文档,成功是204 No Content) * @throws IOException 网络或IO异常 * @throws RuntimeException 关闭请求失败或处理异常 */ public boolean closeOrder(String outTradeNo) throws IOException { // 1. 构建请求URL, 注意替换占位符 String url = WXPayConstants.DOMAIN_API + WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO.replace("{}", outTradeNo); HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // 2. 构建请求体 JSON (只需要商户号) ObjectNode rootNode = objectMapper.createObjectNode(); rootNode.put("mchid", WxV3PayConfig.Mch_ID); // 如果是服务商模式,则用 sp_mchid rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); String requestBody = rootNode.toString(); log.info("微信关单请求 URL: {}, 请求体: {}", url, requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // 3. 发送请求 try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); // 关单成功时,微信返回 HTTP 状态码 204 No Content log.info("微信关单响应状态码: {}", statusCode); if (statusCode == 204) { log.info("订单 {} 关闭成功。", outTradeNo); return true; } else { String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.error("微信关单失败,商户订单号: {}, 状态码: {}, 响应: {}", outTradeNo, statusCode, responseBody); // 根据需要可以解析responseBody获取错误详情 return false; // 或者抛出异常,根据业务决定 } } catch (Exception e) { log.error("微信关单请求执行异常, 商户订单号: {}", outTradeNo, e); throw new IOException("微信关单请求执行异常", e); } } // --- 退款相关方法 (可选) --- /** * 申请退款 * * @param outTradeNo 原商户订单号 * @param outRefundNo 商户退款单号 (商户系统内部的退款单号,要求唯一) * @param reason 退款原因 (可选) * @param refundAmount 退款金额 (单位:元) * @param totalAmount 原订单总金额 (单位:元) * @return 退款处理结果,可以返回微信返回的JSON节点或自定义对象 * @throws IOException 网络或IO异常 * @throws RuntimeException 退款请求失败或处理异常 */ public JsonNode createRefund(String outTradeNo, String outRefundNo, String reason, BigDecimal refundAmount, BigDecimal totalAmount) throws IOException { String url = WXPayConstants.DOMAIN_API + WXPayConstants.REFUND_DOMESTIC_REFUNDS; HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Accept", "application/json"); httpPost.addHeader("Content-type", "application/json; charset=utf-8"); ObjectNode rootNode = objectMapper.createObjectNode(); // 如果是服务商模式,需要添加子商户号 // rootNode.put("sub_mchid", "子商户号"); rootNode.put("out_trade_no", outTradeNo); rootNode.put("out_refund_no", outRefundNo); if (reason != null && !reason.isEmpty()) { rootNode.put("reason", reason); } // 设置退款回调地址 rootNode.put("notify_url", WXPayConstants.WECHAT_REFUNDS_NOTIFY_URL); ObjectNode amountNode = objectMapper.createObjectNode(); amountNode.put("refund", refundAmount.multiply(new BigDecimal("100")).intValue()); // 退款金额,分 amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); // 原订单金额,分 amountNode.put("currency", "CNY"); rootNode.set("amount", amountNode); String requestBody = rootNode.toString(); log.info("微信申请退款请求体: {}", requestBody); httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { int statusCode = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("微信申请退款响应状态码: {}, 响应体: {}", statusCode, responseBody); if (statusCode == 200) { // 成功受理 log.info("微信退款申请成功受理。"); return objectMapper.readTree(responseBody); } else { log.error("微信申请退款失败,状态码: {}, 响应: {}", statusCode, responseBody); throw new RuntimeException("微信申请退款失败: " + responseBody); } } catch (Exception e) { log.error("微信申请退款请求执行异常", e); throw new IOException("微信申请退款请求执行异常", e); } } } //package com.dsh.activity.util.wx; // //import com.dsh.activity.util.wx.WXPayConstants; //import com.dsh.activity.util.wx.WXPaySignatureCertificateUtil; //import com.dsh.activity.util.wx.WxV3PayConfig; //import com.fasterxml.jackson.databind.JsonNode; // 引入Jackson库处理JSON //import com.fasterxml.jackson.databind.ObjectMapper; //import com.fasterxml.jackson.databind.node.ObjectNode; //import org.apache.http.client.methods.CloseableHttpResponse; //import org.apache.http.client.methods.HttpPost; //import org.apache.http.entity.StringEntity; //import org.apache.http.impl.client.CloseableHttpClient; //import org.apache.http.util.EntityUtils; //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.stereotype.Component; //import org.springframework.stereotype.Service; // //import java.io.IOException; //import java.math.BigDecimal; //import java.nio.charset.StandardCharsets; //import java.util.HashMap; //import java.util.Map; // //@Component //public class WxAppPayService { // // private static final Logger log = LoggerFactory.getLogger(WxAppPayService.class); // // private final ObjectMapper objectMapper; // 用于JSON序列化和反序列化 // private final CloseableHttpClient wechatPayClient; // 注入通过工具类创建的HTTP客户端 // // @Autowired // public WxAppPayService(ObjectMapper objectMapper) throws IOException { // this.objectMapper = objectMapper; // // 在构造函数中初始化带有签名验证功能的HTTP客户端 // this.wechatPayClient = WXPaySignatureCertificateUtil.getWechatPayClient(); // log.info("微信支付V3 HTTP客户端初始化完成。"); // } // // /** // * 创建APP支付预付单 (统一下单) // * // * @param description 商品描述 // * @param outTradeNo 商户订单号 (要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一) // * @param totalAmount 支付总金额 (单位:元) // * @return 用于调起APP支付的参数 Map (appid, partnerid, prepayid, package, noncestr, timestamp, sign) // * @throws IOException 网络或IO异常 // * @throws RuntimeException 支付请求失败或处理异常 // */ // public Map<String, String> createOrder(String description, String outTradeNo, BigDecimal totalAmount) // throws IOException { // // // 1. 构建请求URL // String url = WXPayConstants.DOMAIN_API + WXPayConstants.PAY_TRANSACTIONS_APP; // HttpPost httpPost = new HttpPost(url); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // // // 2. 构建请求体 JSON // ObjectNode rootNode = objectMapper.createObjectNode(); //// rootNode.put("appid", WxV3PayConfig.APP_ID);//服务商不需要该字段 //// rootNode.put("mchid", WxV3PayConfig.Mch_ID);//服务商不需要该字段 // rootNode.put("description", description); // rootNode.put("out_trade_no", outTradeNo); // rootNode.put("notify_url", WXPayConstants.WECHAT_PAY_NOTIFY_URL); // 使用常量中的回调地址 // // ObjectNode amountNode = objectMapper.createObjectNode(); // // 微信支付金额单位为分,需要转换 // amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); // amountNode.put("currency", "CNY"); // 货币类型,默认人民币 // rootNode.set("amount", amountNode); // // // 如果你是服务商模式,需要添加子商户信息 // rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); // rootNode.put("sub_mchid", "123"); // rootNode.put("sp_appid", "wx41d32f362ba0f911"); // // rootNode.put("sub_appid", "子商户AppID"); // 如果子商户需要用自己的AppID拉起支付 // // String requestBody = rootNode.toString(); // log.info("微信APP支付下单请求体: {}", requestBody); // httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // // // 3. 发送请求 // try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { // int statusCode = response.getStatusLine().getStatusCode(); // String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); // log.info("微信APP支付下单响应状态码: {}, 响应体: {}", statusCode, responseBody); // // if (statusCode == 200) { // HTTP状态码 200 表示成功 // JsonNode responseNode = objectMapper.readTree(responseBody); // String prepayId = responseNode.get("prepay_id").asText(); // log.info("成功获取预支付交易会话标识 (prepay_id): {}", prepayId); // // // 4. 生成调起支付所需的参数 // Map<String, String> payParams = WXPaySignatureCertificateUtil.buildAppPayParams(prepayId); // log.info("生成APP支付参数: {}", payParams); // return payParams; // // } else { // // 处理错误情况 // log.error("微信APP支付下单失败,状态码: {}, 响应: {}", statusCode, responseBody); // // 可以根据 responseBody 中的 code 和 message 进一步分析错误 // throw new RuntimeException("微信APP支付下单失败: " + responseBody); // } // } catch (Exception e) { // log.error("微信APP支付下单请求执行异常", e); // throw new IOException("微信APP支付下单请求执行异常", e); // } // } // // /** // * 关闭订单 (根据商户订单号) // * // * @param outTradeNo 商户订单号 // * @return true 如果关闭成功或订单已关闭/不存在 (根据微信文档,成功是204 No Content) // * @throws IOException 网络或IO异常 // * @throws RuntimeException 关闭请求失败或处理异常 // */ // public boolean closeOrder(String outTradeNo) throws IOException { // // 1. 构建请求URL, 注意替换占位符 // String url = WXPayConstants.DOMAIN_API // + WXPayConstants.PAY_TRANSACTIONS_OUT_TRADE_NO.replace("{}", outTradeNo); // // HttpPost httpPost = new HttpPost(url); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // // // 2. 构建请求体 JSON (只需要商户号) // ObjectNode rootNode = objectMapper.createObjectNode(); // rootNode.put("mchid", WxV3PayConfig.Mch_ID); // // 如果是服务商模式,则用 sp_mchid // rootNode.put("sp_mchid", WxV3PayConfig.Mch_ID); // // String requestBody = rootNode.toString(); // log.info("微信关单请求 URL: {}, 请求体: {}", url, requestBody); // httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // // // 3. 发送请求 // try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { // int statusCode = response.getStatusLine().getStatusCode(); // // 关单成功时,微信返回 HTTP 状态码 204 No Content // log.info("微信关单响应状态码: {}", statusCode); // if (statusCode == 204) { // log.info("订单 {} 关闭成功。", outTradeNo); // return true; // } else { // String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); // log.error("微信关单失败,商户订单号: {}, 状态码: {}, 响应: {}", outTradeNo, statusCode, responseBody); // // 根据需要可以解析responseBody获取错误详情 // return false; // 或者抛出异常,根据业务决定 // } // } catch (Exception e) { // log.error("微信关单请求执行异常, 商户订单号: {}", outTradeNo, e); // throw new IOException("微信关单请求执行异常", e); // } // } // // // // --- 退款相关方法 (可选) --- // // /** // * 申请退款 // * // * @param outTradeNo 原商户订单号 // * @param outRefundNo 商户退款单号 (商户系统内部的退款单号,要求唯一) // * @param reason 退款原因 (可选) // * @param refundAmount 退款金额 (单位:元) // * @param totalAmount 原订单总金额 (单位:元) // * @return 退款处理结果,可以返回微信返回的JSON节点或自定义对象 // * @throws IOException 网络或IO异常 // * @throws RuntimeException 退款请求失败或处理异常 // */ // public JsonNode createRefund(String outTradeNo, String outRefundNo, String reason, // BigDecimal refundAmount, BigDecimal totalAmount) throws IOException { // // String url = WXPayConstants.DOMAIN_API + WXPayConstants.REFUND_DOMESTIC_REFUNDS; // HttpPost httpPost = new HttpPost(url); // httpPost.addHeader("Accept", "application/json"); // httpPost.addHeader("Content-type", "application/json; charset=utf-8"); // // ObjectNode rootNode = objectMapper.createObjectNode(); // // 如果是服务商模式,需要添加子商户号 // // rootNode.put("sub_mchid", "子商户号"); // rootNode.put("out_trade_no", outTradeNo); // rootNode.put("out_refund_no", outRefundNo); // if (reason != null && !reason.isEmpty()) { // rootNode.put("reason", reason); // } // // 设置退款回调地址 // rootNode.put("notify_url", WXPayConstants.WECHAT_REFUNDS_NOTIFY_URL); // // ObjectNode amountNode = objectMapper.createObjectNode(); // amountNode.put("refund", refundAmount.multiply(new BigDecimal("100")).intValue()); // 退款金额,分 // amountNode.put("total", totalAmount.multiply(new BigDecimal("100")).intValue()); // 原订单金额,分 // amountNode.put("currency", "CNY"); // rootNode.set("amount", amountNode); // // String requestBody = rootNode.toString(); // log.info("微信申请退款请求体: {}", requestBody); // httpPost.setEntity(new StringEntity(requestBody, StandardCharsets.UTF_8)); // // try (CloseableHttpResponse response = wechatPayClient.execute(httpPost)) { // int statusCode = response.getStatusLine().getStatusCode(); // String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); // log.info("微信申请退款响应状态码: {}, 响应体: {}", statusCode, responseBody); // // if (statusCode == 200) { // 成功受理 // log.info("微信退款申请成功受理。"); // return objectMapper.readTree(responseBody); // } else { // log.error("微信申请退款失败,状态码: {}, 响应: {}", statusCode, responseBody); // throw new RuntimeException("微信申请退款失败: " + responseBody); // } // } catch (Exception e) { // log.error("微信申请退款请求执行异常", e); // throw new IOException("微信申请退款请求执行异常", e); // } // } // //} cloud-server-activity/src/main/resources/mapper/PayHuiminMapper.xml
@@ -28,15 +28,13 @@ <if test="query.huiMinType !=null and query.huiMinType != ''"> AND thc.huiMinType = #{query.huiMinType} </if> <if test="query.operatorId !=null and query.operatorId != ''"> AND thc.huiMinType = #{query.huiMinType} <if test="query.operatorId !=null "> AND thc.operatorId = #{query.operatorId} </if> <if test="query.useId !=null and query.useId != ''"> AND FIND_IN_SET(#{query.useId},thc.useIds) </if> <if test="query.useId !=null and query.useId != ''"> AND FIND_IN_SET(#{query.useId},thc.useIds) </if> <if test="query.appUserIds != null and query.appUserIds.size()>0"> AND tph.appUserId IN <foreach collection="query.appUserIds" item="appUserId" open="(" separator="," close=")"> cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TPayHuiminController.java
@@ -142,6 +142,7 @@ records.forEach(item->{ item.setOperatorName(operatorMap.getOrDefault(item.getOperatorId(),"")); StringBuilder sb = new StringBuilder(); System.err.println("==========="+item); Arrays.stream(item.getStoreIds().split(",")).map(Integer::parseInt).forEach(s->{ sb.append( storeMap.getOrDefault(s, "")); sb.append(","); cloud-server-management/src/main/java/com/dsh/guns/modular/system/util/ImageUtils.java
@@ -66,13 +66,5 @@ } // 示例用法 public static void main(String[] args) { try { Dimension dimension = getImageDimensions("https://we-park-life.oss-cn-beijing.aliyuncs.com/img/e4ef2672d1a6456f9cd680ce51cf3a6e.jpg"); System.out.println(dimension); System.out.println(dimension.getDisplayType()); } catch (IOException e) { e.printStackTrace(); } } } cloud-server-management/src/main/webapp/WEB-INF/view/system/tHuiminCard/tHuiminCard.html
@@ -7,9 +7,9 @@ </div> <div class="ibox-content"> <el-form :inline="true" :model="query"> <el-form-item label="惠民卡名称:"> <elshou-form-item label="惠民卡名称:"> <el-input v-model="query.huiMinName" placeholder="请输入"></el-input> </el-form-item> </elshou-form-item> <el-form-item label="惠民卡类型:"> <el-select v-model="query.huiMinType" placeholder="全部">