1. 调整微信服务中RPC服务部分结构

2. 添加云平台首页 部分接口
3. 根据微信支付202412公告,将微信支付平台证书替换为微信支付公钥。具体结果还要等一周,看切换进度
This commit is contained in:
Administrator 2025-02-03 08:59:38 +08:00
parent 7f91a73329
commit 4cb6391f42
52 changed files with 1187 additions and 92 deletions

View File

@ -66,8 +66,7 @@ public class WalletAccount implements Serializable {
@Schema(description = "状态")
private Integer status;
@Schema(description = "引入站点", requiredMode = RequiredMode.REQUIRED)
@NotBlank(message = "站点编码不能为空")
@Schema(description = "引入站点")
private String stationCode;
@Schema(description = "创建人")

View File

@ -34,6 +34,9 @@ public class WalletAccountDetail implements Serializable {
@Schema(description = "编码", requiredMode = RequiredMode.REQUIRED)
@NotBlank
private String code;
@Schema(description = "交易类型", requiredMode = RequiredMode.REQUIRED)
private Integer tradeType;
@Schema(description = "交易编码", requiredMode = RequiredMode.REQUIRED)
@NotBlank

View File

@ -22,7 +22,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@TableName("yt_t_proxy_operater")
@TableName("hd_resource.yt_t_proxy_operater")
@Schema(name = "代理运营商信息")
public class ProxyOperater implements Serializable {

View File

@ -20,7 +20,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@TableName("hd_resource.yt_t_upload_file")
@TableName("hd_resource.hd_resource.yt_t_upload_file")
@Schema(name = "上传文件表")
public class UploadFile implements Serializable {

View File

@ -20,7 +20,7 @@ import lombok.Data;
* @author zrb
* @since 2024-12-21
*/
@TableName("yt_setting_wechat_agreement")
@TableName("hd_resource.yt_setting_wechat_agreement")
@Schema(name = "微信协议")
@Data
public class WechatAgreement implements Serializable {

View File

@ -18,7 +18,7 @@ import lombok.Data;
* @since 2024-12-21
*/
@Data
@TableName("yt_setting_wechat_swiper")
@TableName("hd_resource.yt_setting_wechat_swiper")
@Schema(name = "微信轮播图设置")
public class WechatSwiper implements Serializable {

View File

@ -0,0 +1,39 @@
package com.evotech.hd.common.core.enums;
public enum OrderStatusEnums {
CREATE(1, "已创建"),
SWAP(2, "换电中"),
SWAPOVER(3, "换电完成"),
CHARGING(4, "充电中"),
CHARGED(5, "充电完成"),
TOPAY(6, "待结算"),
FINISH(7, "已完成"),
CANCLE(9, "已取消");
Integer code;
String name;
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
OrderStatusEnums(Integer code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -0,0 +1,35 @@
package com.evotech.hd.common.core.enums;
public enum PayTypeEnums {
WALLET(1, "账户余额"),
WECHAT(2, "微信"),
ALIPAY(3, "支付宝"),
BANK(4, "网银"),
OTHER(9, "其他");
Integer code;
String name;
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
PayTypeEnums(Integer code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -0,0 +1,29 @@
package com.evotech.hd.common.core.enums;
public enum TradeTypeEnums {
RECHARGE(1, "充值"),
PAYORDER(2, "支付订单"),
CASHOUT(9, "提现");
Integer code;
String name;
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
TradeTypeEnums(Integer code, String name) {
this.code = code;
this.name = name;
}
}

View File

@ -0,0 +1,46 @@
package com.evotech.hd.common.core.utils;
import java.util.Date;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
public class CommonUtil {
/**
*
* @return
*/
/**
* 交易编码30位预留2位不用
* @param type 1-微信支付 9-余额支付
* @return
*/
public static String payTradeNo(Integer type) {
String prefix = tradeNoPrefix(type);
return prefix + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN)
+ RandomUtil.randomInt(100, 1000) + RandomUtil.randomStringUpper(2);
}
/**
* 余额支付交易编码 1-充值2-订单消费9-提现
* @return
*/
public static String tradeNoPrefix(Integer type) {
String prefix = "YTHD";
if (type == 1) {
return prefix + "1001";
}
if (type == 2) {
return prefix + "1002";
}
if (type == 9) {
return prefix + "1009";
}
return prefix + "1010";
}
}

View File

@ -1,12 +1,5 @@
package com.evotech.hd.common.core.utils;
import java.util.Date;
import org.springframework.util.StringUtils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.MD5;
public class XCXUtil {
@ -20,14 +13,13 @@ public class XCXUtil {
}
/**
* 微信支付订单号30位预留2位不用
* 微信支付订单号
* @param stationCode
* @return
*/
public static String payOutTradeNo(String stationCode) {
String prefix = "YTHD" + (StringUtils.hasText(stationCode)?stationCode.substring(stationCode.length() - 4):"1001");
return prefix + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN)
+ RandomUtil.randomInt(100, 1000) + RandomUtil.randomStringUpper(2);
return CommonUtil.payTradeNo(1);
// String prefix = "YTHD" + (StringUtils.hasText(stationCode)?stationCode.substring(stationCode.length() - 4):"1001");
}
}

View File

@ -0,0 +1,70 @@
package com.evotech.hd.cloud.controller;
import java.util.List;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.evotech.hd.cloud.entity.request.HomeDataRequest;
import com.evotech.hd.cloud.entity.vo.HomeData1;
import com.evotech.hd.cloud.entity.vo.HomeData2;
import com.evotech.hd.cloud.entity.vo.HomeData3;
import com.evotech.hd.cloud.entity.vo.HomeData4;
import com.evotech.hd.cloud.entity.vo.HomeData5;
import com.evotech.hd.cloud.service.HomeService;
import com.evotech.hd.common.core.entity.Result;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@Tag(name = "首页数据")
@ApiSupport(order = 60)
@RestController
@RequestMapping("/home")
public class HomeController {
@Resource
private HomeService homeService;
@Operation(summary = "数据1-运营商,换电站,电池,机器人")
@GetMapping("/data1")
@ApiOperationSupport(order = 1)
public Result<HomeData1> homeData1(@ParameterObject HomeDataRequest hd) {
return homeService.homeData1(hd);
}
@Operation(summary = "数据2-公司、用户、车辆")
@GetMapping("/data2")
@ApiOperationSupport(order = 2)
public Result<HomeData2> homeData2() {
return homeService.homeData2();
}
@Operation(summary = "数据3-订单 可按换电站统计")
@GetMapping("/data3")
@ApiOperationSupport(order = 3)
public Result<HomeData3> homeData3(@ParameterObject HomeDataRequest hd) {
return homeService.homeData3(hd);
}
@Operation(summary = "数据4-交易 不按换电站统计")
@GetMapping("/data4")
@ApiOperationSupport(order = 4)
public Result<HomeData4> homeData4(@ParameterObject HomeDataRequest hd) {
return homeService.homeData4(hd);
}
@Operation(summary = "数据5-近6个月订单统计")
@GetMapping("/data5")
@ApiOperationSupport(order = 5)
public Result<List<HomeData5>> homeData5(@ParameterObject HomeDataRequest hd) {
return homeService.homeData5(hd);
}
}

View File

@ -99,5 +99,21 @@ public class OrderSwapBatteryController {
public Result<String> calculateCost(@NotBlank @RequestParam String orderNo) {
return orderSwapBatteryService.calculateCost(orderNo);
}
@Operation(summary = "个人账户余额支付")
@PostMapping({"/wallet/pay"})
@ApiOperationSupport(order = 10)
public Result<String> walletPay(@RequestParam String orderNo, String wuid, String uname) {
return orderSwapBatteryService.walletPay(orderNo, wuid, uname);
}
@Operation(summary = "公司账户余额支付")
@PostMapping({"/companywallet/pay"})
@ApiOperationSupport(order = 11)
public Result<String> companyWalletPay(@RequestParam String orderNo, String wuid, String uname) {
return orderSwapBatteryService.calculateCost(orderNo);
}
}

View File

@ -0,0 +1,32 @@
package com.evotech.hd.cloud.entity.request;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(name = "首页请求超参数")
@Data
public class HomeDataRequest {
@Schema(description = "运营商编码")
private String poCode;
@Schema(description = "换电站编码")
private String stationCode;
@Schema(description = "开始时间", example = "2024-10-01 00:00:00")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date timeBegin;
@Schema(description = "结束时间", example = "2025-04-01 23:59:59")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date timeEnd;
}

View File

@ -0,0 +1,34 @@
package com.evotech.hd.cloud.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "运营商,换电站,电池,机器人")
public class HomeData1 {
@Schema(description = "代理商数")
private Integer proxyer;
@Schema(description = "总换电站数")
private Integer totalStation;
@Schema(description = "营业换电站数")
private Integer workStation;
@Schema(description = "总电池数")
private Integer totalDC;
@Schema(description = "充电电池数")
private Integer chargeDC;
@Schema(description = "可用电池数")
private Integer availableDC;
@Schema(description = "总机器人数")
private Integer totalRobot;
@Schema(description = "可用机器人数")
private Integer availableRobot;
}

View File

@ -0,0 +1,19 @@
package com.evotech.hd.cloud.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "公司、用户、车辆")
public class HomeData2 {
@Schema(description = "公司数")
private Integer conpany;
@Schema(description = "用户数")
private Integer totalUser;
@Schema(description = "车辆数")
private Integer totalCar;
}

View File

@ -0,0 +1,26 @@
package com.evotech.hd.cloud.entity.vo;
import java.util.Map;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "订单")
public class HomeData3 {
@Schema(description = "总订单数")
private Integer totalOrder;
@Schema(description = "完成订单数")
private Integer finishedOrder;
@Schema(description = "进行中的订单数")
private Integer toDoOrder;
@Schema(description = "作废订单数")
private Integer cancleOrder;
private Map<String, Long> stationRatio;
}

View File

@ -0,0 +1,24 @@
package com.evotech.hd.cloud.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "交易")
public class HomeData4 {
@Schema(description = "总交易数")
private Integer totalTrade;
@Schema(description = "成功交易数")
private Integer totalSuccessTrade;
@Schema(description = "收入总钱数")
private Integer totalMoney;
@Schema(description = "支出总钱数")
private Integer totalRefund;
}

View File

@ -0,0 +1,18 @@
package com.evotech.hd.cloud.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "近6个月订单统计")
public class HomeData5 {
@Schema(description = "年月")
private String month;
@Schema(description = "数量")
private Integer totalOrder;
@Schema(description = "金额")
private Integer totalMoney;
}

View File

@ -0,0 +1,24 @@
package com.evotech.hd.cloud.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "近6个月交易")
public class HomeData6 {
@Schema(description = "年月")
private String month;
@Schema(description = "总交易数")
private Integer totalTrade;
@Schema(description = "成功交易数")
private Integer totalSuccessTrade;
@Schema(description = "收入总钱数")
private Integer totalMoney;
@Schema(description = "支出总钱数")
private Integer totalRefund;
}

View File

@ -0,0 +1,25 @@
package com.evotech.hd.cloud.service;
import java.util.List;
import com.evotech.hd.cloud.entity.request.HomeDataRequest;
import com.evotech.hd.cloud.entity.vo.HomeData1;
import com.evotech.hd.cloud.entity.vo.HomeData2;
import com.evotech.hd.cloud.entity.vo.HomeData3;
import com.evotech.hd.cloud.entity.vo.HomeData4;
import com.evotech.hd.cloud.entity.vo.HomeData5;
import com.evotech.hd.common.core.entity.Result;
public interface HomeService {
public Result<HomeData1> homeData1(HomeDataRequest hd);
public Result<HomeData2> homeData2();
public Result<HomeData3> homeData3(HomeDataRequest hd);
public Result<HomeData4> homeData4(HomeDataRequest hd);
public Result<List<HomeData5>> homeData5(HomeDataRequest hd);
}

View File

@ -27,5 +27,7 @@ public interface OrderSwapBatteryService {
public Result<List<OrderSwapBatteryStep>> listStep(String orderNo);
public Result<String> calculateCost(String orderNo);
public Result<String> walletPay(String orderNo, String wuid, String uname);
}

View File

@ -74,6 +74,7 @@ public class BatteryStationDcServiceImpl implements BatteryStationDcService {
public Result<List<BatteryStationDc>> list(PageListBatteryStationDcRequest plbsdcr) {
Page<BatteryStationDc> page = new Page<BatteryStationDc>(plbsdcr.getPageNo(), plbsdcr.getPageSize());
page = batteryStationDcDao.selectPage(page, new QueryWrapper<BatteryStationDc>()
.eq("del_flag", 0)
.eq(StringUtils.hasText(plbsdcr.getProxyId()), "proxy_id", plbsdcr.getProxyId())
.eq(StringUtils.hasText(plbsdcr.getStationCode()), "station_code", plbsdcr.getStationCode()));
if (page.getRecords().isEmpty()) {

View File

@ -23,8 +23,8 @@ import com.evotech.hd.cloud.dao.BatteryStationSecretKeyDao;
import com.evotech.hd.cloud.dao.VehicleInfoDao;
import com.evotech.hd.cloud.entity.BatteryStationSecretKey;
import com.evotech.hd.cloud.entity.request.PageListBatteryStationRequest;
import com.evotech.hd.cloud.rpc.WechatService;
import com.evotech.hd.cloud.service.BatteryStationService;
import com.evotech.hd.cloud.service.rpc.WechatService;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.BatteryStation;
import com.evotech.hd.common.core.entity.cloud.VehicleInfo;

View File

@ -0,0 +1,208 @@
package com.evotech.hd.cloud.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.evotech.hd.cloud.dao.BatteryStationDao;
import com.evotech.hd.cloud.dao.BatteryStationDcDao;
import com.evotech.hd.cloud.dao.BatteryStationRobotDao;
import com.evotech.hd.cloud.dao.CompanyDao;
import com.evotech.hd.cloud.dao.OrderSwapBatteryDao;
import com.evotech.hd.cloud.dao.TradeDetailDao;
import com.evotech.hd.cloud.dao.VehicleInfoDao;
import com.evotech.hd.cloud.entity.request.HomeDataRequest;
import com.evotech.hd.cloud.entity.vo.HomeData1;
import com.evotech.hd.cloud.entity.vo.HomeData2;
import com.evotech.hd.cloud.entity.vo.HomeData3;
import com.evotech.hd.cloud.entity.vo.HomeData4;
import com.evotech.hd.cloud.entity.vo.HomeData5;
import com.evotech.hd.cloud.service.HomeService;
import com.evotech.hd.common.core.dao.resource.ProxyOperaterDao;
import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.BatteryStation;
import com.evotech.hd.common.core.entity.cloud.BatteryStationDc;
import com.evotech.hd.common.core.entity.cloud.BatteryStationRobot;
import com.evotech.hd.common.core.entity.cloud.Company;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.common.core.entity.cloud.VehicleInfo;
import com.evotech.hd.common.core.entity.resource.ProxyOperater;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import com.evotech.hd.common.core.enums.TradeResultEnums;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import jakarta.annotation.Resource;
@Service
public class HomeServiceImpl implements HomeService {
@Resource
private ProxyOperaterDao proxyOperaterDao;
@Resource
private BatteryStationDao batteryStationDao;
@Resource
private BatteryStationDcDao batteryStationDcDao;
@Resource
private BatteryStationRobotDao batteryStationRobotDao;
@Resource
private CompanyDao companyDao;
@Resource
private WechatUserDao wechatUserDao;
@Resource
private VehicleInfoDao vehicleInfoDao;
@Resource
private OrderSwapBatteryDao orderSwapBatteryDao;
@Resource
private TradeDetailDao tradeDetailDao;
@Override
public Result<HomeData1> homeData1(HomeDataRequest hd) {
// 1. 运营商
List<ProxyOperater> list1 = proxyOperaterDao.selectList(new QueryWrapper<ProxyOperater>()
.eq(StringUtils.hasText(hd.getPoCode()), "pocode", hd.getPoCode()));
HomeData1 data = new HomeData1();
data.setProxyer(list1.size());
// 2. 换电站
List<BatteryStation> list2 = batteryStationDao.selectList(new QueryWrapper<BatteryStation>()
.eq("del_flag", 0)
.eq(StringUtils.hasText(hd.getPoCode()), "proxy_id", hd.getPoCode())
.eq(StringUtils.hasText(hd.getStationCode()), "code", hd.getStationCode()));
data.setTotalStation(list2.size());
int size1 = list2.stream().filter(i -> i.getStatus() == 1).toList().size();
data.setWorkStation(size1);
// 电池
List<BatteryStationDc> list3 = batteryStationDcDao.selectList(new QueryWrapper<BatteryStationDc>()
.eq("del_flag", 0)
.eq(StringUtils.hasText(hd.getPoCode()), "proxy_id", hd.getPoCode())
.eq(StringUtils.hasText(hd.getStationCode()), "station_code", hd.getStationCode()));
data.setTotalDC(list3.size());
int dcSize1 = list3.stream().filter(i -> i.getStatus() == 2).toList().size();
data.setChargeDC(dcSize1);
int dcSize2 = list3.stream().filter(i -> i.getStatus() == 3).toList().size();
data.setAvailableDC(dcSize2);
// 机器人
List<BatteryStationRobot> list4 = batteryStationRobotDao.selectList(new QueryWrapper<BatteryStationRobot>()
.eq(StringUtils.hasText(hd.getStationCode()), "station_code", hd.getStationCode()));
data.setTotalRobot(list4.size());
int robotSize1 = list4.stream().filter(i -> i.getStatus() == 1).toList().size();
data.setAvailableRobot(robotSize1);
return new Result<HomeData1>().success(data);
}
@Override
public Result<HomeData2> homeData2() {
HomeData2 data = new HomeData2();
// 1. 公司
Long count1 = companyDao.selectCount(new QueryWrapper<Company>());
data.setConpany(count1.intValue());
// 2. 用户
Long count2 = wechatUserDao.selectCount(new QueryWrapper<WechatUser>());
data.setTotalUser(count2.intValue());
// 3. 车辆
Long count3 = vehicleInfoDao.selectCount(new QueryWrapper<VehicleInfo>());
data.setTotalCar(count3.intValue());
return new Result<HomeData2>().success(data);
}
@Override
public Result<HomeData3> homeData3(HomeDataRequest hd) {
if (hd.getTimeBegin() == null || hd.getTimeEnd() == null) {
return new Result<HomeData3>().error("时间范围未填写!");
}
HomeData3 data = new HomeData3();
// 订单
List<OrderSwapBattery> orderList = orderSwapBatteryDao.selectList(new QueryWrapper<OrderSwapBattery>()
.eq(StringUtils.hasText(hd.getStationCode()), "station_code", hd.getStationCode())
.ge("order_time", hd.getTimeBegin())
.le("order_time", hd.getTimeEnd()));
data.setTotalOrder(orderList.size());
long count1 = orderList.stream().filter(i -> i.getStatus() < 7).count();
data.setToDoOrder((int)count1);
long count2 = orderList.stream().filter(i -> i.getStatus() == 7).count();
data.setFinishedOrder((int)count2);
long count3 = orderList.stream().filter(i -> i.getStatus() == 9).count();
data.setCancleOrder((int)count3);
Map<String, Long> map = orderList.parallelStream().map(i -> {
i.setStationCode(i.getStationCode() + "---" + i.getStationName());
return i;
}).collect(Collectors.groupingBy(OrderSwapBattery::getStationCode, Collectors.counting()));
data.setStationRatio(map);
return new Result<HomeData3>().success(data);
}
@Override
public Result<HomeData4> homeData4(HomeDataRequest hd) {
if (hd.getTimeBegin() == null || hd.getTimeEnd() == null) {
return new Result<HomeData4>().error("时间范围未填写!");
}
HomeData4 data = new HomeData4();
// 交易
List<TradeDetail> tradeList = tradeDetailDao.selectList(new QueryWrapper<TradeDetail>()
.ge("pay_time", hd.getTimeBegin())
.le("pay_time", hd.getTimeEnd()));
data.setTotalTrade(tradeList.size());
tradeList = tradeList.stream().filter(i -> TradeResultEnums.SUCCESS.getName().equals(i.getPayResult())).toList();
data.setTotalSuccessTrade(tradeList.size());
int czSum = tradeList.stream().filter(i -> i.getTradeType() == 1).mapToInt(i -> i.getTradeAmount()).sum();
int paySum = tradeList.stream().filter(i -> i.getTradeType() == 2 && i.getPayType() != 1).mapToInt(i -> i.getTradeAmount()).sum();
data.setTotalMoney(czSum + paySum);
int refundSum = tradeList.stream().filter(i -> i.getTradeType() == 9).mapToInt(i -> i.getTradeAmount()).sum();
data.setTotalRefund(refundSum);
return new Result<HomeData4>().success(data);
}
@Override
public Result<List<HomeData5>> homeData5(HomeDataRequest hd) {
List<HomeData5> list = new ArrayList<HomeData5>();
// 1. 找出6个月
String[] monthArr = new String[7];
Date d = new Date();
monthArr[0] = DateUtil.format(d, DatePattern.SIMPLE_MONTH_FORMATTER);
for (int i = 1; i < monthArr.length; i++) {
monthArr[i] = DateUtil.format(DateUtil.offsetMonth(d, -i), DatePattern.SIMPLE_MONTH_FORMATTER);
}
Date beginTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(d, -6));
List<OrderSwapBattery> orderList = orderSwapBatteryDao.selectList(new QueryWrapper<OrderSwapBattery>()
.eq(StringUtils.hasText(hd.getStationCode()), "station_code", hd.getStationCode())
.ge("order_time", beginTime));
Map<String, Long> map1 = orderList.parallelStream().filter(i -> i.getDelFlag() == 0 && i.getStatus() <= 7)
.collect(Collectors.groupingBy(i -> DateUtil.format(i.getOrderTime(), DatePattern.SIMPLE_MONTH_FORMATTER), Collectors.counting()));
Map<String, Integer> map2 = orderList.parallelStream().filter(i -> i.getDelFlag() == 0 && i.getStatus() <= 7).filter(i -> i.getAmount() != null)
.collect(Collectors.groupingBy(i -> DateUtil.format(i.getOrderTime(), DatePattern.SIMPLE_MONTH_FORMATTER),
Collectors.reducing(0, OrderSwapBattery::getAmount, Integer::sum)
));
for (int i = 0; i < monthArr.length; i++) {
HomeData5 data = new HomeData5();
data.setMonth(monthArr[i]);
data.setTotalOrder(map1.get(monthArr[i]) == null ? 0 : map1.get(monthArr[i]).intValue());
data.setTotalMoney(map2.get(monthArr[i]) == null ? 0 : map2.get(monthArr[i]));
list.add(data);
}
return new Result<List<HomeData5>>().success(list);
}
}

View File

@ -8,6 +8,7 @@ import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -16,7 +17,10 @@ import com.evotech.hd.cloud.dao.OrderSwapBatteryDao;
import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao;
import com.evotech.hd.cloud.dao.OrderSwapBatteryStepDao;
import com.evotech.hd.cloud.dao.VehicleInfoDao;
import com.evotech.hd.cloud.dao.WalletAccountDao;
import com.evotech.hd.cloud.service.OrderSwapBatteryService;
import com.evotech.hd.cloud.service.TradeService;
import com.evotech.hd.cloud.service.WalletAccountService;
import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService;
import com.evotech.hd.cloud.utils.components.SwapOrderBasicFeeComponent;
import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
@ -25,9 +29,16 @@ import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep;
import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.common.core.entity.cloud.VehicleInfo;
import com.evotech.hd.common.core.entity.cloud.WalletAccount;
import com.evotech.hd.common.core.entity.cloud.WalletAccountDetail;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import com.evotech.hd.common.core.enums.CodeMsg;
import com.evotech.hd.common.core.enums.OrderStatusEnums;
import com.evotech.hd.common.core.enums.PayTypeEnums;
import com.evotech.hd.common.core.enums.TradeTypeEnums;
import com.evotech.hd.common.core.utils.CommonUtil;
import jakarta.annotation.Resource;
@ -48,6 +59,12 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
private SwapOrderBasicFeeComponent orderBasicFeeComponent;
@Resource
private GZHTemplateMessageService templateMessageService;
@Resource
private WalletAccountDao walletAccountDao;
@Resource
private WalletAccountService walletAccountService;
@Resource
private TradeService tradeService;
@Override
@ -169,7 +186,6 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
.eq(StringUtils.hasText(plsor.getTradeNo()), "trade_no", plsor.getTradeNo())
.ne("del_flag", 1)
.orderByDesc("pk_id"));
System.out.println(page.getTotal());
if (page.getRecords().isEmpty()) {
return new Result<List<OrderSwapBattery>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
@ -216,4 +232,73 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
return new Result<String>().success(fee);
}
@Override
@Transactional
public Result<String> walletPay(String orderNo, String wuid, String uname) {
// 订单
OrderSwapBattery order = orderSwapBatteryDao
.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderNo));
if (order.getStatus() != OrderStatusEnums.TOPAY.getCode()) {
return new Result<String>().error("订单异常!");
}
if (order.getAmount() < 1) {
return new Result<String>().error("订单金额异常!");
}
// 账户
WalletAccount wallet = walletAccountDao.selectOne(new QueryWrapper<WalletAccount>()
.eq("owner_id", wuid));
if (wallet == null) {
return new Result<String>().error("钱包账户异常!");
}
if (wallet.getTotalAmount() < order.getAmount()) {
return new Result<String>().error("钱包余额不足!");
}
// 添加交易
TradeDetail trade = new TradeDetail();
trade.setOutTradeNo(CommonUtil.payTradeNo(2));
trade.setTrader(uname);
trade.setTraderCode(wuid);
trade.setTradeType(TradeTypeEnums.PAYORDER.getCode());
trade.setOrderCount(1);
trade.setOrderNo(orderNo);
trade.setTradeAmount(order.getAmount());
trade.setPayType(PayTypeEnums.WALLET.getCode());
trade.setPayResult("SUCCESS");
trade.setPayMsg("OK");
trade.setPayer(wuid);
trade.setWallet(wallet.getCode());
tradeService.add(trade);
// 添加明细
WalletAccountDetail wad = new WalletAccountDetail();
wad.setPreTotalAmount(wallet.getTotalAmount());
wad.setPreRechargeAmount(wallet.getRechargeAmount());
wad.setPreGiftAmount(0);
// TODO 写一个算法计算充值的减多少赠送的减多少总金额减多少
wad.setTradeRechargeAmount(-order.getAmount());
wad.setTradeGiftAmount(0);
wad.setTradeTotalAmount(wad.getTradeRechargeAmount() + wad.getTradeGiftAmount());
wad.setCode(wallet.getCode());
wad.setTradeType(trade.getTradeType());
wad.setTradeNo(trade.getOutTradeNo());
wad.setAfterTotalAmount(wad.getPreTotalAmount() - Math.abs(wad.getTradeTotalAmount()));
wad.setAfterRechargeAmount(wad.getPreRechargeAmount() - Math.abs(wad.getTradeRechargeAmount()));
wallet.setGiftAmount(wad.getPreGiftAmount() - Math.abs(wad.getTradeGiftAmount()));
walletAccountService.addDetail(wad);
// 改余额
wallet.setTotalAmount(wad.getAfterTotalAmount());
wallet.setRechargeAmount(wad.getAfterRechargeAmount());
walletAccountDao.updateById(wallet);
// 修改订单状态
order.setStatus(OrderStatusEnums.FINISH.getCode());
order.setTradeNo(trade.getOutTradeNo());
orderSwapBatteryDao.updateById(order);
return new Result<String>().success("OK");
}
}

View File

@ -11,13 +11,18 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.evotech.hd.cloud.dao.OrderSwapBatteryDao;
import com.evotech.hd.cloud.dao.TradeDetailDao;
import com.evotech.hd.cloud.dao.WalletAccountDao;
import com.evotech.hd.cloud.dao.WalletAccountDetailDao;
import com.evotech.hd.cloud.entity.request.PageListTradeRequest;
import com.evotech.hd.cloud.service.TradeService;
import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.common.core.entity.cloud.WalletAccount;
import com.evotech.hd.common.core.entity.cloud.WalletAccountDetail;
import com.evotech.hd.common.core.enums.CodeMsg;
import com.evotech.hd.common.core.enums.OrderStatusEnums;
import com.evotech.hd.common.core.enums.TradeResultEnums;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -32,6 +37,10 @@ public class TradeServiceImpl implements TradeService {
private OrderSwapBatteryDao orderSwapBatteryDao;
@Resource
private GZHTemplateMessageService templateMessageService;
@Resource
private WalletAccountDao walletAccountDao;
@Resource
private WalletAccountDetailDao walletAccountDetailDao;
@Override
public Result<Integer> add(TradeDetail td) {
@ -94,10 +103,44 @@ public class TradeServiceImpl implements TradeService {
log.info("\r\n===>>>已处理过此回调:" + tradeDetail);
return new Result<String>().error("重复消息!");
}
// 添加交易
add(tradeDetail);
// 2. 业务类型
if (tradeDetail.getTradeType() == 1) {
// 充值
WalletAccount wallet = walletAccountDao.selectOne(new QueryWrapper<WalletAccount>().eq("code", tradeDetail.getWallet()));
if (wallet == null) {
return null;
}
// 添加明细
WalletAccountDetail wad = new WalletAccountDetail();
// TODO 写一个算法计算充值的减多少赠送的减多少总金额减多少
wad.setTradeRechargeAmount(tradeDetail.getTradeAmount());
wad.setTradeGiftAmount(0);
wad.setTradeTotalAmount(wad.getTradeRechargeAmount() + wad.getTradeGiftAmount());
wad.setPreTotalAmount(wallet.getTotalAmount());
wad.setPreRechargeAmount(wallet.getRechargeAmount());
wad.setPreGiftAmount(wallet.getGiftAmount());
wad.setAfterRechargeAmount(wad.getPreRechargeAmount() + Math.abs(wad.getTradeRechargeAmount()));
wad.setAfterTotalAmount(wad.getPreTotalAmount() + Math.abs(wad.getTradeTotalAmount()));
wad.setAfterGiftAmount(wad.getPreGiftAmount() + Math.abs(wad.getTradeGiftAmount()));
wad.setTradeGiftAmount(0);
wad.setCode(tradeDetail.getWallet());
wad.setTradeType(tradeDetail.getTradeType());
wad.setTradeNo(tradeDetail.getOutTradeNo());
walletAccountDetailDao.insert(wad);
// 改余额
wallet.setTotalAmount(wad.getAfterTotalAmount());
wallet.setRechargeAmount(wad.getAfterRechargeAmount());
wallet.setGiftAmount(wad.getAfterGiftAmount());
walletAccountDao.updateById(wallet);
// 发送公众号消息
templateMessageService.rechargeMessageSend(tradeDetail, wallet.getTotalAmount());
} else if (tradeDetail.getTradeType() == 2) {
// 支付订单
@ -106,7 +149,7 @@ public class TradeServiceImpl implements TradeService {
if (TradeResultEnums.SUCCESS.getName().equals(tradeDetail.getPayResult())) {
// 支付成功修改订单
OrderSwapBattery osb = new OrderSwapBattery();
osb.setStatus(7);
osb.setStatus(OrderStatusEnums.FINISH.getCode());
osb.setTradeNo(tradeDetail.getOutTradeNo());
orderSwapBatteryDao.update(osb, new QueryWrapper<OrderSwapBattery>().eq("order_no", tradeDetail.getOrderNo()));
// 发送公众号消息

View File

@ -3,9 +3,10 @@ package com.evotech.hd.cloud.service.newthread;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.evotech.hd.cloud.rpc.WechatService;
import com.evotech.hd.cloud.service.rpc.WechatService;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import jakarta.annotation.Resource;
@ -25,5 +26,10 @@ public class GZHTemplateMessageService {
public void orderMessageSend(OrderSwapBattery osb, Integer type) {
wechatService.orderMessage(osb, type);
}
@Async("taskExecutor")
public void rechargeMessageSend(TradeDetail trade, Integer money) {
wechatService.rechargeMessage(trade, money);
}
}

View File

@ -1,4 +1,4 @@
package com.evotech.hd.cloud.rpc;
package com.evotech.hd.cloud.service.rpc;
import java.util.List;

View File

@ -1,4 +1,4 @@
package com.evotech.hd.cloud.rpc;
package com.evotech.hd.cloud.service.rpc;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cloud.openfeign.FeignClient;
@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
@FeignClient(value = "wechat-server")
public interface WechatService {
@ -30,5 +31,9 @@ public interface WechatService {
@PostMapping(value = "/wechat/gzh/msg/send/order",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<String> orderMessage(@ParameterObject OrderSwapBattery osb, @RequestParam Integer templateType);
@PostMapping(value = "/wechat/gzh/msg/send/recharge",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<String> rechargeMessage(@ParameterObject TradeDetail trade, @RequestParam Integer money);
}

View File

@ -4,7 +4,7 @@ import java.util.List;
import org.springframework.stereotype.Component;
import com.evotech.hd.cloud.rpc.ResourceService;
import com.evotech.hd.cloud.service.rpc.ResourceService;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.resource.dict.Dict;
import com.evotech.hd.common.core.enums.CodeMsg;

View File

@ -3,7 +3,7 @@ package com.evotech.hd.cloud;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import com.evotech.hd.cloud.rpc.ResourceService;
import com.evotech.hd.cloud.service.rpc.ResourceService;
import com.evotech.hd.cloud.utils.components.HDStepDictComponent;
import jakarta.annotation.Resource;

View File

@ -43,7 +43,7 @@
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.14</version>
<version>0.2.15</version>
</dependency>
<dependency>

View File

@ -29,4 +29,6 @@ public class GZHProperties {
private String orderToPayTemplateId;
private String orderEndTemplateId;
private String WalletRechargeTemplateId;
}

View File

@ -3,7 +3,8 @@ package com.evotech.hd.wechat.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.RSAPublicKeyNotificationConfig;
@Configuration
public class WechatConfig {
@ -13,16 +14,51 @@ public class WechatConfig {
return new XcxProperties();
}
/**
* 支付证书签名配置系统里面用的SDK里面的方法这个配置是SDK里面需要的
* 发送请求时要做签名用这个公钥的配置
*/
@Bean
RSAPublicKeyConfig rsaPublicKeyConfig() {
RSAPublicKeyConfig config = new RSAPublicKeyConfig.Builder()
.merchantId(xcxProperties().getMchid())
.merchantSerialNumber(xcxProperties().getSerialNo())
.privateKeyFromPath(xcxProperties().getPrivateKeyPath())
.publicKeyId(xcxProperties().getPublicKeyId())
.publicKeyFromPath(xcxProperties().getPublicKeyPath())
.apiV3Key(xcxProperties().getApiV3Key())
.build();
return config;
}
/**
* 支付证书签名配置系统里面用的SDK里面的方法这个配置是SDK里面需要的
* 支付回调时要验签用这个配置证书过渡到公钥期间用的
* 2025-02-03过渡完成100%这个不用了注释掉
*/
// @Bean
// RSACombinedNotificationConfig rsaCombinedNotificationConfig() {
// RSACombinedNotificationConfig config = new RSACombinedNotificationConfig.Builder()
// .merchantId(xcxProperties().getMchid())
// .merchantSerialNumber(xcxProperties().getSerialNo())
// .privateKeyFromPath(xcxProperties().getPrivateKeyPath())
// .publicKeyId(xcxProperties().getPublicKeyId())
// .publicKeyFromPath(xcxProperties().getPublicKeyPath())
// .apiV3Key(xcxProperties().getApiV3Key())
// .build();
// return config;
// }
/**
* 支付证书签名配置系统里面用的SDK里面的方法这个配置是SDK里面需要的
* 支付回调时要验签用这个配置使用公钥的配置
*/
@Bean
RSAAutoCertificateConfig rsaAutoCertificateConfig() {
RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder()
.merchantId(xcxProperties().getMchid())
.privateKeyFromPath(xcxProperties().getPrivateKeyPath())
.merchantSerialNumber(xcxProperties().getSerialNo())
RSAPublicKeyNotificationConfig rsaPublicKeyNotificationConfig() {
RSAPublicKeyNotificationConfig config = new RSAPublicKeyNotificationConfig.Builder()
.publicKeyId(xcxProperties().getPublicKeyId())
.publicKeyFromPath(xcxProperties().getPublicKeyPath())
.apiV3Key(xcxProperties().getApiV3Key())
.build();
return config;

View File

@ -27,5 +27,9 @@ public class XcxProperties {
private String notifyUrl;
private String refundNotifyUrl;
private String publicKeyId;
private String publicKeyPath;
}

View File

@ -3,31 +3,22 @@ package com.evotech.hd.wechat.controller;
import java.util.List;
import java.util.Map;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep;
import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest;
import com.evotech.hd.common.core.entity.cloud.VehicleInfo;
import com.evotech.hd.common.core.entity.cloud.vo.BatteryStationVO;
import com.evotech.hd.wechat.service.CloudService;
import com.evotech.hd.wechat.service.rpc.CloudService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Tag(name = "云平台API")
@ApiSupport(order = 13)
@ -39,43 +30,7 @@ public class CloudServeController {
private CloudService cloudService;
@Operation(summary = "增加预约")
@PostMapping("/order/swap/pre/add")
@ApiOperationSupport(order = 1)
public Result<Integer> addPre(@Valid @ParameterObject OrderSwapBatteryPre osbp) {
return cloudService.addPre(osbp);
}
@Operation(summary = "取消预约")
@PostMapping("/order/swap/pre/cancel")
@ApiOperationSupport(order = 2)
public Result<Integer> cancelPre(@NotNull Integer id) {
return cloudService.cancelPre(id, null);
}
@Operation(summary = "查询预约")
@GetMapping("/order/swap/pre/list")
@ApiOperationSupport(order = 3)
public Result<List<OrderSwapBatteryPre>> listPre(@RequestParam(required = false) String plateNum, @RequestParam(required = false) Integer status, @RequestParam(required = false) String ucode, @RequestParam(required = false) String stationCode) {
return cloudService.listPre(plateNum, status, ucode, stationCode);
}
@Operation(summary = "查询订单")
@GetMapping("/order/swap/list")
@ApiOperationSupport(order = 7)
public Result<List<OrderSwapBattery>> list(@ParameterObject PageListSwapOrderRequest plsor) {
if (!StringUtils.hasText(plsor.getUserId())) {
return null;
}
return cloudService.list(plsor);
}
@Operation(summary = "查询换电步骤")
@GetMapping("/order/swap/step/list")
@ApiOperationSupport(order = 8)
public Result<List<OrderSwapBatteryStep>> listStep(@NotBlank String orderNo) {
return cloudService.listStep(orderNo);
}
@Operation(summary = "查询换电站")
@GetMapping("/station/list")

View File

@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.resource.WechatAgreement;
import com.evotech.hd.common.core.entity.resource.WechatSwiper;
import com.evotech.hd.wechat.service.ResourceService;
import com.evotech.hd.wechat.service.rpc.ResourceService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;

View File

@ -0,0 +1,86 @@
package com.evotech.hd.wechat.controller;
import java.util.List;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep;
import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest;
import com.evotech.hd.wechat.service.OrderService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Tag(name = "换电订单")
@ApiSupport(order = 17)
@RestController
@RequestMapping("/order/swap")
public class SwapOrderController {
@Resource
private OrderService orderService;
@Operation(summary = "增加预约")
@PostMapping("/pre/add")
@ApiOperationSupport(order = 1)
public Result<Integer> addPre(@Valid @ParameterObject OrderSwapBatteryPre osbp) {
return orderService.addPre(osbp);
}
@Operation(summary = "取消预约")
@PostMapping("/pre/cancel")
@ApiOperationSupport(order = 2)
public Result<Integer> cancelPre(@NotNull Integer id) {
return orderService.cancelPre(id);
}
@Operation(summary = "查询预约")
@GetMapping("/pre/list")
@ApiOperationSupport(order = 3)
public Result<List<OrderSwapBatteryPre>> listPre(@RequestParam(required = false) String plateNum, @RequestParam(required = false) Integer status, @RequestParam(required = false) String ucode, @RequestParam(required = false) String stationCode) {
return orderService.listPre(plateNum, status, ucode, stationCode);
}
@Operation(summary = "查询订单")
@GetMapping("/list")
@ApiOperationSupport(order = 4)
public Result<List<OrderSwapBattery>> list(@ParameterObject PageListSwapOrderRequest plsor) {
return orderService.list(plsor);
}
@Operation(summary = "查询换电步骤")
@GetMapping("/step/list")
@ApiOperationSupport(order = 5)
public Result<List<OrderSwapBatteryStep>> listStep(@NotBlank String orderNo) {
return orderService.listStep(orderNo);
}
@Operation(summary = "个人账户余额支付")
@PostMapping({"/wallet/pay"})
@ApiOperationSupport(order = 6)
public Result<String> walletPay(@RequestParam String orderNo, String wuid, String uname) {
return orderService.walletPay(orderNo, wuid, uname);
}
}

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.wechat.service.gzh.GZHMessageTemplateService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
@ -52,5 +53,12 @@ public class GZHMessageSendController {
public Result<String> preOrderMessage2(@RequestBody OrderSwapBatteryPre osbp) {
return gzhMessageTemplateService.sendTemplateMessageOrderPre(osbp);
}
@Operation(summary = "充值成功推送公众号消息")
@PostMapping("/recharge")
@ApiOperationSupport(order = 4)
public Result<String> sendTemplateMessageRecharge(@ParameterObject TradeDetail trade, @RequestParam Integer money) {
return gzhMessageTemplateService.sendTemplateMessageRecharge(trade, money);
}
}

View File

@ -0,0 +1,45 @@
package com.evotech.hd.wechat.entity.gzh.templatemessage;
import cn.hutool.json.JSONObject;
import lombok.Getter;
/**
* 充值成功 模板消息 关键词
*/
@Getter
public class WalletRechargeTemplateData {
private JSONObject thing3;
private JSONObject amount1;
private JSONObject time4;
private JSONObject amount5;
public void setThing3(String value1) {
JSONObject jo = new JSONObject();
jo.set("value", value1);
this.thing3 = jo;
}
public void setAmount1(String value2) {
JSONObject jo = new JSONObject();
jo.set("value", value2);
this.amount1 = jo;
}
public void setTime4(String value3) {
JSONObject jo = new JSONObject();
jo.set("value", value3);
this.time4 = jo;
}
public void setAmount5(String value4) {
JSONObject jo = new JSONObject();
jo.set("value", value4);
this.amount5 = jo;
}
}

View File

@ -0,0 +1,25 @@
package com.evotech.hd.wechat.service;
import java.util.List;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep;
import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest;
public interface OrderService {
public Result<Integer> addPre(OrderSwapBatteryPre osbp);
public Result<Integer> cancelPre(Integer id);
public Result<List<OrderSwapBatteryPre>> listPre(String plateNum, Integer status, String ucode, String stationCode);
public Result<List<OrderSwapBattery>> list(PageListSwapOrderRequest plsor);
public Result<List<OrderSwapBatteryStep>> listStep(String orderNo);
public Result<String> walletPay(String orderNo, String wuid, String uname);
}

View File

@ -8,6 +8,7 @@ import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import com.evotech.hd.common.core.enums.CodeMsg;
import com.evotech.hd.wechat.config.GZHProperties;
@ -18,6 +19,7 @@ import com.evotech.hd.wechat.entity.gzh.templatemessage.Miniprogram;
import com.evotech.hd.wechat.entity.gzh.templatemessage.PayTemplateData;
import com.evotech.hd.wechat.entity.gzh.templatemessage.PreOrderTemplateData;
import com.evotech.hd.wechat.entity.gzh.templatemessage.SwapTemplateData;
import com.evotech.hd.wechat.entity.gzh.templatemessage.WalletRechargeTemplateData;
import com.evotech.hd.wechat.utils.gzh.TemplateMessageUtil;
import cn.hutool.core.date.DatePattern;
@ -160,5 +162,49 @@ public class GZHMessageTemplateService {
}
return new Result<String>().error(CodeMsg.WECHAT_API_ERROR, jo);
}
/**
* 充值成功推送公众号消息
* @param osb
* @param templateType
* @return
*/
public Result<String> sendTemplateMessageRecharge(TradeDetail trade, Integer money) {
if (!StringUtils.hasText(trade.getTraderCode())) {
return null;
}
WechatUser wuser = wechatUserDao.selectOne(new QueryWrapper<WechatUser>().eq("wuid", trade.getTraderCode()));
if (wuser == null) {
return null;
}
if (!StringUtils.hasText(wuser.getGzhOpenid())) {
return new Result<String>().error("未关注公众号!");
}
MessageTemplateSendData sendData = new MessageTemplateSendData();
sendData.setTouser(wuser.getGzhOpenid());
String templateId = gzhProperties.getWalletRechargeTemplateId();
sendData.setTemplate_id(templateId);
Miniprogram miniprogram = new Miniprogram();
miniprogram.setAppid(xcxProperties.getAppid());
miniprogram.setPath(orderPage);
sendData.setMiniprogram(miniprogram);
WalletRechargeTemplateData data = new WalletRechargeTemplateData();
data.setThing3(trade.getTrader());
data.setAmount1(trade.getTradeAmount()/100 + "");
data.setTime4(DateUtil.format(trade.getPayTime(), DatePattern.CHINESE_DATE_TIME_PATTERN));
data.setAmount5(money/100 + "");
sendData.setData(JSONUtil.parseObj(data));
String res = TemplateMessageUtil.templateMessageSend(gzhAccessTokenService.gzhAccessToken(), sendData);
JSONObject jo = JSONUtil.parseObj(res);
if (jo.getInt("errcode") == 0) {
return new Result<String>().success(jo);
}
return new Result<String>().error(CodeMsg.WECHAT_API_ERROR, jo);
}
}

View File

@ -0,0 +1,70 @@
package com.evotech.hd.wechat.service.impl;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.evotech.hd.common.core.constant.HDConstant;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryStep;
import com.evotech.hd.common.core.entity.cloud.PageListSwapOrderRequest;
import com.evotech.hd.wechat.service.OrderService;
import com.evotech.hd.wechat.service.rpc.CloudService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private CloudService cloudService;
@Resource
private HttpServletRequest request;
@Override
public Result<Integer> addPre(OrderSwapBatteryPre osbp) {
return cloudService.addPre(osbp);
}
@Override
public Result<Integer> cancelPre(Integer id) {
return cloudService.cancelPre(id, null);
}
@Override
public Result<List<OrderSwapBatteryPre>> listPre(String plateNum, Integer status, String ucode,
String stationCode) {
return cloudService.listPre(plateNum, status, ucode, stationCode);
}
@Override
public Result<List<OrderSwapBattery>> list(PageListSwapOrderRequest plsor) {
if (!StringUtils.hasText(plsor.getUserId())) {
return null;
}
return cloudService.list(plsor);
}
@Override
public Result<List<OrderSwapBatteryStep>> listStep(String orderNo) {
return cloudService.listStep(orderNo);
}
@Override
public Result<String> walletPay(String orderNo, String wuid, String uname) {
// 看账号
if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<String>().error("账号错误");
}
return cloudService.walletPay(orderNo, wuid, uname);
}
}

View File

@ -21,11 +21,12 @@ import com.evotech.hd.common.core.entity.wechat.WechatUser;
import com.evotech.hd.common.core.utils.XCXUtil;
import com.evotech.hd.wechat.config.XcxProperties;
import com.evotech.hd.wechat.entity.PrePayVO;
import com.evotech.hd.wechat.service.CloudService;
import com.evotech.hd.wechat.service.WechatPayService;
import com.evotech.hd.wechat.service.rpc.CloudService;
import com.evotech.hd.wechat.utils.wechatpay.WechatPayUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RSAPublicKeyNotificationConfig;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.core.util.IOUtil;
import com.wechat.pay.java.service.billdownload.BillDownloadService;
@ -64,7 +65,9 @@ import lombok.extern.slf4j.Slf4j;
public class WechatPayServiceImpl implements WechatPayService {
@Resource
private RSAAutoCertificateConfig config;
private RSAPublicKeyConfig config;
@Resource
private RSAPublicKeyNotificationConfig notificationConfig;
@Resource
private XcxProperties xcxProperties;
@Resource
@ -175,7 +178,7 @@ public class WechatPayServiceImpl implements WechatPayService {
throw e;
}
// 1. 初始化解析器
NotificationParser parser = new NotificationParser(config);
NotificationParser parser = new NotificationParser(notificationConfig);
// 2. 构造解析器所需参数
RequestParam param = new RequestParam.Builder()
// 序列号
@ -294,7 +297,7 @@ public class WechatPayServiceImpl implements WechatPayService {
e.printStackTrace();
}
// 1. 初始化解析器
NotificationParser parser = new NotificationParser(config);
NotificationParser parser = new NotificationParser(notificationConfig);
// 2. 构造解析器所需参数
RequestParam param = new RequestParam.Builder()
// 序列号

View File

@ -14,8 +14,8 @@ import com.evotech.hd.common.core.entity.cloud.WalletAccountDetail;
import com.evotech.hd.common.core.entity.cloud.request.PageListWalletRequest;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import com.evotech.hd.common.core.enums.CodeMsg;
import com.evotech.hd.wechat.service.CloudService;
import com.evotech.hd.wechat.service.WechatUserService;
import com.evotech.hd.wechat.service.rpc.CloudService;
import cn.hutool.core.util.DesensitizedUtil;
import jakarta.annotation.Resource;

View File

@ -1,4 +1,4 @@
package com.evotech.hd.wechat.service;
package com.evotech.hd.wechat.service.rpc;
import java.util.List;
import java.util.Map;
@ -64,7 +64,7 @@ public interface CloudService {
@GetMapping(value = "/cloud/wallet/list",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<List<WalletAccount>> listWallet(@RequestParam String wuid);
public Result<List<WalletAccount>> listWallet(@RequestParam String ownerId);
@GetMapping(value = "/cloud/wallet/detail/list",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
@ -73,5 +73,9 @@ public interface CloudService {
@PostMapping(value = "/cloud/trade/wechatpay/notify",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public void wechatPayNotifyHandle(TradeDetail tradeDetail);
@PostMapping(value = "/cloud/order/swap/wallet/pay",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<String> walletPay(@RequestParam String orderNo, @RequestParam String wuid, @RequestParam String uname);
}

View File

@ -1,4 +1,4 @@
package com.evotech.hd.wechat.service;
package com.evotech.hd.wechat.service.rpc;
import java.util.List;

View File

@ -1,6 +1,6 @@
package com.evotech.hd.wechat.utils.wechatpay;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
@ -13,7 +13,7 @@ public class WechatPayUtil {
/**
* JSAPI下单
*/
public static PrepayWithRequestPaymentResponse jsapiPrepay(RSAAutoCertificateConfig config, PrepayRequest request) {
public static PrepayWithRequestPaymentResponse jsapiPrepay(Config config, PrepayRequest request) {
JsapiServiceExtension jsapiService = new JsapiServiceExtension.Builder().config(config).build();
// 调用下单方法
PrepayWithRequestPaymentResponse response = jsapiService.prepayWithRequestPayment(request);

View File

@ -83,5 +83,20 @@
"name": "hbyt.gzh.encodingAESKey",
"type": "java.lang.String",
"description": "A description for 'hbyt.gzh.encodingAESKey'"
},
{
"name": "hbyt.xcx.public_key_id",
"type": "java.lang.String",
"description": "A description for 'hbyt.xcx.public_key_id'"
},
{
"name": "hbyt.xcx.public_key_path",
"type": "java.lang.String",
"description": "A description for 'hbyt.xcx.public_key_path'"
},
{
"name": "hbyt.gzh.wallet_recharge_template_id",
"type": "java.lang.String",
"description": "A description for 'hbyt.gzh.wallet_recharge_template_id'"
}
]}

View File

@ -49,10 +49,15 @@ hbyt:
appid: wx2ab384cf1e6f85a1
app-secret: 6c55a398703529358eac398e2bc89ae2
mchid: 1695885921
serial_no: 32B3AF8FD49920B7455E6A38B7A2AFE9004632D0
api_v3_key: KUSjZPPw96rVR2XvyBXHps3o7MvaAA0x
# 商户 API 证书私钥
# 商户私钥序列号
serial_no: 32B3AF8FD49920B7455E6A38B7A2AFE9004632D0
# 商户API证书私钥
private_key_path: src/main/resources/static/key/apiclient_key.pem
# 微信支付公钥ID
public_key_id: PUB_KEY_ID_0116958859212025012300219100001373
# 微信支付公钥
public_key_path: src/main/resources/static/key/pub_key.pem
# 支付回调地址
notify_url: https://api.evo-techina.com/wechat/wechatpay/prepayback/msg
# 退款回调地址
@ -70,4 +75,5 @@ hbyt:
order_swap_end_template_id: wGll5W3NSHXkHjcEprjUbd1shigGOqywGX7A0BVnzUs
order_to_pay_template_id: IE0_RGuN5ufU4GFrCgM9JeUfvlWfbneEuUMDsn0RBQs
order_end_template_id: C5-AGh67aFXChQONqSwxaRrJgFrn_Z25VTlTk0jHSUY
wallet_recharge_template_id: 8JXsn_VkI0S0YZSbT2EKmV_zOxyudo4IsBLeU7V-SFk

View File

@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IBW62BcctzRG5cBrdx8
asfPszU1Rf/PK0/Is5oWQez8cV3Id5gwJTHqZ6ybHZq1Zw7owr23PnDmymuYIykB
JwI0ckQuzNkxsxhCOOUqMK9UZKdnUkxO2dplA7qrQiDdfVOAs+tMdmsI4P3hEdTP
zrLQMMD5gRicKfn1SFEkZQKDgvmcNNirjBC5pNYCIHSa79F3g86wpFPbiui29o/l
1tnqLWXpCQaHQ1W3i32Na1uI4/4186ekMYhbx0JEgNGFvbpE3inxrsKQBx5Bkg3p
lbr3Yydj2qKo7RMM8HGVIrFcgOD5aEdTgxyM7WpO56kFh4w6CqCcchk1bE2ZZrqc
FwIDAQAB
-----END PUBLIC KEY-----