From 0c569ab4b38d972213eeaf7e8965f33f8ec650fd Mon Sep 17 00:00:00 2001 From: luodangjia <luodangjia> Date: 星期二, 05 十一月 2024 11:19:19 +0800 Subject: [PATCH] 11.5 --- ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java | 434 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 429 insertions(+), 5 deletions(-) diff --git a/ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java b/ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java index 3699e94..0405a71 100644 --- a/ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java +++ b/ruoyi-service/ruoyi-admin/src/main/java/com/ruoyi/admin/controller/FranchiseeController.java @@ -1,29 +1,69 @@ package com.ruoyi.admin.controller; +import cn.hutool.http.HttpException; +import com.alibaba.excel.EasyExcelFactory; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alipay.api.AlipayApiException; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.admin.config.WeChatConfig; import com.ruoyi.admin.entity.*; import com.ruoyi.admin.service.*; +import com.ruoyi.admin.utils.MD5AndKL; +import com.ruoyi.admin.utils.WeChatUtil; +import com.ruoyi.admin.vo.InfoDto; +import com.ruoyi.admin.vo.MoneyRecentQuery; +import com.ruoyi.admin.vo.RencentBalance; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.GlobalException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.security.annotation.RequiresPermissions; +import com.ruoyi.common.security.service.TokenService; +import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import com.wechat.pay.java.core.exception.MalformedMessageException; +import com.wechat.pay.java.core.exception.ServiceException; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.service.partnerpayments.app.model.Transaction; +import com.wechat.pay.java.service.payments.jsapi.model.Amount; +import com.wechat.pay.java.service.payments.jsapi.JsapiService; +import com.wechat.pay.java.service.payments.jsapi.model.Payer; +import com. wechat. pay. java. service. payments. jsapi. model. PrepayRequest; +import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse; +import com.wechat.pay.java.service.payments.nativepay.NativePayService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import lombok.Getter; +import org.apache.commons.codec.CharEncoding; +import org.apache.poi.util.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.math.BigDecimal; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * <p> @@ -50,6 +90,338 @@ private MasterWorkerService masterWorkerService; @Resource private SiteService siteService; + + @Resource + private JsapiService jsapiService; + + @Resource + private WeChatConfig weChatConfig; + + @Resource + private PrivateKeySigner privateKeySigner; + + @Resource + private TFranchiseeBalanceChangeService balanceChangeService; + + private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static final Random RANDOM = new SecureRandom(); + + + @ApiOperation(value = "加盟商列表余额", tags = {"后台2.0-加盟商列表余额"}) + @PostMapping(value = "/recent/money") + public R<RencentBalance> recentmoney() { + BigDecimal balance = new BigDecimal(0); + List<Franchisee> list = franchiseeService.lambdaQuery().list(); + for (Franchisee franchisee : list) { + balance = balance.add(franchisee.getBalance()); + } + + //充值的金额 + BigDecimal balance1 = new BigDecimal(0); + List<TFranchiseeBalanceChange> list1 = balanceChangeService.lambdaQuery().eq(TFranchiseeBalanceChange::getType, 1).list(); + for (TFranchiseeBalanceChange franchiseeBalanceChange : list1) { + balance1 = balance1.add(franchiseeBalanceChange.getAmount()); + } + //扣除的金额 + BigDecimal balance2 = new BigDecimal(0); + List<TFranchiseeBalanceChange> list2 = balanceChangeService.lambdaQuery().eq(TFranchiseeBalanceChange::getType, 2).list(); + for (TFranchiseeBalanceChange franchiseeBalanceChange : list1) { + balance2 = balance2.add(franchiseeBalanceChange.getAmount()); + } + + RencentBalance balance3 = new RencentBalance(); + balance3.setBalance1(balance); + balance3.setBalance2(balance1); + balance3.setBalance3(balance2); + + return R.ok(balance3); + } + + @ApiOperation(value = "扣款记录及充值记录", tags = {"后台2.0-统一充值扣款列表","师傅段2.0-统一充值扣款列表"}) + @PostMapping(value = "/recent/money/list") + public R<Page<TFranchiseeBalanceChange>> recentmoneylist(@RequestBody MoneyRecentQuery moneyRecentQuery) { + Page<TFranchiseeBalanceChange> page = balanceChangeService.lambdaQuery().eq(moneyRecentQuery.getType() != null, TFranchiseeBalanceChange::getType, moneyRecentQuery.getType()) + .eq(moneyRecentQuery.getFranchId() != null, TFranchiseeBalanceChange::getFranchiseeId, moneyRecentQuery.getFranchId()) + .eq(moneyRecentQuery.getFranchName() != null && !"".equals(moneyRecentQuery.getFranchName()), TFranchiseeBalanceChange::getFranchiseeName, moneyRecentQuery.getFranchName()) + .ge(moneyRecentQuery.getDate1() != null, TFranchiseeBalanceChange::getCreateTime, moneyRecentQuery.getDate1()) + .le(moneyRecentQuery.getDate2() != null, TFranchiseeBalanceChange::getCreateTime, moneyRecentQuery.getDate2()) + .page(Page.of(moneyRecentQuery.getPageNum(), moneyRecentQuery.getPageSize())); + + + for (TFranchiseeBalanceChange record : page.getRecords()) { + Franchisee franchisee = franchiseeService.getById(record.getFranchiseeId()); + String siteIds = franchisee.getSiteIds(); + String cityCode = franchisee.getCityCode(); + List<Region> list = regionService.lambdaQuery().in(Region::getCode, cityCode.split(",")).list(); + List<Site> list1 = siteService.lambdaQuery().in(Site::getId, siteIds.split(",")).list(); + record.setList(list); + record.setList1(list1); + record.setFranchiseeName(franchisee.getName()); + } + return R.ok(page); + } + + @ApiOperation(value = "导出", tags = {"后台2.0-统一充值扣款列表"}) + @PostMapping(value = "/recent/money/list/export") + public R<Page<TFranchiseeBalanceChange>> export(@RequestBody MoneyRecentQuery moneyRecentQuery, HttpServletResponse response) { + List<TFranchiseeBalanceChange> page = balanceChangeService.lambdaQuery().eq(moneyRecentQuery.getType() != null, TFranchiseeBalanceChange::getType, moneyRecentQuery.getType()) + .eq(moneyRecentQuery.getFranchId() != null, TFranchiseeBalanceChange::getFranchiseeId, moneyRecentQuery.getFranchId()) + .eq(moneyRecentQuery.getFranchName() != null && !"".equals(moneyRecentQuery.getFranchName()), TFranchiseeBalanceChange::getFranchiseeName, moneyRecentQuery.getFranchName()) + .ge(moneyRecentQuery.getDate1() != null, TFranchiseeBalanceChange::getCreateTime, moneyRecentQuery.getDate1()) + .le(moneyRecentQuery.getDate2() != null, TFranchiseeBalanceChange::getCreateTime, moneyRecentQuery.getDate2()) + .list(); + + try { + response.setCharacterEncoding(Constants.UTF8); + response.setContentType("application/vnd.ms-excel"); + response.setHeader("Access-Control-Expose-Headers", "Content-disposition"); + response.setHeader("Content-Disposition", "attachment;filename=" + + URLEncoder.encode(Constants.EXCEL_ORDER_FILE_NAME, CharEncoding.UTF_8) + ".xlsx"); + } catch (UnsupportedEncodingException e) { + return R.fail("excel导出失败!"); + } + try { + // excel模板封装 + ExcelWriterBuilder excelWriterBuilder = EasyExcelFactory.write(response.getOutputStream()); + InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("template/" + Constants.EXCEL_ORDER_FILE_NAME1 + ".xlsx"); + // 自动释放资源 + try (ExcelWriter excelWriter = excelWriterBuilder.withTemplate(stream).build()) { + WriteSheet writeSheet = EasyExcelFactory.writerSheet().build(); + excelWriter.fill(page, writeSheet); + excelWriter.finish(); + } catch (Exception e) { + return R.fail("excel导出失败!"); + } + } catch (IOException e) { + return R.fail("excel导出失败!"); + } + return R.ok(); + } + + + @ApiOperation(value = "扣余额", tags = {"后台2.0-加盟商列表余额"}) + @PostMapping(value = "/recent/money/consume") + public R<Page<TFranchiseeBalanceChange>> consume(@RequestBody TFranchiseeBalanceChange franchiseeBalanceChange) { + Franchisee byId = franchiseeService.getById(franchiseeBalanceChange.getFranchiseeId()); + franchiseeBalanceChange.setFranchiseeName(byId.getName()); + balanceChangeService.save(franchiseeBalanceChange); + byId.setBalance(byId.getBalance().subtract(franchiseeBalanceChange.getAmount())); + franchiseeService.updateById(byId); + return R.ok(); + } + + @Getter + private PrivateKey privateKey; + + @ApiOperation(value = "js支付", tags = {"2.0-支付"}) + @GetMapping(value = "/js/wxPay") + public R jsPay(@RequestParam String openId,@RequestParam BigDecimal money,@RequestParam Integer userId) { + SysUser byId1 = sysUserService.getById(userId); + this.privateKey = PemUtil.loadPrivateKey(getPrivateKeyStream()); + this.privateKeySigner = new PrivateKeySigner(weChatConfig.merchantSerialNumber, privateKey); + + String code = generateTradeNumber(); + int i = money.multiply(BigDecimal.valueOf(100)).intValue(); + Franchisee byId = franchiseeService.getById(byId1.getFranchiseeId()); + + + PrepayRequest prepayRequest = new PrepayRequest(); + prepayRequest.setAppid(weChatConfig.appId); + prepayRequest.setMchid(weChatConfig.merchantId); + prepayRequest.setDescription("加盟商充值"); + prepayRequest.setOutTradeNo(code); + prepayRequest.setNotifyUrl("http://www.zhipingwang.com.cn:9090/admin/franchisee/callBack"); + Amount amount = new Amount(); + amount.setTotal(i); + prepayRequest.setAmount(amount); + Payer payer = new Payer(); + payer.setOpenid(openId); + prepayRequest.setPayer(payer); + PrepayResponse prepay = jsapiService.prepay(prepayRequest); + String timeStamp = String.valueOf(System.currentTimeMillis() / 1000); + String packageStr = "prepay_id=" + prepay.getPrepayId(); + + String prepay_id = prepay.getPrepayId(); + //重新进行签名后返回给前端 + Map<String, Object> map2 = new HashMap<>(); + map2.put("appid", weChatConfig.getAppId()); + map2.put("noncestr", code); + map2.put("package", "Sign=WXPay"); + map2.put("partnerid", weChatConfig.getMerchantId()); + map2.put("prepayid", prepay_id); + map2.put("timestamp", timeStamp); +// String s1 = this.weixinSignature(map2); + String signStr = Stream.of(weChatConfig.getAppId(), timeStamp, code, packageStr).collect(Collectors.joining("\n", "", "\n")); + String packageSign = privateKeySigner.sign(signStr.getBytes(StandardCharsets.UTF_8)).getSign(); + + map2.put("sign", packageSign); + System.err.println(map2); + + + TFranchiseeBalanceChange tFranchiseeBalanceChange = new TFranchiseeBalanceChange(); + tFranchiseeBalanceChange.setAmount(money); + tFranchiseeBalanceChange.setIs_pay(0); + tFranchiseeBalanceChange.setFranchiseeName(byId.getName()); + tFranchiseeBalanceChange.setFranchiseeId(String.valueOf(byId.getId())); + tFranchiseeBalanceChange.setType(2); + tFranchiseeBalanceChange.setCode(code); + balanceChangeService.save(tFranchiseeBalanceChange); + + return R.ok(map2); + + } + + public InputStream getPrivateKeyStream() { + // 需要证书释放 + byte[] certData; +// InputStream certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(this.privateKeyPath); + InputStream certStream = null; + try { + certStream = new FileInputStream(weChatConfig.privateKeyPath); + certData = IOUtils.toByteArray(certStream); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException("私钥文件未找到"); + }finally { + if(null != certStream){ + try { + certStream.close(); + } catch (IOException e) { + } + } + } + return new ByteArrayInputStream(certData); + } + @Resource + private TokenService tokenService; + @Resource + private NativePayService nativePayService; + + @ApiOperation(value = "扫码支付",tags = {"后台2.0-加盟商列表余额"}) + @PostMapping(value = "/code/buy") + public R buy(@RequestParam BigDecimal money) throws AlipayApiException { + Long userid = tokenService.getLoginUser().getUserid(); + SysUser byId1 = sysUserService.getById(userid); + Franchisee byId = franchiseeService.getById(byId1.getFranchiseeId()); + String code = generateTradeNumber(); + int i = money.multiply(BigDecimal.valueOf(100)).intValue(); + com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest(); + prepayRequest.setAppid(weChatConfig.appId); + prepayRequest.setMchid(weChatConfig.merchantId); + prepayRequest.setOutTradeNo(code); + prepayRequest.setDescription("购买资料"); + prepayRequest.setNotifyUrl("http://www.zhipingwang.com.cn:9090/admin/franchisee/callBack"); + com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount(); + amount.setTotal(i); + prepayRequest.setAmount(amount); + // 调用下单方法,得到应答 + com.wechat.pay.java.service.partnerpayments.app.model.PrepayResponse response; + try { + com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse prepay = nativePayService.prepay(prepayRequest); + //预支付成功,创建预支付订单 + TFranchiseeBalanceChange tFranchiseeBalanceChange = new TFranchiseeBalanceChange(); + tFranchiseeBalanceChange.setAmount(money); + tFranchiseeBalanceChange.setIs_pay(0); + tFranchiseeBalanceChange.setFranchiseeName(byId.getName()); + tFranchiseeBalanceChange.setFranchiseeId(String.valueOf(userid)); + tFranchiseeBalanceChange.setType(2); + tFranchiseeBalanceChange.setCode(code); + balanceChangeService.save(tFranchiseeBalanceChange); + return R.ok(prepay.getCodeUrl()); + } catch (HttpException e) { // 发送HTTP请求失败 +// log.error("发送HTTP请求失败: {}", e.getHttpRequest()); + } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500 +// log.error("服务返回状态异常: {}", e.getResponseBody()); + } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败 +// log.error("返回体类型不合法: {}", e.getMessage()); + } catch (Exception e) { +// log.error("预下单异常: {}", e.getMessage()); + } + return null; + + } + @Resource + private NotificationParser notificationParser; + + @ApiOperation(value = "支付回调",tags = {"微信支付回调"}) + @RequestMapping (value = "/callBack") + @Transactional + public R payNotify(HttpServletRequest request) throws Exception{ + System.err.println("======回调开始"); + Transaction transaction; + transaction = notificationParser.parse(WeChatUtil.handleNodifyRequestParam(request), Transaction.class); + if (transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS) { + //将记录变为已支付 + TFranchiseeBalanceChange one = balanceChangeService.lambdaQuery().eq(TFranchiseeBalanceChange::getCode, transaction.getOutTradeNo()).one(); + if (one.getIs_pay()==0) { + //将加盟商的余额增加 + Franchisee byId = franchiseeService.getById(one.getFranchiseeId()); + byId.setBalance(byId.getBalance().add(one.getAmount())); + franchiseeService.updateById(byId); + one.setIs_pay(1); + balanceChangeService.updateById(one); + + } + + } + return R.ok(null,"SUCCESS"); + } + + public static String generateTradeNumber() { + // 定义订单号前缀 + // 当前年月日 + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + String currentTimeStr =now.format(formatter); + // 获取当前时间戳 + long timestamp = System.currentTimeMillis(); + // 构造订单号 + return currentTimeStr + timestamp; + } + + + + private String weixinSignature(Map<String, Object> map){ + 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=" + "TA2npSNWmS0GcB0tFFRWA94rm1M0iSFs"); + String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 + return sign; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + + + + public static String generateNonceStr() { + char[] nonceChars = new char[32]; + for (int index = 0; index < nonceChars.length; ++index) { + nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + return new String(nonceChars); + } /** * 加盟商信息分页列表 @@ -103,8 +475,13 @@ @ApiImplicitParam(value = "加盟商信息id", name = "id", dataType = "Integer", required = true) }) public R<Franchisee> detail(@RequestParam("id") Integer id) { - return R.ok(franchiseeService.lambdaQuery() - .eq(Franchisee::getId, id).eq(Franchisee::getIsDelete, 0).one()); + Franchisee one = franchiseeService.lambdaQuery() + .eq(Franchisee::getId, id).eq(Franchisee::getIsDelete, 0).one(); + List<Site> list = siteService.lambdaQuery().in(Site::getId, one.getSiteIds().split(",")).list(); + //用 , 拼接 + one.setSiteStr(list.stream().map(Site::getSiteName).collect(Collectors.joining(","))); + + return R.ok(one); } /** @@ -121,6 +498,53 @@ return R.ok(Arrays.stream(franchisee.getCityCode().split(",")).collect(Collectors.toList())); } + + @ApiOperation(value = "主页信息", tags = {"2.0师傅端"}) + @GetMapping(value = "/info") + public R<InfoDto> info() { + Long userid = tokenService.getLoginUser().getUserid(); + SysUser byId = sysUserService.getById(userid); + Franchisee franchisee = franchiseeService.lambdaQuery() + .eq(Franchisee::getId, byId.getFranchiseeId()).eq(Franchisee::getIsDelete, 0).one(); + String siteIds = franchisee.getSiteIds(); + String cityCode = franchisee.getCityCode(); + List<Region> list = regionService.lambdaQuery().in(Region::getCode, cityCode.split(",")).list(); + List<Site> list1 = siteService.lambdaQuery().in(Site::getId, siteIds.split(",")).list(); + InfoDto infoDto = new InfoDto(); + infoDto.setList(list); + infoDto.setList1(list1); + infoDto.setFranchisee(franchisee); + return R.ok(infoDto); + } + + @ApiOperation(value = "主页信息", tags = {"2.0师傅端"}) + @GetMapping(value = "/info1") + public R<InfoDto> info1(Integer id) { + + Franchisee franchisee = franchiseeService.lambdaQuery() + .eq(Franchisee::getId, id).eq(Franchisee::getIsDelete, 0).one(); + String siteIds = franchisee.getSiteIds(); + String cityCode = franchisee.getCityCode(); + List<Region> list = regionService.lambdaQuery().in(Region::getCode, cityCode.split(",")).list(); + List<Site> list1 = siteService.lambdaQuery().in(Site::getId, siteIds.split(",")).list(); + InfoDto infoDto = new InfoDto(); + infoDto.setList(list); + infoDto.setList1(list1); + infoDto.setFranchisee(franchisee); + return R.ok(infoDto); + } + + @ApiOperation(value = "当前余额", tags = {"后台2.0-加盟商列表余额"}) + @GetMapping(value = "/rencentBalance") + public R<Franchisee> rencentBalance() { + Long userid = tokenService.getLoginUser().getUserid(); + SysUser byId = sysUserService.getById(userid); + Franchisee franchisee = franchiseeService.lambdaQuery() + .eq(Franchisee::getId, byId.getFranchiseeId()).eq(Franchisee::getIsDelete, 0).one(); + + return R.ok(franchisee); + } + @GetMapping(value = "/getWorkPic") public R<String> getWorkPic(@RequestParam("id") Integer id) { MasterWorker byId = masterWorkerService.getById(id); -- Gitblit v1.7.1