Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV
35个文件已添加
4 文件已重命名
19个文件已删除
20个文件已修改
| | |
| | | * @return |
| | | */ |
| | | List<VoCards> getCards(Map<?, ?> params); |
| | | |
| | | /** |
| | | * 获取已挂失,未补卡的记录数量,应用程序使用 |
| | | * @return |
| | | */ |
| | | Long getUnreplacedRecordCount(); |
| | | |
| | | /** |
| | | * 获取已挂失,未补卡的记录,应用程序使用 |
| | | * @return |
| | | */ |
| | | List<VoCards> getUnreplaced(Map<?, ?> params); |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.daoSe; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge; |
| | | import com.dy.pipIrrGlobal.voSe.VoOrders; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-05 20:21 |
| | | * @LastEditTime 2024-03-05 20:21 |
| | | * @Description |
| | | */ |
| | | |
| | | @Mapper |
| | | public interface SeVcRechargeMapper extends BaseMapper<SeVcRecharge> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int insert(SeVcRecharge record); |
| | | |
| | | int insertSelective(SeVcRecharge record); |
| | | |
| | | SeVcRecharge selectByPrimaryKey(Long id); |
| | | |
| | | int updateByPrimaryKeySelective(SeVcRecharge record); |
| | | |
| | | int updateByPrimaryKey(SeVcRecharge record); |
| | | |
| | | /** |
| | | * 根据订单号获取虚拟卡充值对象 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | SeVcRecharge getVCRechargeByorderNumber(String orderNumber); |
| | | |
| | | /** |
| | | * 根据虚拟卡号获取订单列表 |
| | | * @param virtualId |
| | | * @return |
| | | */ |
| | | List<VoOrders> getOrders(@Param("virtualId") Long virtualId); |
| | | |
| | | /** |
| | | * 根据订单号获取充值金额 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | Integer getRechargeAmountByOrderNumber(@Param("orderNumber") String orderNumber); |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.daoSe; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-10 21:05 |
| | | * @LastEditTime 2024-03-10 21:05 |
| | | * @Description |
| | | */ |
| | | |
| | | @Mapper |
| | | public interface SeVcRefundItemMapper extends BaseMapper<SeVcRefundItem> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int insert(SeVcRefundItem record); |
| | | |
| | | int insertSelective(SeVcRefundItem record); |
| | | |
| | | SeVcRefundItem selectByPrimaryKey(Long id); |
| | | |
| | | int updateByPrimaryKeySelective(SeVcRefundItem record); |
| | | |
| | | int updateByPrimaryKey(SeVcRefundItem record); |
| | | |
| | | /** |
| | | * 根据订单号获取最后一个退单号 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | String getLastRefundNumber(@Param("orderNumber") String orderNumber); |
| | | |
| | | /** |
| | | * 根据退款通知接口返回的退款单号反查退款ID,查询该退款ID下未退款记录数量 |
| | | * @param refundNumber |
| | | * @return |
| | | */ |
| | | Integer getNoRefundedCount(String refundNumber); |
| | | |
| | | /** |
| | | * 根据退款单号获取退款ID,退款通知后更新退款表所需 |
| | | * @param refundNumber |
| | | * @return |
| | | */ |
| | | Long getRefundIdByRefundNumber(String refundNumber); |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.daoSe; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefund; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 11:06 |
| | | * @LastEditTime 2024-03-08 11:06 |
| | | * @Description |
| | | */ |
| | | |
| | | @Mapper |
| | | public interface SeVcRefundMapper extends BaseMapper<SeVcRefund> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int insert(SeVcRefund record); |
| | | |
| | | int insertSelective(SeVcRefund record); |
| | | |
| | | SeVcRefund selectByPrimaryKey(Long id); |
| | | |
| | | int updateByPrimaryKeySelective(SeVcRefund record); |
| | | |
| | | int updateByPrimaryKey(SeVcRefund record); |
| | | |
| | | /** |
| | | * 根据订单号获取其各笔退款金额 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | List<Integer> getRefundAmount(@Param("orderNumber") String orderNumber); |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.daoSe; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-05 20:45 |
| | | * @LastEditTime 2024-03-05 20:45 |
| | | * @Description |
| | | */ |
| | | |
| | | @Mapper |
| | | public interface SeVirtualCardMapper extends BaseMapper<SeVirtualCard> { |
| | | int deleteByPrimaryKey(Long id); |
| | | |
| | | int insert(SeVirtualCard record); |
| | | |
| | | int insertSelective(SeVirtualCard record); |
| | | |
| | | SeVirtualCard selectByPrimaryKey(Long id); |
| | | |
| | | int updateByPrimaryKeySelective(SeVirtualCard record); |
| | | |
| | | int updateByPrimaryKey(SeVirtualCard record); |
| | | |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoSe; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.*; |
| | | import org.hibernate.validator.constraints.Length; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-05 20:21 |
| | | * @LastEditTime 2024-03-05 20:21 |
| | | * @Description |
| | | */ |
| | | |
| | | @TableName(value="se_vc_recharge", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "虚拟卡充值实体") |
| | | public class SeVcRecharge implements BaseEntity { |
| | | public static final long serialVersionUID = 202403052025001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | @Schema(description = "实体id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Long id; |
| | | |
| | | /** |
| | | * 虚拟卡ID |
| | | */ |
| | | @Schema(description = "虚拟卡ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡ID不能为空") |
| | | private Long vcId; |
| | | |
| | | /** |
| | | * 农户ID |
| | | */ |
| | | @Schema(description = "农户ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "农户ID不能为空") |
| | | private Long clientId; |
| | | |
| | | /** |
| | | * 钱包余额 |
| | | */ |
| | | @Schema(description = "钱包余额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "钱包余额不能为空") |
| | | private Double money; |
| | | |
| | | /** |
| | | * 充值后余额 |
| | | */ |
| | | @Schema(description = "充值后余额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值后余额不能为空") |
| | | private Double afterRecharge; |
| | | |
| | | /** |
| | | * 订单号 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 充值金额 |
| | | */ |
| | | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值金额不能为空") |
| | | private Integer rechargeAmount; |
| | | |
| | | /** |
| | | * 下单时间 |
| | | */ |
| | | @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date orderTime; |
| | | |
| | | /** |
| | | * 充值完成时间 |
| | | */ |
| | | @Schema(description = "充值完成时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date rechargeTime; |
| | | |
| | | /** |
| | | * 订单状态;1-未支付,2-已支付 |
| | | */ |
| | | @Schema(description = "订单状态", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @Length(message = "订单状态不大于{max},不小于{min}", min = 1, max = 2) |
| | | private Byte orderState; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoSe; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.*; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 11:06 |
| | | * @LastEditTime 2024-03-08 11:06 |
| | | * @Description |
| | | */ |
| | | |
| | | @TableName(value="se_vc_refund", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "虚拟卡退款实体") |
| | | public class SeVcRefund implements BaseEntity { |
| | | public static final long serialVersionUID = 202403081109001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | @Schema(description = "实体id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Long id; |
| | | |
| | | /** |
| | | * 虚拟卡ID |
| | | */ |
| | | @Schema(description = "虚拟卡ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡ID不能为空") |
| | | private Long vcId; |
| | | |
| | | /** |
| | | * 农户ID |
| | | */ |
| | | @Schema(description = "农户ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "农户ID不能为空") |
| | | private Long clientId; |
| | | |
| | | /** |
| | | * 虚拟卡余额,退款通知后更新余额 |
| | | */ |
| | | @Schema(description = "虚拟卡余额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Double money; |
| | | |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | private Integer refundAmount; |
| | | |
| | | /** |
| | | * 退款后余额 |
| | | */ |
| | | @Schema(description = "退款后余额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Double afterRefund; |
| | | |
| | | /** |
| | | * 申请时间 |
| | | */ |
| | | @Schema(description = "申请时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "申请时间不能为空") |
| | | private Date applicationTime; |
| | | |
| | | /** |
| | | * 审核人 |
| | | */ |
| | | @Schema(description = "审核人", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Long auditor; |
| | | |
| | | /** |
| | | * 审核时间 |
| | | */ |
| | | @Schema(description = "审核时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date auditTime; |
| | | |
| | | /** |
| | | * 审核备注 |
| | | */ |
| | | @Schema(description = "审核备注", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String remarks; |
| | | |
| | | /** |
| | | * 退款单号;12位农户号+17位时间戳+2位数量 |
| | | */ |
| | | @Schema(description = "退款单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String refundNumber; |
| | | |
| | | /** |
| | | * 退款完成时间 |
| | | */ |
| | | @Schema(description = "退款完成时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date refundTime; |
| | | |
| | | /** |
| | | * 退款状态;1-待审核,2-待退款,3-已退款 |
| | | */ |
| | | @Schema(description = "退款状态", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Byte refundStatus; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoSe; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.*; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-10 21:05 |
| | | * @LastEditTime 2024-03-10 21:05 |
| | | * @Description |
| | | */ |
| | | |
| | | @TableName(value="se_vc_refund_item", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "虚拟卡退款分项实体") |
| | | public class SeVcRefundItem implements BaseEntity { |
| | | public static final long serialVersionUID = 202403102108001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | @Schema(description = "实体id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Long id; |
| | | |
| | | /** |
| | | * 退款ID |
| | | */ |
| | | @Schema(description = "退款ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款ID不能为空") |
| | | private Long refundId; |
| | | |
| | | /** |
| | | * 订单号;12位农户好+17位时间戳 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 退款单号;12位农户号+17位时间戳+2位数量 |
| | | */ |
| | | @Schema(description = "退款单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "退款单号不能为空") |
| | | private String refundNumber; |
| | | |
| | | /** |
| | | * 退款金额;与订单对应的退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | private Integer refundAmount; |
| | | |
| | | /** |
| | | * 退款单创建时间 |
| | | */ |
| | | @Schema(description = "退款单创建时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款单创建时间不能为空") |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * 退款完成时间 |
| | | */ |
| | | @Schema(description = "退款完成时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date refundTime; |
| | | |
| | | /** |
| | | * 退款状态;1-未退款,2-已退款 |
| | | */ |
| | | @Schema(description = "退款状态", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Byte refundStatus; |
| | | |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.pojoSe; |
| | | |
| | | import com.alibaba.fastjson2.annotation.JSONField; |
| | | import com.alibaba.fastjson2.writer.ObjectWriterImplToString; |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.dy.common.po.BaseEntity; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.Max; |
| | | import jakarta.validation.constraints.Min; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.*; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-05 20:45 |
| | | * @LastEditTime 2024-03-05 20:45 |
| | | * @Description |
| | | */ |
| | | |
| | | @TableName(value="se_virtual_card", autoResultMap = true) |
| | | @Data |
| | | @Builder |
| | | @ToString |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | @Schema(name = "虚拟卡实体") |
| | | public class SeVirtualCard implements BaseEntity { |
| | | public static final long serialVersionUID = 202403052048001L; |
| | | |
| | | /** |
| | | * 主键 |
| | | */ |
| | | @JSONField(serializeUsing= ObjectWriterImplToString.class) |
| | | @TableId(type = IdType.INPUT) |
| | | @Schema(description = "实体id", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Long id; |
| | | |
| | | /** |
| | | * 农户ID |
| | | */ |
| | | @Schema(description = "农户ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "农户ID不能为空") |
| | | private Long clientId; |
| | | |
| | | /** |
| | | * 钱包余额 |
| | | */ |
| | | @Schema(description = "钱包余额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @Min(value = 0, message = "钱包余额不能小于0") |
| | | private Double money; |
| | | |
| | | /** |
| | | * 最后操作;1-开户,2-充值,3-消费,4-申请退款,5-退款审核 |
| | | */ |
| | | @Schema(description = "操作类型", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @Min(value = 1, message = "最后操作不能小于1") |
| | | @Max(value = 5, message = "最后操作不能大于5") |
| | | private Byte lastOperate; |
| | | |
| | | /** |
| | | * 最后操作时间 |
| | | */ |
| | | @Schema(description = "最后操作时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date lastOperateTime; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Date createTime; |
| | | |
| | | } |
| | |
| | | import com.dy.common.po.BaseEntity; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.Max; |
| | | import jakarta.validation.constraints.Min; |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | |
| | | @Schema(title = "ID") |
| | | @ExcelProperty("ID") |
| | | @ColumnWidth(10) |
| | | private Long id; |
| | | private String id; |
| | | |
| | | @Schema(title = "控制器地址") |
| | | @ExcelProperty("控制器地址") |
| | |
| | | @ExcelProperty("发现日期时间") |
| | | @ColumnWidth(30) |
| | | private Date findDt; |
| | | |
| | | @Schema(title = "在线状态") |
| | | @ExcelProperty("在线状态") |
| | | @ColumnWidth(6) |
| | | private String onlineState; |
| | | } |
| | |
| | | @Schema(title = "ID") |
| | | @ExcelProperty("ID") |
| | | @ColumnWidth(10) |
| | | private Long id; |
| | | private String id; |
| | | |
| | | @Schema(title = "管网流量监测站名称") |
| | | @ExcelProperty("管网流量监测站名称") |
| | |
| | | private String cardNum; |
| | | |
| | | @Schema(title = "电话号码") |
| | | private Float phone; |
| | | private String phone; |
| | | |
| | | @Schema(title = "身份证号码") |
| | | private Float idCard; |
| | | private String idCard; |
| | | |
| | | @Schema(title = "水卡状态") |
| | | private Float cardState; |
| | | private Integer cardState; |
| | | |
| | | @Schema(title = "水卡状态名称") |
| | | private String stateName; |
| New file |
| | |
| | | package com.dy.pipIrrGlobal.voSe; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Positive; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 9:36 |
| | | * @LastEditTime 2024-03-08 9:36 |
| | | * @Description |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(title = "订单视图对象") |
| | | public class VoOrders { |
| | | public static final long serialVersionUID = 202403072157001L; |
| | | |
| | | /** |
| | | * 订单号 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 充值金额 |
| | | */ |
| | | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值金额不能为空") |
| | | @Positive(message = "充值金额必须为大于0的整数") |
| | | private Integer rechargeAmount; |
| | | |
| | | /** |
| | | * 充值完成时间 |
| | | */ |
| | | @Schema(description = "充值完成时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值完成时间不能为空") |
| | | private Date rechargeTime; |
| | | } |
| | |
| | | webPort: 8085 |
| | | actutorPort: 9085 |
| | | idSuffix: 7 |
| | | webchat: |
| | | webPort: 8086 |
| | | actutorPort: 9086 |
| | | idSuffix: 8 |
| | | |
| | | #项目编号 |
| | | #projectCode: |
| | |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from pr_controller |
| | | where id = #{id,jdbcType=BIGINT} |
| | |
| | | INNER JOIN pr_intake inta ON con.intakeId = inta.id |
| | | <where> |
| | | AND ic.operateType = 1 |
| | | AND deleted = 0 |
| | | AND con.deleted = 0 |
| | | |
| | | <if test = "id != null and id > 0"> |
| | | AND con.id = ${id} |
| | |
| | | <!--根据指定条件获取控制器记录--> |
| | | <select id="getControllers" resultType="com.dy.pipIrrGlobal.voPr.VoController"> |
| | | SELECT |
| | | CAST(con.id AS char) AS id, |
| | | con.rtuAddr AS rtuAddr, |
| | | inta.name AS intakeName, |
| | | "在线" AS onlineState, |
| | | (SELECT COUNT(*) FROM pr_intake_controller WHERE controllerId = con.id AND intakeId = inta.id AND operateType = 1) AS bindNumber, |
| | | con.findDt |
| | | con.findDt AS findDt |
| | | FROM pr_controller con |
| | | INNER JOIN pr_intake_controller ic ON ic.controllerId = con.id |
| | | INNER JOIN pr_intake inta ON con.intakeId = inta.id |
| | | <where> |
| | | AND ic.operateType = 1 |
| | | AND deleted = 0 |
| | | AND con.deleted = 0 |
| | | |
| | | <if test = "id != null and id > 0"> |
| | | AND con.id = ${id} |
| | |
| | | INNER JOIN ba_district country ON pfm.countyId = country.id |
| | | INNER JOIN ba_district town ON pfm.townId = town.id |
| | | INNER JOIN ba_district village ON pfm.villageId = village.id |
| | | INNER JOIN pr_monitoring_flowmeter pmofl ON pmofl.monitoringId = pfm.id |
| | | LEFT JOIN pr_monitoring_flowmeter pmofl ON pmofl.monitoringId = pfm.id |
| | | <where> |
| | | pfm.deleted = 0 |
| | | <if test = "name != null and name !=''"> |
| | |
| | | |
| | | <!--根据指定条件获取流量监测站实体记录--> |
| | | <select id="getPrFlowMonitoring" parameterType="map" resultType="com.dy.pipIrrGlobal.voPr.VoFlowMonitoring"> |
| | | select (@i:=@i+1) AS id, |
| | | select CAST(pfm.id AS char) AS id, |
| | | CONCAT(country.`name`, town.`name`, village.`name`) AS address, |
| | | pfm.`name` AS `name`, |
| | | pmofl.operateType AS bindState |
| | |
| | | INNER JOIN ba_district country ON pfm.countyId = country.id |
| | | INNER JOIN ba_district town ON pfm.townId = town.id |
| | | INNER JOIN ba_district village ON pfm.villageId = village.id |
| | | INNER JOIN pr_monitoring_flowmeter pmofl ON pmofl.monitoringId = pfm.id, |
| | | (SELECT @i:=0) AS itable |
| | | LEFT JOIN pr_monitoring_flowmeter pmofl ON pmofl.monitoringId = pfm.id |
| | | <where> |
| | | pfm.deleted = 0 |
| | | <if test = "name != null and name !=''"> |
| | |
| | | <select id="getBindsByIntakeId" resultType="java.util.Map"> |
| | | SELECT |
| | | user.name AS userName, |
| | | con.code AS controllerCode, |
| | | <!--con.code AS controllerCode,--> |
| | | con.rtuAddr, |
| | | (CASE |
| | | WHEN ic.operateType = 1 THEN "绑定" |
| | | WHEN ic.operateType = 2 THEN "解绑" |
| | |
| | | WHEN card.state = 3 THEN '已挂失' |
| | | End) AS stateName, |
| | | '农户卡' AS cardType, |
| | | card.money |
| | | FORMAT(card.money, 2) AS money |
| | | FROM se_client_card card |
| | | INNER JOIN se_client cli ON card.clientId = cli.id |
| | | <where> |
| | |
| | | </if> |
| | | </trim> |
| | | </select> |
| | | |
| | | <!--获取已挂失未补卡的记录数量--> |
| | | <select id="getUnreplacedRecordCount" resultType="java.lang.Long"> |
| | | SELECT |
| | | COUNT(*) AS recordCount |
| | | FROM se_client_card card |
| | | INNER JOIN se_client cli ON card.clientId = cli.id |
| | | WHERE card.state = 3 AND NOT EXISTS (SELECT * FROM se_client_card card2 WHERE card.clientId = card2.clientId AND card2.state = 1) |
| | | </select> |
| | | |
| | | <!--获取已挂失未补卡的记录--> |
| | | <select id="getUnreplaced" resultType="com.dy.pipIrrGlobal.voSe.VoCards"> |
| | | SELECT |
| | | cli.clientNum, |
| | | cli.name AS clientName, |
| | | card.cardNum, |
| | | cli.phone, |
| | | cli.idCard, |
| | | card.state AS cardState, |
| | | (CASE |
| | | WHEN card.state = 1 THEN '正常' |
| | | WHEN card.state = 2 THEN '已注销' |
| | | WHEN card.state = 3 THEN '已挂失' |
| | | End) AS stateName, |
| | | '农户卡' AS cardType, |
| | | FORMAT(card.money,2) AS money |
| | | FROM se_client_card card |
| | | INNER JOIN se_client cli ON card.clientId = cli.id |
| | | WHERE card.state = 3 AND NOT EXISTS (SELECT * FROM se_client_card card2 WHERE card.clientId = card2.clientId AND card2.state = 1) |
| | | ORDER BY card.id |
| | | <trim prefix="limit " > |
| | | <if test="start != null and count != null"> |
| | | #{start,javaType=Integer,jdbcType=INTEGER}, #{count,javaType=Integer,jdbcType=INTEGER} |
| | | </if> |
| | | </trim> |
| | | </select> |
| | | </mapper> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVcRechargeMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVcRecharge"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table se_vc_recharge--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="vc_id" jdbcType="BIGINT" property="vcId" /> |
| | | <result column="client_id" jdbcType="BIGINT" property="clientId" /> |
| | | <result column="money" jdbcType="FLOAT" property="money" /> |
| | | <result column="after_recharge" jdbcType="FLOAT" property="afterRecharge" /> |
| | | <result column="order_number" jdbcType="VARCHAR" property="orderNumber" /> |
| | | <result column="recharge_amount" jdbcType="INTEGER" property="rechargeAmount" /> |
| | | <result column="order_time" jdbcType="TIMESTAMP" property="orderTime" /> |
| | | <result column="recharge_time" jdbcType="TIMESTAMP" property="rechargeTime" /> |
| | | <result column="order_state" jdbcType="TINYINT" property="orderState" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, vc_id, client_id, money, after_recharge, order_number, recharge_amount, order_time, |
| | | recharge_time, order_state |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from se_vc_recharge |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from se_vc_recharge |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRecharge"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_recharge (id, vc_id, client_id, |
| | | money, after_recharge, order_number, |
| | | recharge_amount, order_time, recharge_time, |
| | | order_state) |
| | | values (#{id,jdbcType=BIGINT}, #{vcId,jdbcType=BIGINT}, #{clientId,jdbcType=BIGINT}, |
| | | #{money,jdbcType=FLOAT}, #{afterRecharge,jdbcType=FLOAT}, #{orderNumber,jdbcType=VARCHAR}, |
| | | #{rechargeAmount,jdbcType=INTEGER}, #{orderTime,jdbcType=TIMESTAMP}, #{rechargeTime,jdbcType=TIMESTAMP}, |
| | | #{orderState,jdbcType=TINYINT}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRecharge"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_recharge |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="vcId != null"> |
| | | vc_id, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | client_id, |
| | | </if> |
| | | <if test="money != null"> |
| | | money, |
| | | </if> |
| | | <if test="afterRecharge != null"> |
| | | after_recharge, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | order_number, |
| | | </if> |
| | | <if test="rechargeAmount != null"> |
| | | recharge_amount, |
| | | </if> |
| | | <if test="orderTime != null"> |
| | | order_time, |
| | | </if> |
| | | <if test="rechargeTime != null"> |
| | | recharge_time, |
| | | </if> |
| | | <if test="orderState != null"> |
| | | order_state, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="vcId != null"> |
| | | #{vcId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="afterRecharge != null"> |
| | | #{afterRecharge,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | #{orderNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="rechargeAmount != null"> |
| | | #{rechargeAmount,jdbcType=INTEGER}, |
| | | </if> |
| | | <if test="orderTime != null"> |
| | | #{orderTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="rechargeTime != null"> |
| | | #{rechargeTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="orderState != null"> |
| | | #{orderState,jdbcType=TINYINT}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRecharge"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_recharge |
| | | <set> |
| | | <if test="vcId != null"> |
| | | vc_id = #{vcId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | client_id = #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | money = #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="afterRecharge != null"> |
| | | after_recharge = #{afterRecharge,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | order_number = #{orderNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="rechargeAmount != null"> |
| | | recharge_amount = #{rechargeAmount,jdbcType=INTEGER}, |
| | | </if> |
| | | <if test="orderTime != null"> |
| | | order_time = #{orderTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="rechargeTime != null"> |
| | | recharge_time = #{rechargeTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="orderState != null"> |
| | | order_state = #{orderState,jdbcType=TINYINT}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRecharge"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_recharge |
| | | set vc_id = #{vcId,jdbcType=BIGINT}, |
| | | client_id = #{clientId,jdbcType=BIGINT}, |
| | | money = #{money,jdbcType=FLOAT}, |
| | | after_recharge = #{afterRecharge,jdbcType=FLOAT}, |
| | | order_number = #{orderNumber,jdbcType=VARCHAR}, |
| | | recharge_amount = #{rechargeAmount,jdbcType=INTEGER}, |
| | | order_time = #{orderTime,jdbcType=TIMESTAMP}, |
| | | recharge_time = #{rechargeTime,jdbcType=TIMESTAMP}, |
| | | order_state = #{orderState,jdbcType=TINYINT} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | |
| | | <!--根据订单号获取虚拟卡充值对象--> |
| | | <select id="getVCRechargeByorderNumber" resultMap="BaseResultMap"> |
| | | SELECT |
| | | <include refid="Base_Column_List" /> |
| | | FROM se_vc_recharge |
| | | WHERE order_number = #{orderNumber} |
| | | LIMIT 0,1 |
| | | </select> |
| | | |
| | | <!--根据虚拟卡号获取订单列表--> |
| | | <select id="getOrders" resultType="com.dy.pipIrrGlobal.voSe.VoOrders"> |
| | | SELECT |
| | | order_number AS orderNumber, |
| | | recharge_amount AS rechargeAmount, |
| | | recharge_time AS rechargeTime |
| | | FROM se_vc_recharge |
| | | <where> |
| | | AND order_state = 2 |
| | | <if test = "virtualId != null and virtualId > 0"> |
| | | AND vc_id = ${virtualId} |
| | | </if> |
| | | </where> |
| | | ORDER BY order_number |
| | | </select> |
| | | |
| | | <!--根据订单号获取充值金额--> |
| | | <select id="getRechargeAmountByOrderNumber" resultType="java.lang.Integer"> |
| | | SELECT |
| | | recharge_amount AS rechargeAmount |
| | | FROM se_vc_recharge |
| | | <where> |
| | | <if test = "orderNumber != null and orderNumber !=''"> |
| | | AND order_number = #{orderNumber} |
| | | </if> |
| | | </where> |
| | | </select> |
| | | </mapper> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVcRefundItemMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table se_vc_refund_item--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="refund_id" jdbcType="BIGINT" property="refundId" /> |
| | | <result column="order_number" jdbcType="VARCHAR" property="orderNumber" /> |
| | | <result column="refund_number" jdbcType="VARCHAR" property="refundNumber" /> |
| | | <result column="refund_amount" jdbcType="INTEGER" property="refundAmount" /> |
| | | <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> |
| | | <result column="refund_time" jdbcType="TIMESTAMP" property="refundTime" /> |
| | | <result column="refund_status" jdbcType="TINYINT" property="refundStatus" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, refund_id, order_number, refund_number, refund_amount, create_time, refund_time, |
| | | refund_status |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from se_vc_refund_item |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from se_vc_refund_item |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_refund_item (id, refund_id, order_number, |
| | | refund_number, refund_amount, create_time, |
| | | refund_time, refund_status) |
| | | values (#{id,jdbcType=BIGINT}, #{refundId,jdbcType=BIGINT}, #{orderNumber,jdbcType=VARCHAR}, |
| | | #{refundNumber,jdbcType=VARCHAR}, #{refundAmount,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, |
| | | #{refundTime,jdbcType=TIMESTAMP}, #{refundStatus,jdbcType=TINYINT}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_refund_item |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="refundId != null"> |
| | | refund_id, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | order_number, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | refund_number, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | refund_amount, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | create_time, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | refund_time, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | refund_status, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="refundId != null"> |
| | | #{refundId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | #{orderNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | #{refundNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | #{refundAmount,jdbcType=INTEGER}, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | #{createTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | #{refundTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | #{refundStatus,jdbcType=TINYINT}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_refund_item |
| | | <set> |
| | | <if test="refundId != null"> |
| | | refund_id = #{refundId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="orderNumber != null"> |
| | | order_number = #{orderNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | refund_number = #{refundNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | refund_amount = #{refundAmount,jdbcType=INTEGER}, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | create_time = #{createTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | refund_time = #{refundTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | refund_status = #{refundStatus,jdbcType=TINYINT}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_refund_item |
| | | set refund_id = #{refundId,jdbcType=BIGINT}, |
| | | order_number = #{orderNumber,jdbcType=VARCHAR}, |
| | | refund_number = #{refundNumber,jdbcType=VARCHAR}, |
| | | refund_amount = #{refundAmount,jdbcType=INTEGER}, |
| | | create_time = #{createTime,jdbcType=TIMESTAMP}, |
| | | refund_time = #{refundTime,jdbcType=TIMESTAMP}, |
| | | refund_status = #{refundStatus,jdbcType=TINYINT} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | |
| | | <!--根据订单号获取最后一个退单号--> |
| | | <select id="getLastRefundNumber" resultType="java.lang.String"> |
| | | SELECT |
| | | refund_number AS refundNumber |
| | | FROM se_vc_refund_item |
| | | <where> |
| | | <if test = "orderNumber != null"> |
| | | AND order_number = #{orderNumber} |
| | | </if> |
| | | </where> |
| | | ORDER BY refund_number DESC |
| | | LIMIT 0,1 |
| | | </select> |
| | | |
| | | <!--根据退款通知接口返回的退款单号反查退款ID,查询该退款ID下未退款记录数量--> |
| | | <select id="getNoRefundedCount" resultType="java.lang.Integer"> |
| | | SELECT |
| | | COUNT(*) AS recordCount |
| | | FROM se_vc_refund_item |
| | | WHERE refund_id = (SELECT refund_id FROM se_vc_refund_item WHERE refund_number = #{refundNumber}) AND refund_status = 1 |
| | | </select> |
| | | |
| | | <!--根据退款单号获取退款ID,退款通知后更新退款表所需--> |
| | | <select id="getRefundIdByRefundNumber" resultType="java.lang.Long"> |
| | | SELECT |
| | | refund_id AS refundId |
| | | FROM se_vc_refund_item |
| | | WHERE refund_number = #{refundNumber} |
| | | </select> |
| | | </mapper> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVcRefundMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVcRefund"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table se_vc_refund--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="vc_id" jdbcType="BIGINT" property="vcId" /> |
| | | <result column="client_id" jdbcType="BIGINT" property="clientId" /> |
| | | <result column="money" jdbcType="FLOAT" property="money" /> |
| | | <result column="refund_amount" jdbcType="FLOAT" property="refundAmount" /> |
| | | <result column="after_refund" jdbcType="FLOAT" property="afterRefund" /> |
| | | <result column="application_time" jdbcType="TIMESTAMP" property="applicationTime" /> |
| | | <result column="auditor" jdbcType="BIGINT" property="auditor" /> |
| | | <result column="audit_time" jdbcType="TIMESTAMP" property="auditTime" /> |
| | | <result column="remarks" jdbcType="VARCHAR" property="remarks" /> |
| | | <result column="refund_number" jdbcType="VARCHAR" property="refundNumber" /> |
| | | <result column="refund_time" jdbcType="TIMESTAMP" property="refundTime" /> |
| | | <result column="refund_status" jdbcType="TINYINT" property="refundStatus" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, vc_id, client_id, money, refund_amount, after_refund, application_time, auditor, |
| | | audit_time, remarks, refund_number, refund_time, refund_status |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from se_vc_refund |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from se_vc_refund |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_refund (id, vc_id, client_id, |
| | | money, refund_amount, after_refund, |
| | | application_time, auditor, audit_time, |
| | | remarks, refund_number, refund_time, |
| | | refund_status) |
| | | values (#{id,jdbcType=BIGINT}, #{vcId,jdbcType=BIGINT}, #{clientId,jdbcType=BIGINT}, |
| | | #{money,jdbcType=FLOAT}, #{refundAmount,jdbcType=FLOAT}, #{afterRefund,jdbcType=FLOAT}, |
| | | #{applicationTime,jdbcType=TIMESTAMP}, #{auditor,jdbcType=BIGINT}, #{auditTime,jdbcType=TIMESTAMP}, |
| | | #{remarks,jdbcType=VARCHAR}, #{refundNumber,jdbcType=VARCHAR}, #{refundTime,jdbcType=TIMESTAMP}, |
| | | #{refundStatus,jdbcType=TINYINT}) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund"> |
| | | <!--@mbg.generated--> |
| | | insert into se_vc_refund |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="vcId != null"> |
| | | vc_id, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | client_id, |
| | | </if> |
| | | <if test="money != null"> |
| | | money, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | refund_amount, |
| | | </if> |
| | | <if test="afterRefund != null"> |
| | | after_refund, |
| | | </if> |
| | | <if test="applicationTime != null"> |
| | | application_time, |
| | | </if> |
| | | <if test="auditor != null"> |
| | | auditor, |
| | | </if> |
| | | <if test="auditTime != null"> |
| | | audit_time, |
| | | </if> |
| | | <if test="remarks != null"> |
| | | remarks, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | refund_number, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | refund_time, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | refund_status, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="vcId != null"> |
| | | #{vcId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | #{refundAmount,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="afterRefund != null"> |
| | | #{afterRefund,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="applicationTime != null"> |
| | | #{applicationTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="auditor != null"> |
| | | #{auditor,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="auditTime != null"> |
| | | #{auditTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="remarks != null"> |
| | | #{remarks,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | #{refundNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | #{refundTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | #{refundStatus,jdbcType=TINYINT}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_refund |
| | | <set> |
| | | <if test="vcId != null"> |
| | | vc_id = #{vcId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | client_id = #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | money = #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="refundAmount != null"> |
| | | refund_amount = #{refundAmount,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="afterRefund != null"> |
| | | after_refund = #{afterRefund,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="applicationTime != null"> |
| | | application_time = #{applicationTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="auditor != null"> |
| | | auditor = #{auditor,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="auditTime != null"> |
| | | audit_time = #{auditTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="remarks != null"> |
| | | remarks = #{remarks,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundNumber != null"> |
| | | refund_number = #{refundNumber,jdbcType=VARCHAR}, |
| | | </if> |
| | | <if test="refundTime != null"> |
| | | refund_time = #{refundTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="refundStatus != null"> |
| | | refund_status = #{refundStatus,jdbcType=TINYINT}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVcRefund"> |
| | | <!--@mbg.generated--> |
| | | update se_vc_refund |
| | | set vc_id = #{vcId,jdbcType=BIGINT}, |
| | | client_id = #{clientId,jdbcType=BIGINT}, |
| | | money = #{money,jdbcType=FLOAT}, |
| | | refund_amount = #{refundAmount,jdbcType=FLOAT}, |
| | | after_refund = #{afterRefund,jdbcType=FLOAT}, |
| | | application_time = #{applicationTime,jdbcType=TIMESTAMP}, |
| | | auditor = #{auditor,jdbcType=BIGINT}, |
| | | audit_time = #{auditTime,jdbcType=TIMESTAMP}, |
| | | remarks = #{remarks,jdbcType=VARCHAR}, |
| | | refund_number = #{refundNumber,jdbcType=VARCHAR}, |
| | | refund_time = #{refundTime,jdbcType=TIMESTAMP}, |
| | | refund_status = #{refundStatus,jdbcType=TINYINT} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | |
| | | <!--根据订单号获取其各笔退款金额--> |
| | | <select id="getRefundAmount" resultType="java.lang.Integer"> |
| | | SELECT |
| | | refund_amount AS refundAmount |
| | | FROM se_vc_refund |
| | | <where> |
| | | AND refund_status = 3 |
| | | <if test = "orderNumber != null"> |
| | | AND refund_amount LIKE CONCAT(#{orderNumber},'%') |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | </mapper> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper"> |
| | | <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoSe.SeVirtualCard"> |
| | | <!--@mbg.generated--> |
| | | <!--@Table se_virtual_card--> |
| | | <id column="id" jdbcType="BIGINT" property="id" /> |
| | | <result column="client_id" jdbcType="BIGINT" property="clientId" /> |
| | | <result column="money" jdbcType="FLOAT" property="money" /> |
| | | <result column="last_operate" jdbcType="TINYINT" property="lastOperate" /> |
| | | <result column="last_operate_time" jdbcType="TIMESTAMP" property="lastOperateTime" /> |
| | | <result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> |
| | | </resultMap> |
| | | <sql id="Base_Column_List"> |
| | | <!--@mbg.generated--> |
| | | id, client_id, money, last_operate, last_operate_time, create_time |
| | | </sql> |
| | | <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
| | | <!--@mbg.generated--> |
| | | select |
| | | <include refid="Base_Column_List" /> |
| | | from se_virtual_card |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </select> |
| | | <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
| | | <!--@mbg.generated--> |
| | | delete from se_virtual_card |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </delete> |
| | | <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVirtualCard"> |
| | | <!--@mbg.generated--> |
| | | insert into se_virtual_card (id, client_id, money, |
| | | last_operate, last_operate_time, create_time |
| | | ) |
| | | values (#{id,jdbcType=BIGINT}, #{clientId,jdbcType=BIGINT}, #{money,jdbcType=FLOAT}, |
| | | #{lastOperate,jdbcType=TINYINT}, #{lastOperateTime,jdbcType=TIMESTAMP}, #{createTime,jdbcType=TIMESTAMP} |
| | | ) |
| | | </insert> |
| | | <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVirtualCard"> |
| | | <!--@mbg.generated--> |
| | | insert into se_virtual_card |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | id, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | client_id, |
| | | </if> |
| | | <if test="money != null"> |
| | | money, |
| | | </if> |
| | | <if test="lastOperate != null"> |
| | | last_operate, |
| | | </if> |
| | | <if test="lastOperateTime != null"> |
| | | last_operate_time, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | create_time, |
| | | </if> |
| | | </trim> |
| | | <trim prefix="values (" suffix=")" suffixOverrides=","> |
| | | <if test="id != null"> |
| | | #{id,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="clientId != null"> |
| | | #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="lastOperate != null"> |
| | | #{lastOperate,jdbcType=TINYINT}, |
| | | </if> |
| | | <if test="lastOperateTime != null"> |
| | | #{lastOperateTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | #{createTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVirtualCard"> |
| | | <!--@mbg.generated--> |
| | | update se_virtual_card |
| | | <set> |
| | | <if test="clientId != null"> |
| | | client_id = #{clientId,jdbcType=BIGINT}, |
| | | </if> |
| | | <if test="money != null"> |
| | | money = #{money,jdbcType=FLOAT}, |
| | | </if> |
| | | <if test="lastOperate != null"> |
| | | last_operate = #{lastOperate,jdbcType=TINYINT}, |
| | | </if> |
| | | <if test="lastOperateTime != null"> |
| | | last_operate_time = #{lastOperateTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | <if test="createTime != null"> |
| | | create_time = #{createTime,jdbcType=TIMESTAMP}, |
| | | </if> |
| | | </set> |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoSe.SeVirtualCard"> |
| | | <!--@mbg.generated--> |
| | | update se_virtual_card |
| | | set client_id = #{clientId,jdbcType=BIGINT}, |
| | | money = #{money,jdbcType=FLOAT}, |
| | | last_operate = #{lastOperate,jdbcType=TINYINT}, |
| | | last_operate_time = #{lastOperateTime,jdbcType=TIMESTAMP}, |
| | | create_time = #{createTime,jdbcType=TIMESTAMP} |
| | | where id = #{id,jdbcType=BIGINT} |
| | | </update> |
| | | |
| | | </mapper> |
| | |
| | | @Slf4j |
| | | @Tag(name = "控制器管理", description = "控制器操作") |
| | | @RestController |
| | | @RequestMapping(path="controller") |
| | | @RequestMapping(path = "controller") |
| | | @RequiredArgsConstructor |
| | | public class ControllerCtrl { |
| | | private final ControllerSv controllerSv; |
| | | |
| | | /** |
| | | * 根据指定条件获取控制器列表 |
| | | * |
| | | * @param vo 查询条件 |
| | | * @return 符合条件的控制器列表 |
| | | */ |
| | |
| | | }) |
| | | @GetMapping(path = "/getControllers") |
| | | @SsoAop() |
| | | public BaseResponse<QueryResultVo<List<VoController>>> getControllers(QueryVo vo){ |
| | | public BaseResponse<QueryResultVo<List<VoController>>> getControllers(QueryVo vo) { |
| | | try { |
| | | QueryResultVo<List<VoController>> res = controllerSv.getControllers(vo); |
| | | if(res.itemTotal != null && res.itemTotal > 0) { |
| | | if (res.itemTotal != null && res.itemTotal > 0) { |
| | | return BaseResponseUtils.buildSuccess(res); |
| | | }else { |
| | | } else { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.NO_RECORDS.getMessage()); |
| | | } |
| | | //return BaseResponseUtils.buildSuccess(res); |
| | | } catch (Exception e) { |
| | | log.error("获取开卡记录异常", e); |
| | | return BaseResponseUtils.buildException(e.getMessage()) ; |
| | | return BaseResponseUtils.buildException(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据控制器编号获取控制器列表 |
| | | * |
| | | * @param rtuAddr 控制器地址 |
| | | * @return 符合条件的控制器列表 |
| | | */ |
| | |
| | | }) |
| | | @GetMapping(path = "controller_list") |
| | | @SsoAop() |
| | | public BaseResponse<List<Map<String, Object>>> getControllersByCode(String rtuAddr){ |
| | | public BaseResponse<List<Map<String, Object>>> getControllersByCode(String rtuAddr) { |
| | | try { |
| | | List<Map<String, Object>> list = Optional.ofNullable(controllerSv.getControllersByAddr(rtuAddr)).orElse(new ArrayList<>()); |
| | | if(list.size() <= 0) { |
| | | if (list.size() <= 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.NO_RECORDS.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(list); |
| | | } catch (Exception e) { |
| | | log.error("查询控制器异常", e); |
| | | return BaseResponseUtils.buildException(e.getMessage()) ; |
| | | return BaseResponseUtils.buildException(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 添加控制器 |
| | | * @param po 控制器实体对象 |
| | | * |
| | | * @param po 控制器实体对象 |
| | | * @param bindingResult |
| | | * @return 添加是否成功 |
| | | */ |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | //public BaseResponse<Boolean> add(@RequestBody @Valid DtoController po, BindingResult bindingResult){ |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid PrController po, BindingResult bindingResult){ |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid PrController po, BindingResult bindingResult) { |
| | | if (bindingResult != null && bindingResult.hasErrors()) { |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | |
| | |
| | | |
| | | Date operateTime = new Date(); |
| | | po.setOperateDt(operateTime); |
| | | po.setDeleted((byte)0); |
| | | po.setDeleted((byte) 0); |
| | | po.setFindDt(operateTime); |
| | | if (po.getAddWays() == null) { |
| | | po.setAddWays((byte) 1); |
| | | } |
| | | Integer rec = Optional.ofNullable(controllerSv.addController(po)).orElse(0); |
| | | if(rec == 0) { |
| | | if (rec == 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.CONTROLLER_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | return BaseResponseUtils.buildSuccess(true); |
| | | } |
| | | |
| | | /** |
| | | * 根据控制器编号删除控制器 |
| | | * |
| | | * @param map |
| | | * @return |
| | | */ |
| | |
| | | }) |
| | | @PostMapping(path = "delete") |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> delete(@RequestBody Map map){ |
| | | if(map == null || map.size() <=0) { |
| | | public BaseResponse<Boolean> delete(@RequestBody Map map) { |
| | | if (map == null || map.size() <= 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.PLEASE_INPUT_CONTROLLER_ID.getMessage()); |
| | | } |
| | | |
| | | Long controllerId = Long.parseLong(map.get("controllerId").toString()); |
| | | Integer recordCount = Optional.ofNullable(controllerSv.deleteControllerById(controllerId)).orElse(0); |
| | | if(recordCount == 0) { |
| | | if (recordCount == 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.DELETE_CONTROLLER_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | return BaseResponseUtils.buildSuccess(true); |
| | | } |
| | | |
| | | /** |
| | | * 获取未绑控制器的取水口列表 |
| | | * |
| | | * @return |
| | | */ |
| | | @Operation(summary = "获得未绑控制器的取水口记录", description = "返回未绑控制器的取水口数据") |
| | |
| | | }) |
| | | @GetMapping(path = "nobinding_intakes") |
| | | @SsoAop() |
| | | public BaseResponse<JSONArray> getNoBindingIntakes(){ |
| | | public BaseResponse<JSONArray> getNoBindingIntakes() { |
| | | try { |
| | | JSONArray array = controllerSv.getNoBindingIntakes(); |
| | | if(array.size() <= 0) { |
| | | if (array.size() <= 0) { |
| | | return BaseResponseUtils.buildFail(ProjectResultCode.NO_BINDING_INTAKE.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(array); |
| | | } catch (Exception e) { |
| | | log.error("查询控制器异常", e); |
| | | return BaseResponseUtils.buildException(e.getMessage()) ; |
| | | return BaseResponseUtils.buildException(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导出控制器列表 |
| | | * |
| | | * @param response |
| | | * @param vo |
| | | */ |
| | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.dy.common.webUtil.QueryResultVo; |
| | | import com.dy.pipIrrGlobal.daoPr.PrControllerMapper; |
| | | import com.dy.pipIrrGlobal.daoPr.PrIntakeControllerMapper; |
| | | import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrController; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrIntakeController; |
| | | import com.dy.pipIrrGlobal.voPr.VoController; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.dubbo.common.utils.PojoUtils; |
| | |
| | | @Autowired |
| | | private PrIntakeMapper prIntakeMapper; |
| | | |
| | | @Autowired |
| | | private PrIntakeControllerMapper prIntakeControllerMapper; |
| | | |
| | | /** |
| | | * 根据指定获取控制器记录 |
| | | * @param queryVo |
| | |
| | | * @return |
| | | */ |
| | | public Integer addController(PrController po) { |
| | | return prControllerMapper.insert(po); |
| | | prControllerMapper.insert(po); |
| | | PrIntakeController addPrIntakeController = new PrIntakeController(); |
| | | addPrIntakeController.setIntakeid(po.getIntakeId()); |
| | | addPrIntakeController.setControllerid(po.getId()); |
| | | addPrIntakeController.setOperatetype((byte) 1); |
| | | addPrIntakeController.setOperator(po.getOperator()); |
| | | addPrIntakeController.setOperatedt(po.getOperateDt()); |
| | | addPrIntakeController.setRemarks("绑定"); |
| | | prIntakeControllerMapper.insert(addPrIntakeController); |
| | | return 1; |
| | | } |
| | | |
| | | /** |
| | |
| | | @Schema(description = "控制器编号") |
| | | private String controllerCode; |
| | | |
| | | @Schema(description = "控制器地址") |
| | | private String rtuAddr; |
| | | |
| | | @Schema(description = "在线状态") |
| | | public Integer onlineState; |
| | | |
| | |
| | | <name>pipIrr-web-sell</name> |
| | | <description>web营销信息系统</description> |
| | | |
| | | <dependencies> |
| | | <!--OkHttp--> |
| | | <dependency> |
| | | <groupId>com.squareup.okhttp3</groupId> |
| | | <artifactId>okhttp</artifactId> |
| | | <version>4.9.2</version> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <!-- 生成不包含依赖jar的可执行jar包 |
| | |
| | | @PostMapping(path = "add", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid DtoClient po, BindingResult bindingResult){ |
| | | public BaseResponse<Boolean> add(@RequestBody @Valid DtoClient po, BindingResult bindingResult) { |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | |
| | | return BaseResponseUtils.buildException(e.getMessage()) ; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获得一页已挂失,未补卡的水卡记录 |
| | | * @param vo |
| | | * @return |
| | | */ |
| | | @Operation(summary = "获得一页已挂失,未补卡的水卡记录", description = "返回一页已挂失,未补卡的水卡数据") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "返回一页农户数据(BaseResponse.content:QueryResultVo[{}])", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = BaClient.class))} |
| | | ) |
| | | }) |
| | | @GetMapping(path = "getUnreplaced") |
| | | @SsoAop() |
| | | public BaseResponse<QueryResultVo<List<VoCards>>> getUnreplaced(QoCards vo){ |
| | | try { |
| | | QueryResultVo<List<VoCards>> res = clientCardSv.getUnreplaced(vo); |
| | | if(res.itemTotal != null && res.itemTotal > 0) { |
| | | return BaseResponseUtils.buildSuccess(res); |
| | | }else { |
| | | return BaseResponseUtils.buildFail(SellResultCode.THE_CARD_NOT_EXIST.getMessage()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("查询农户异常", e); |
| | | return BaseResponseUtils.buildException(e.getMessage()) ; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | return rsVo ; |
| | | } |
| | | |
| | | /** |
| | | * 获取已挂失,未补卡的记录,应用程序使用 |
| | | * @param queryVo |
| | | * @return |
| | | */ |
| | | public QueryResultVo<List<VoCards>> getUnreplaced(QoCards queryVo){ |
| | | Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo) ; |
| | | Long itemTotal = seClientCardMapper.getUnreplacedRecordCount(); |
| | | |
| | | QueryResultVo<List<VoCards>> rsVo = new QueryResultVo<>() ; |
| | | rsVo.pageSize = queryVo.pageSize ; |
| | | rsVo.pageCurr = queryVo.pageCurr ; |
| | | |
| | | rsVo.calculateAndSet(itemTotal, params); |
| | | rsVo.obj = seClientCardMapper.getUnreplaced(params); |
| | | |
| | | return rsVo ; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.config; |
| | | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.http.converter.HttpMessageConverter; |
| | | import org.springframework.http.converter.StringHttpMessageConverter; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 11:43 |
| | | * @LastEditTime 2024-03-06 11:43 |
| | | * @Description |
| | | */ |
| | | |
| | | @Configuration |
| | | public class RestTemplateConfig { |
| | | @Autowired |
| | | private RestTemplateWechatCertConfig restTemplateWechatCertConfig; |
| | | |
| | | @Bean() |
| | | public RestTemplate restTemplate() throws Exception { |
| | | RestTemplate restTemplate = new RestTemplate(restTemplateWechatCertConfig.wechatHttpRequestFactory()); |
| | | // 添加拦截器 |
| | | //List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(); |
| | | //RestTemplateWechatCertConfig.MyRequestInterceptor myRequestInterceptor = new RestTemplateWechatCertConfig.MyRequestInterceptor(); |
| | | //interceptors.add(myRequestInterceptor); |
| | | //restTemplate.setInterceptors(interceptors); |
| | | |
| | | // 中文乱码,主要是 StringHttpMessageConverter的默认编码为ISO导致的 |
| | | List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters(); |
| | | for (HttpMessageConverter converter : list) { |
| | | if (converter instanceof StringHttpMessageConverter) { |
| | | ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | return restTemplate; |
| | | } |
| | | } |
| File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-webchat/src/main/java/com/dy/pipirrWebChat/config/RestTemplateWechatCertConfig.java |
| | |
| | | package com.dy.pipirrWebChat.config; |
| | | package com.dy.pipIrrSell.config; |
| | | |
| | | import com.dy.pipirrWebChat.payment.PayInfo; |
| | | import com.dy.pipIrrSell.wechatpay.PayInfo; |
| | | import okhttp3.OkHttpClient; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-02-23 19:18 |
| | | * @LastEditTime 2024-02-23 19:18 |
| | | * @date 2024-03-06 11:44 |
| | | * @LastEditTime 2024-03-06 11:44 |
| | | * @Description |
| | | */ |
| | | |
| | |
| | | AUDITS_ADD_FAIL(80001, "总账审核记录添加失败"), |
| | | |
| | | /** |
| | | * 电子钱包 |
| | | * 虚拟卡 |
| | | */ |
| | | |
| | | VERIFY_FAIL(10001, "验签失败"), |
| | | |
| | | TOTAL_REFUND_EXCEED_TRADE(10001, "退款总额超过订单金额"), |
| | | ACCEPTED(10001, "退款申请已受理"), |
| | | PROCESSING(10001, "退款处理中"), |
| | | ABNORMAL(10001, "退款异常"), |
| | | RECHARGE_ADD_FAIL(10001, "充值记录添加失败"), |
| | | |
| | | CLIENT_ID_CANNOT_BE_NULL(90001, "农户编号不能为空"), |
| | | WALLET_OPEN_ACCOUNT_FAIL(90002, "电子钱包账户注册失败"), |
| | | WALLET_ACCOUNT_EXIST(90003, "该农户已注册电子钱包"), |
| | | NO_ACCOUNT(90004, "您尚未注册电子钱包账户"), |
| | | WALLET_OPEN_ACCOUNT_FAIL(90002, "虚拟卡账户注册失败"), |
| | | //WALLET_ACCOUNT_EXIST(90003, "该农户已注册电子钱包"), |
| | | NO_ACCOUNT(90004, "您指定的虚拟卡未注册"), |
| | | |
| | | UPDATE_ACCOUNT_FAIL(90005, "充值失败,电子钱包账户更新失败"), |
| | | RECHARGE_FAIL(90006, "充值失败"), |
| | | RECHARGE_NOT_EXIST(90006, "充值记录不存在"), |
| | | VIRTUAL_CARD_NOT_EXIST(90006, "虚拟卡账户不存在"), |
| | | |
| | | BALANCE_IS_INSUFFICIENT(90007, "消费失败,余额不足"), |
| | | CONSUME_FAIL(90008, "消费失败"), |
| | | REFUND_AMOUNT_CANNOT_GREATER_THAN_MONEY(90009, "申请退款失败,退款金额不能大于余额"), |
| | | APPLICATION_REFUND_FAIL(900010, "申请退款失败"), |
| | | NOT_SUFFICIENT_FUNDS(900010, "退款失败,余额不足"), |
| | | NO_TO_AUDIT_REFUND(900011, "该电子钱包没有待审核的退款申请"), |
| | | AUDIT_REFUND_FAIL(900012, "审核退款申请失败"), |
| | | No_WALLER_RECHARGES(900013, "没有符合条件的充值数据"), |
| New file |
| | |
| | | package com.dy.pipIrrSell.util; |
| | | |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.NoSuchPaddingException; |
| | | import javax.crypto.spec.GCMParameterSpec; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.io.IOException; |
| | | import java.security.GeneralSecurityException; |
| | | import java.security.InvalidAlgorithmParameterException; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.util.Base64; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 11:46 |
| | | * @LastEditTime 2024-03-06 11:46 |
| | | * @Description |
| | | */ |
| | | |
| | | public class AesUtil { |
| | | static final int KEY_LENGTH_BYTE = 32; |
| | | static final int TAG_LENGTH_BIT = 128; |
| | | |
| | | /** |
| | | * 解密 |
| | | * @param apiV3Key apiV3密钥 |
| | | * @param associatedData 附加数据 |
| | | * @param nonce 随机串 |
| | | * @param ciphertext 数据密文 |
| | | * @return 解密后字符串 |
| | | * @throws GeneralSecurityException |
| | | * @throws IOException |
| | | */ |
| | | public static String decryptToString(byte[] apiV3Key, byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException { |
| | | try { |
| | | Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); |
| | | SecretKeySpec key = new SecretKeySpec(apiV3Key, "AES"); |
| | | GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce); |
| | | |
| | | cipher.init(Cipher.DECRYPT_MODE, key, spec); |
| | | cipher.updateAAD(associatedData); |
| | | |
| | | return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8"); |
| | | } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { |
| | | throw new IllegalStateException(e); |
| | | } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { |
| | | throw new IllegalArgumentException(e); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.util; |
| | | |
| | | import javax.crypto.Mac; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 11:47 |
| | | * @LastEditTime 2024-03-06 11:47 |
| | | * @Description |
| | | */ |
| | | public class HmacSha256 { |
| | | public static String getSignature(String secretKey, String data) throws NoSuchAlgorithmException, InvalidKeyException { |
| | | // 创建密钥对象 |
| | | byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "HmacSHA256"); |
| | | |
| | | // 创建Mac对象并初始化 |
| | | Mac mac = Mac.getInstance("HmacSHA256"); |
| | | mac.init(secretKeySpec); |
| | | |
| | | // 将待加密的数据转换为字节数组 |
| | | byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); |
| | | |
| | | // 使用密钥对数据进行加密 |
| | | byte[] encryptedBytes = mac.doFinal(dataBytes); |
| | | |
| | | // 将加密后的结果转换为十六进制字符串 |
| | | StringBuilder hexString = new StringBuilder(); |
| | | for (byte b : encryptedBytes) { |
| | | String hex = Integer.toHexString(0xff & b); |
| | | if (hex.length() == 1) { |
| | | hexString.append('0'); |
| | | } |
| | | hexString.append(hex); |
| | | } |
| | | String hmacSha256 = hexString.toString(); |
| | | return hmacSha256; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.util; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.BaseResponseUtils; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; |
| | | import com.dy.pipIrrGlobal.voSe.VoOrders; |
| | | import com.dy.pipIrrSell.result.SellResultCode; |
| | | import com.dy.pipIrrSell.virtualCard.VirtualCardSv; |
| | | import com.dy.pipIrrSell.wechatpay.PayInfo; |
| | | import com.dy.pipIrrSell.wechatpay.dto.Refund; |
| | | import com.dy.pipIrrSell.wechatpay.dto.RefundRequest; |
| | | import com.dy.pipIrrSell.wechatpay.dto.RefundResponse; |
| | | import com.dy.pipIrrSell.wechatpay.dto.ToRefund; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.crypto.NoSuchPaddingException; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Paths; |
| | | import java.security.*; |
| | | import java.security.cert.Certificate; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.CertificateFactory; |
| | | import java.security.spec.InvalidKeySpecException; |
| | | import java.security.spec.PKCS8EncodedKeySpec; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 11:47 |
| | | * @LastEditTime 2024-03-06 11:47 |
| | | * @Description |
| | | */ |
| | | @Component |
| | | @RequiredArgsConstructor |
| | | public class PayHelper { |
| | | private final VirtualCardSv virtualCardSv; |
| | | private final RestTemplateUtil restTemplateUtil; |
| | | |
| | | private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
| | | |
| | | private String checkSessionUrl = PayInfo.checkSessionUrl; |
| | | private String tokenUrl = PayInfo.tokenUrl; |
| | | private String resetUserSessionKeyUrl = PayInfo.resetUserSessionKeyUrl; |
| | | private String notifyUrl = PayInfo.notifyUrl; |
| | | private String schema = PayInfo.schema; |
| | | private String privateCertFileName = PayInfo.privateCertFileName; |
| | | private String refundUrl = PayInfo.refundUrl; |
| | | |
| | | // 平台证书公钥 |
| | | public Map<String, Certificate> CERTIFICATE_MAP = new HashMap(); |
| | | |
| | | /** |
| | | * 获取32位随机字符串 |
| | | * @return 随机串 |
| | | */ |
| | | public String generateRandomString() { |
| | | Random random = new Random(); |
| | | StringBuilder sb = new StringBuilder(32); |
| | | for (int i = 0; i < 32; i++) { |
| | | int index = random.nextInt(CHARACTERS.length()); |
| | | sb.append(CHARACTERS.charAt(index)); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 获取商户证书私钥对象 |
| | | * @param filename 私钥文件路径 |
| | | * @return 私钥对象 |
| | | * @throws IOException |
| | | */ |
| | | public PrivateKey getPrivateKey(String filename) throws IOException { |
| | | String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8"); |
| | | try { |
| | | String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") |
| | | .replace("-----END PRIVATE KEY-----", "") |
| | | .replaceAll("\\s+", ""); |
| | | KeyFactory kf = KeyFactory.getInstance("RSA"); |
| | | return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | throw new RuntimeException("当前Java环境不支持RSA", e); |
| | | } catch (InvalidKeySpecException e) { |
| | | throw new RuntimeException("无效的密钥格式"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检验登录态 |
| | | * @param appid 小程序 appId |
| | | * @param secret 小程序 appSecret |
| | | * @param openid 用户唯一标识符 |
| | | * @param sessionKey 会话密钥 |
| | | * @return |
| | | * @throws IOException |
| | | */ |
| | | public JSONObject checkSessionKey(String appid, String secret, String openid, String sessionKey) throws IOException, NoSuchAlgorithmException, InvalidKeyException { |
| | | String accessToken = ""; |
| | | Integer expiresIn = 0; |
| | | String signature = HmacSha256.getSignature(sessionKey, ""); |
| | | String sigMethod = "hmac_sha256"; |
| | | |
| | | JSONObject job_token = getAccessToken(appid, secret); |
| | | if(job_token != null) { |
| | | accessToken = job_token.getString("access_token"); |
| | | expiresIn = job_token.getInteger("expires_in"); |
| | | } |
| | | |
| | | Map<String, Object> queryParams = new HashMap<>(); |
| | | queryParams.put("access_token", accessToken); |
| | | queryParams.put("openid", openid); |
| | | queryParams.put("signature", signature); |
| | | queryParams.put("sig_method", sigMethod); |
| | | Map<String, String> headerParams = new HashMap<>(); |
| | | JSONObject result = restTemplateUtil.get(checkSessionUrl, queryParams, headerParams); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 重置登录态 |
| | | * @param appid 小程序 appId |
| | | * @param secret 小程序 appSecret |
| | | * @param openid 用户唯一标识符 |
| | | * @param sessionKey 会话密钥 |
| | | * @return |
| | | * @throws NoSuchAlgorithmException |
| | | * @throws InvalidKeyException |
| | | * @throws IOException |
| | | */ |
| | | public JSONObject resetUserSessionKey(String appid, String secret, String openid, String sessionKey) throws NoSuchAlgorithmException, InvalidKeyException, IOException { |
| | | String accessToken = ""; |
| | | Integer expiresIn = 0; |
| | | String signature = HmacSha256.getSignature(sessionKey, ""); |
| | | String sigMethod = "hmac_sha256"; |
| | | |
| | | JSONObject job_token = getAccessToken(appid, secret); |
| | | if(job_token != null) { |
| | | accessToken = job_token.getString("access_token"); |
| | | expiresIn = job_token.getInteger("expires_in"); |
| | | } |
| | | |
| | | Map<String, Object> queryParams = new HashMap<>(); |
| | | queryParams.put("access_token", accessToken); |
| | | queryParams.put("openid", openid); |
| | | queryParams.put("signature", signature); |
| | | queryParams.put("sig_method", sigMethod); |
| | | Map<String, String> headerParams = new HashMap<>(); |
| | | JSONObject result = restTemplateUtil.get(resetUserSessionKeyUrl, queryParams, headerParams); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 获取接口调用凭据 |
| | | * @param appid 小程序 appId |
| | | * @param secret 小程序 appSecret |
| | | * @return 凭据及凭据有效时间 |
| | | * @throws IOException |
| | | */ |
| | | public JSONObject getAccessToken(String appid, String secret) throws IOException { |
| | | Map<String, Object> queryParams = new HashMap<>(); |
| | | queryParams.put("grant_type", "client_credential"); |
| | | queryParams.put("appid", appid); |
| | | queryParams.put("secret", secret); |
| | | Map<String, String> headerParams = new HashMap<>(); |
| | | JSONObject job_result = restTemplateUtil.get(tokenUrl, queryParams, headerParams); |
| | | return job_result; |
| | | } |
| | | |
| | | /** |
| | | * 构造签名串_下单 |
| | | * @param method HTTP请求方法 |
| | | * @param url URL |
| | | * @param timestamp 时间戳 |
| | | * @param nonceStr 随机串 |
| | | * @param body 报文主题 |
| | | * @return 签名串 |
| | | */ |
| | | public String buildMessage_order(String method, String url, long timestamp, String nonceStr, String body) { |
| | | return method + "\n" |
| | | + url + "\n" |
| | | + timestamp + "\n" |
| | | + nonceStr + "\n" |
| | | + body + "\n"; |
| | | } |
| | | |
| | | /** |
| | | * 构造签名串_再次下单 |
| | | * @param appid 小程序唯一标识 |
| | | * @param timestamp 时间戳 |
| | | * @param nonceStr 随机串 |
| | | * @param pkg package |
| | | * @return 签名串 |
| | | */ |
| | | public String buildMessage_signAgain(String appid, String timestamp, String nonceStr, String pkg) { |
| | | return appid + "\n" |
| | | + timestamp + "\n" |
| | | + nonceStr + "\n" |
| | | + pkg + "\n"; |
| | | } |
| | | |
| | | /** |
| | | * 签名 |
| | | * @param message 被签名信息 |
| | | * @param certFileName 私钥证书文件路径 |
| | | * @return signature签名值,签名信息中的一项,参与生成签名信息 |
| | | * @throws NoSuchAlgorithmException |
| | | * @throws InvalidKeyException |
| | | * @throws SignatureException |
| | | * @throws IOException |
| | | */ |
| | | public String sign(byte[] message, String certFileName) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException { |
| | | Signature sign = Signature.getInstance("SHA256withRSA"); |
| | | sign.initSign(getPrivateKey(certFileName)); |
| | | sign.update(message); |
| | | return Base64.getEncoder().encodeToString(sign.sign()); |
| | | } |
| | | |
| | | /** |
| | | * 获取签名信息 |
| | | * @param method |
| | | * @param url |
| | | * @param body |
| | | * @return 签名信息,HTTP头中的签名信息 |
| | | * HTTP头:Authorization: 认证类型 签名信息 |
| | | * 认证类型,WECHATPAY2-SHA256-RSA2048 |
| | | */ |
| | | public String getToken(String method, String url, String body, String nonceStr, Long timestamp, String certFileName) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException, NoSuchPaddingException { |
| | | String message = buildMessage_order(method, url, timestamp, nonceStr, body); |
| | | String signature = sign(message.getBytes("utf-8"), certFileName); |
| | | |
| | | return "mchid=\"" + PayInfo.mchid + "\"," |
| | | + "nonce_str=\"" + nonceStr + "\"," |
| | | + "timestamp=\"" + timestamp + "\"," |
| | | + "serial_no=\"" + PayInfo.serial_no + "\"," |
| | | + "signature=\"" + signature + "\""; |
| | | } |
| | | |
| | | /** |
| | | * 构造验造签名串 |
| | | * @param wechatpayTimestamp 请求头中返回的时间戳 |
| | | * @param wechatpayNonce 请求头中返回的随机串 |
| | | * @param boey 请求返回的body |
| | | * @return signatureStr构造的验签名串 |
| | | */ |
| | | public String responseSign(String wechatpayTimestamp, String wechatpayNonce, String boey) { |
| | | String signatureStr = wechatpayTimestamp + "\n" |
| | | + wechatpayNonce + "\n" |
| | | + boey + "\n"; |
| | | return signatureStr; |
| | | } |
| | | |
| | | /** |
| | | * 重新下载证书 |
| | | */ |
| | | public void refreshCertificate() throws GeneralSecurityException, IOException { |
| | | String method = "GET"; |
| | | String httpUrl = "/v3/certificates"; |
| | | String nonceStr = generateRandomString(); |
| | | Long timestamp = System.currentTimeMillis() / 1000; |
| | | |
| | | String header = PayInfo.schema + " " + getToken(method, httpUrl, "", nonceStr, timestamp, PayInfo.privateCertFileName); |
| | | |
| | | Map<String, String> headers = new HashMap<>(); |
| | | headers.put("Authorization", header); |
| | | headers.put("Accept", "application/json"); |
| | | |
| | | JSONObject job_result = restTemplateUtil.getHeaders(PayInfo.certificates,null, headers); |
| | | JSONObject job_headers = job_result.getJSONObject("headers"); |
| | | |
| | | String wechatpayNonce = job_headers.getJSONArray("Wechatpay-Nonce").getString(0); |
| | | String wechatpaySerial = job_headers.getJSONArray("Wechatpay-Serial").getString(0); |
| | | String signature_h = job_headers.getJSONArray("Wechatpay-Signature").getString(0); |
| | | String signatureType_h = job_headers.getJSONArray("Wechatpay-Signature-Type").getString(0); |
| | | String wechatpayTimestamp = job_headers.getJSONArray("Wechatpay-Timestamp").getString(0); |
| | | |
| | | JSONObject job_body = job_result.getJSONObject("body"); |
| | | if(job_body != null) { |
| | | JSONArray array = job_body.getJSONArray("data"); |
| | | if(array != null && array.size() > 0) { |
| | | for(int i = 0; i < array.size(); i++) { |
| | | JSONObject job_data = array.getJSONObject(i); |
| | | String certificateSerial = job_data.getString("serial_no"); |
| | | String effective_time = job_data.getString("effective_time"); |
| | | String expire_time = job_data.getString("expire_time"); |
| | | JSONObject job_certificate = job_data.getJSONObject("encrypt_certificate"); |
| | | String algorithm = job_certificate.getString("algorithm"); |
| | | String nonce = job_certificate.getString("nonce"); |
| | | String associated_data = job_certificate.getString("associated_data"); |
| | | String ciphertext = job_certificate.getString("ciphertext"); |
| | | |
| | | //对证书密文进行解密得到平台证书公钥 |
| | | String publicKey = AesUtil.decryptToString(PayInfo.key.getBytes("utf-8"), associated_data.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext); |
| | | |
| | | // 将平台公钥字符串转成Certificate对象 |
| | | final CertificateFactory cf = CertificateFactory.getInstance("X509"); |
| | | ByteArrayInputStream inputStream = new ByteArrayInputStream(publicKey.getBytes(StandardCharsets.UTF_8)); |
| | | Certificate certificate = null; |
| | | try { |
| | | certificate = cf.generateCertificate(inputStream); |
| | | } catch (CertificateException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | // 响应头证书序号与响应体证书序列号一致,且时间差小于5分钟时才将证书存储map |
| | | Long timeDiff = (System.currentTimeMillis() / 1000 - Long.parseLong(wechatpayTimestamp))/60; |
| | | if(wechatpaySerial.equals(certificateSerial) && timeDiff <= 5) { |
| | | // 证书放入MAP |
| | | CERTIFICATE_MAP.put(certificateSerial, certificate); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 使用微信平台证书进行响应验签 |
| | | * @param wechatpaySerial 来自响应头的微信平台证书序列号 |
| | | * @param signatureStr 构造的验签名串 |
| | | * @param wechatpaySignature 来自响应头的微信平台签名 |
| | | * @return |
| | | * @throws NoSuchAlgorithmException |
| | | * @throws InvalidKeyException |
| | | * @throws SignatureException |
| | | */ |
| | | public Boolean responseSignVerify(String wechatpaySerial, String signatureStr, String wechatpaySignature) throws GeneralSecurityException, IOException { |
| | | if(CERTIFICATE_MAP.isEmpty() || !CERTIFICATE_MAP.containsKey(wechatpaySerial)) { |
| | | CERTIFICATE_MAP.clear(); |
| | | refreshCertificate(); |
| | | } |
| | | Certificate certificate = (Certificate)CERTIFICATE_MAP.get(wechatpaySerial); |
| | | if(certificate == null) { |
| | | return false; |
| | | } |
| | | |
| | | // 获取公钥 |
| | | PublicKey publicKey = certificate.getPublicKey(); |
| | | |
| | | // 初始化SHA256withRSA前面器 |
| | | Signature signature = Signature.getInstance("SHA256withRSA"); |
| | | // 用微信平台公钥对前面器进行初始化 |
| | | signature.initVerify(certificate); |
| | | |
| | | // 将构造的验签名串更新到签名器中 |
| | | signature.update(signatureStr.getBytes(StandardCharsets.UTF_8)); |
| | | |
| | | // 请求头中微信服务器返回的签名用Base64解码,使用签名器进行验证 |
| | | boolean valid = signature.verify(Base64.getDecoder().decode(wechatpaySignature)); |
| | | return valid; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取待退款对象列表 |
| | | * 待退款对象包含订单号和可退款金额 |
| | | * 订单对象包含订单号、充值金额、充值完成时间 |
| | | * 1. 根据虚拟卡号到虚拟卡表中取出该卡余额 |
| | | * 2. 根据虚拟卡号到充值表取出订单对象列表 |
| | | * @param virtualId |
| | | * @param refundAmount |
| | | * @return |
| | | */ |
| | | public List<ToRefund> getToRefunds(Long virtualId, Integer refundAmount) { |
| | | ToRefund toRefund = new ToRefund(); |
| | | List<ToRefund> list = new ArrayList<>(); |
| | | Double money = 0d; |
| | | |
| | | // 根据虚拟卡号获取当前虚拟卡余额 |
| | | SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); |
| | | if(seVirtualCard != null) { |
| | | money = seVirtualCard.getMoney(); |
| | | } |
| | | |
| | | // 要退金额大于该卡余额,返回空列表 |
| | | if(refundAmount > money) { |
| | | return list; |
| | | } |
| | | |
| | | // 根据虚拟卡号获取订单列表(仅限充值成功的) |
| | | List<VoOrders> list_Orders = virtualCardSv.selectOrders(virtualId); |
| | | // 遍历订单列表,获取 |
| | | if(list_Orders != null && list_Orders.size() > 0) { |
| | | JSONArray array_Orders = (JSONArray) JSON.toJSON(list_Orders); |
| | | for(int i = 0; i < array_Orders.size(); i++) { |
| | | JSONObject job_order = array_Orders.getJSONObject(i); |
| | | String orderNumber = job_order.getString("orderNumber"); |
| | | Integer rechargeAmount = job_order.getInteger("rechargeAmount"); |
| | | Date rechargeTime = job_order.getDate("rechargeTime"); |
| | | |
| | | // 计算充值至今时间差(分钟) |
| | | Long timestamp_Recharge = rechargeTime.getTime() / 1000; |
| | | Long timestamp_Current = System.currentTimeMillis() / 1000; |
| | | Long timeDiff_Minute = (timestamp_Current - timestamp_Recharge)/60; |
| | | |
| | | // 获取该订单已退款笔数 |
| | | Integer refundCount = 0; |
| | | List<Integer> list_RefundAmount = virtualCardSv.selectRefundAmount(orderNumber); |
| | | if(list_RefundAmount != null && list_RefundAmount.size() > 0) { |
| | | refundCount = list_RefundAmount.size(); |
| | | } |
| | | |
| | | // 充值至今未超过一年且该订单退款总次数未超过50次 |
| | | if(timeDiff_Minute/(365*24*60) >= 1 && (refundCount + 1) > 50) |
| | | return list; |
| | | |
| | | /** |
| | | * 1. 如果要退金额小于当前订单的充值金额,要退金额即为应退金额并返回 |
| | | * 2. 如果要推金额大于当前订单充值金额,当前订单充值金额即为应退金额 |
| | | * a. 生成应退款对象 |
| | | * b. 计算新的余额 |
| | | * c. 金蒜新的要退款金额 |
| | | * d. 如果要退金额大于0,遍历下一个订单 |
| | | */ |
| | | if(refundAmount <= rechargeAmount) { |
| | | toRefund = new ToRefund(); |
| | | toRefund.setOrderNumber(orderNumber); |
| | | toRefund.setRefundAmount(refundAmount); |
| | | list.add(toRefund); |
| | | // 计算新的余额和新的要退金额 |
| | | money = money - refundAmount; |
| | | refundAmount = refundAmount - refundAmount; |
| | | return list; |
| | | }else { |
| | | toRefund = new ToRefund(); |
| | | toRefund.setOrderNumber(orderNumber); |
| | | toRefund.setRefundAmount(rechargeAmount); |
| | | list.add(toRefund); |
| | | // 计算新的余额和新的要退金额 |
| | | money = money - rechargeAmount; |
| | | refundAmount = refundAmount - rechargeAmount; |
| | | if(refundAmount > 0) { |
| | | continue; |
| | | }else { |
| | | return list; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * 退款申请,调用微信支付退款申请接口 |
| | | * @param po 退款请求对象,包含订单号、退款单号、退款金额 |
| | | * @return |
| | | * @throws NoSuchPaddingException |
| | | * @throws NoSuchAlgorithmException |
| | | * @throws InvalidKeySpecException |
| | | * @throws IOException |
| | | * @throws SignatureException |
| | | * @throws InvalidKeyException |
| | | */ |
| | | public BaseResponse<Boolean> refunds(Refund po) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException { |
| | | String tradeNo = po.getTradeNo(); |
| | | String refundNo = po.getRefundNo(); |
| | | Integer refund = po.getRefund(); |
| | | |
| | | // 生成body |
| | | Integer total = virtualCardSv.getRechargeAmountByOrderNumber(tradeNo); |
| | | RefundRequest.Amount amount = new RefundRequest.Amount(); |
| | | amount.setRefund(refund); |
| | | amount.setTotal(total); |
| | | amount.setCurrency("CNY"); |
| | | |
| | | RefundRequest refundRequest = new RefundRequest(); |
| | | refundRequest.setOut_trade_no(tradeNo); |
| | | refundRequest.setOut_refund_no(refundNo); |
| | | refundRequest.setNotify_url(notifyUrl); |
| | | refundRequest.setAmount(amount); |
| | | |
| | | // 生成header |
| | | String nonceStr = generateRandomString(); |
| | | Long timestamp = System.currentTimeMillis() / 1000; |
| | | |
| | | String method = "POST"; |
| | | String httpUrl = "/v3/refund/domestic/refunds"; |
| | | |
| | | String body = JSONObject.toJSONString(refundRequest); |
| | | String header = schema + " " + getToken(method, httpUrl, body, nonceStr, timestamp, privateCertFileName); |
| | | |
| | | Map<String, String> headers = new HashMap<>(); |
| | | headers.put("Authorization", header); |
| | | headers.put("Accept", "application/json"); |
| | | headers.put("Content-Type", "application/json"); |
| | | |
| | | JSONObject job_refundResponse = restTemplateUtil.post(PayInfo.refundUrl, body, headers); |
| | | RefundResponse refundResponse = JSON.parseObject(job_refundResponse.toJSONString(), RefundResponse.class); |
| | | |
| | | String status = refundResponse.getStatus(); |
| | | if(status != null && status.equals("SUCCESS")) { |
| | | // 退款申请已受理 |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } else if(status != null && status.equals("PROCESSING")) { |
| | | // 退款处理中 |
| | | return BaseResponseUtils.buildFail(SellResultCode.PROCESSING.getMessage()); |
| | | } else { |
| | | // 退款异常 |
| | | return BaseResponseUtils.buildError(SellResultCode.ABNORMAL.getMessage()); |
| | | } |
| | | } |
| | | } |
| File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-webchat/src/main/java/com/dy/pipirrWebChat/util/RestTemplateUtil.java |
| | |
| | | package com.dy.pipirrWebChat.util; |
| | | package com.dy.pipIrrSell.util; |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-02-23 15:42 |
| | | * @LastEditTime 2024-02-23 15:42 |
| | | * @date 2024-03-06 13:47 |
| | | * @LastEditTime 2024-03-06 13:47 |
| | | * @Description |
| | | */ |
| | | |
| | |
| | | HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(null, headers); |
| | | ResponseEntity<String> response = restTemplate.exchange(tempUrl, HttpMethod.GET, httpEntity, String.class); |
| | | return JSONObject.parseObject(response.getBody()); |
| | | } |
| | | |
| | | public JSONObject getHeaders(String url, Map<String, Object> queryParams, Map<String, String> headerParams) throws IOException { |
| | | String tempUrl = setParamsByAppendUrl(queryParams, url); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headerParams.forEach(headers::add); |
| | | HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(null, headers); |
| | | ResponseEntity<String> response = restTemplate.exchange(tempUrl, HttpMethod.GET, httpEntity, String.class); |
| | | |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("headers", response.getHeaders()); |
| | | jsonObject.put("body", response.getBody()); |
| | | return jsonObject; |
| | | } |
| | | |
| | | public JSONObject get2(String url, Map<String, Object> queryParams, Map<String, String> headerParams) throws IOException { |
| | |
| | | return url + sb; |
| | | } |
| | | |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.aop.SsoAop; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.BaseResponseUtils; |
| | | import com.dy.common.webUtil.ResultCodeMsg; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefund; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; |
| | | import com.dy.pipIrrSell.result.SellResultCode; |
| | | import com.dy.pipIrrSell.util.PayHelper; |
| | | import com.dy.pipIrrSell.virtualCard.dto.DtoAudit; |
| | | import com.dy.pipIrrSell.virtualCard.dto.DtoRefund; |
| | | import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM; |
| | | import com.dy.pipIrrSell.virtualCard.enums.RefundItemStateENUM; |
| | | import com.dy.pipIrrSell.virtualCard.enums.RefundStateENUM; |
| | | import com.dy.pipIrrSell.wechatpay.dto.Refund; |
| | | import com.dy.pipIrrSell.wechatpay.dto.ToRefund; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.media.Content; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| | | import io.swagger.v3.oas.annotations.responses.ApiResponses; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.validation.Valid; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.crypto.NoSuchPaddingException; |
| | | import java.io.IOException; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.SignatureException; |
| | | import java.security.spec.InvalidKeySpecException; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 8:40 |
| | | * @LastEditTime 2024-03-06 8:40 |
| | | * @Description |
| | | */ |
| | | |
| | | @Slf4j |
| | | @Tag(name = "虚拟卡管理", description = "虚拟卡管理") |
| | | @RestController |
| | | @RequestMapping(path="virtual_card") |
| | | @RequiredArgsConstructor |
| | | @Validated |
| | | public class VirtualCardCtrl { |
| | | private final VirtualCardSv virtualCardSv; |
| | | private final PayHelper payHelper; |
| | | |
| | | /** |
| | | * 虚拟卡账号注册 |
| | | * @param clientId |
| | | * @return |
| | | */ |
| | | @Operation(summary = "注册虚拟卡", description = "注册虚拟卡") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "add_vc") |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> addWallet(@RequestParam("clientId") @NotNull(message = "农户编号不能为空") Long clientId){ |
| | | if(clientId == null || clientId < 0) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.CLIENT_ID_CANNOT_BE_NULL.getMessage()); |
| | | } |
| | | |
| | | SeVirtualCard seVirtualCard = new SeVirtualCard(); |
| | | seVirtualCard.setClientId(clientId); |
| | | seVirtualCard.setMoney(0d); |
| | | seVirtualCard.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode()); |
| | | seVirtualCard.setLastOperateTime(new Date()); |
| | | seVirtualCard.setCreateTime(new Date()); |
| | | Long rec = virtualCardSv.insertVirtualCard(seVirtualCard); |
| | | if(rec == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.WALLET_OPEN_ACCOUNT_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 用户申请退款 |
| | | * @param po |
| | | * @param bindingResult |
| | | * @return |
| | | */ |
| | | @Operation(summary = "虚拟卡申请退款", description = "虚拟卡申请退款") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "add_refund", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> addRefund(@RequestBody @Valid DtoRefund po, BindingResult bindingResult){ |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | |
| | | Long virtualId = po.getVirtualId(); |
| | | Integer refundAmount = po.getRefundAmount(); |
| | | |
| | | // 根据虚拟卡ID获取虚拟卡对象 |
| | | SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); |
| | | if(seVirtualCard == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage()); |
| | | } |
| | | Long clientId = seVirtualCard.getClientId(); |
| | | Double money = seVirtualCard.getMoney(); |
| | | |
| | | // 验证退款金额是否大于余额 |
| | | if(refundAmount > money) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.REFUND_AMOUNT_CANNOT_GREATER_THAN_MONEY.getMessage()); |
| | | } |
| | | |
| | | // 计算消费后余额 |
| | | Double afterRefund = money - refundAmount; |
| | | |
| | | SeVcRefund seVcRefund = new SeVcRefund(); |
| | | seVcRefund.setVcId(virtualId); |
| | | seVcRefund.setClientId(clientId); |
| | | seVcRefund.setMoney(money); |
| | | seVcRefund.setRefundAmount(refundAmount); |
| | | seVcRefund.setAfterRefund(afterRefund); |
| | | seVcRefund.setApplicationTime(new Date()); |
| | | seVcRefund.setRefundStatus(RefundStateENUM.TO_AUDIT.getCode()); |
| | | |
| | | Long rec = virtualCardSv.addRefund(seVcRefund); |
| | | if(rec == 0) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.APPLICATION_REFUND_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } |
| | | |
| | | /** |
| | | * 审核退款申请 |
| | | * @param po |
| | | * @param bindingResult |
| | | * @return |
| | | */ |
| | | @Operation(summary = "审核退款申请", description = "审核退款申请") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "audit_refund", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> auditRefund(@RequestBody @Valid DtoAudit po, BindingResult bindingResult) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException { |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | |
| | | // 根据退款ID获取退款对象,并更新审核人、审核时间、审核备注、退款状态字段 |
| | | SeVcRefund seVcRefund = virtualCardSv.selectRefundByRefundId(po.getRefundId()); |
| | | Long virtualId = seVcRefund.getVcId(); |
| | | Integer refundAmount = seVcRefund.getRefundAmount(); |
| | | seVcRefund.setAuditor(po.getAuditor()); |
| | | seVcRefund.setAuditTime(new Date()); |
| | | seVcRefund.setRemarks(po.getRemarks()); |
| | | seVcRefund.setRefundStatus(RefundStateENUM.TO_REFUND.getCode()); |
| | | Integer rec = virtualCardSv.updateRefund(seVcRefund); |
| | | if(rec == 0) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.AUDIT_REFUND_FAIL.getMessage()); |
| | | } |
| | | |
| | | // 完成审核后获取待退款订单列表 |
| | | List<ToRefund> list_ToRefund = payHelper.getToRefunds(virtualId, refundAmount); |
| | | if(list_ToRefund == null || list_ToRefund.size() <=0) |
| | | return BaseResponseUtils.buildFail(SellResultCode.NOT_SUFFICIENT_FUNDS.getMessage()); |
| | | |
| | | //遍历待退款列表 |
| | | JSONArray array_ToRefund = (JSONArray) JSON.toJSON(list_ToRefund); |
| | | for(int i = 0; i < array_ToRefund.size(); i++) { |
| | | JSONObject job_ToRefund = array_ToRefund.getJSONObject(i); |
| | | String orderNumber_ToRefund = job_ToRefund.getString("orderNumber"); |
| | | Integer refundAmount_ToRefund = job_ToRefund.getInteger("refundAmount"); |
| | | |
| | | // 生成退款分项记录 |
| | | SeVcRefundItem seVcRefundItem = new SeVcRefundItem(); |
| | | seVcRefundItem.setRefundId(po.getRefundId()); |
| | | seVcRefundItem.setOrderNumber(orderNumber_ToRefund); |
| | | String refundNumber = virtualCardSv.generateRefundNumber(orderNumber_ToRefund); |
| | | seVcRefundItem.setRefundNumber(refundNumber); |
| | | seVcRefundItem.setRefundAmount(refundAmount_ToRefund); |
| | | seVcRefundItem.setCreateTime(new Date()); |
| | | seVcRefundItem.setRefundStatus(RefundItemStateENUM.NO_REFUND.getCode()); |
| | | Long refundItemId = virtualCardSv.addRefundItem(seVcRefundItem); |
| | | |
| | | // 调用微信退款申请接口 |
| | | Refund refund = new Refund(); |
| | | refund.setTradeNo(orderNumber_ToRefund); |
| | | refund.setRefundNo(refundNumber); |
| | | refund.setRefund(refundAmount_ToRefund); |
| | | BaseResponse rep = payHelper.refunds(refund); |
| | | } |
| | | |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard; |
| | | |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.BaseResponseUtils; |
| | | import com.dy.pipIrrGlobal.daoSe.SeVcRechargeMapper; |
| | | import com.dy.pipIrrGlobal.daoSe.SeVcRefundItemMapper; |
| | | import com.dy.pipIrrGlobal.daoSe.SeVcRefundMapper; |
| | | import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefund; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; |
| | | import com.dy.pipIrrGlobal.voSe.VoOrders; |
| | | import com.dy.pipIrrSell.result.SellResultCode; |
| | | import com.dy.pipIrrSell.virtualCard.dto.DtoVirtualCard; |
| | | import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM; |
| | | import com.dy.pipIrrSell.virtualCard.enums.OrderStateENUM; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 8:41 |
| | | * @LastEditTime 2024-03-06 8:41 |
| | | * @Description |
| | | */ |
| | | |
| | | @Slf4j |
| | | @Service |
| | | public class VirtualCardSv { |
| | | @Autowired |
| | | private SeVirtualCardMapper seVirtualCardMapper; |
| | | |
| | | @Autowired |
| | | private SeVcRechargeMapper seVcRechargeMapper; |
| | | |
| | | @Autowired |
| | | private SeVcRefundMapper seVcRefundMapper; |
| | | |
| | | @Autowired |
| | | private SeVcRefundItemMapper seVcRefundItemMapper; |
| | | |
| | | /** |
| | | * 注册虚拟卡 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Long insertVirtualCard(SeVirtualCard po) { |
| | | seVirtualCardMapper.insert(po); |
| | | return po.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 修改虚拟卡 |
| | | * 充值、消费、申请退款、审核退款时需要修改虚拟卡的:余额、最后操作、最后操作时间 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Integer updateVirtualCard(SeVirtualCard po) { |
| | | return seVirtualCardMapper.updateByPrimaryKeySelective(po); |
| | | } |
| | | |
| | | /** |
| | | * 根据虚拟卡编号获取虚拟卡对象 |
| | | * @param virtualId |
| | | * @return |
| | | */ |
| | | public SeVirtualCard selectVirtuCardById(Long virtualId) { |
| | | return seVirtualCardMapper.selectByPrimaryKey(virtualId); |
| | | } |
| | | |
| | | /** |
| | | * 添加虚拟卡充值记录 |
| | | * JSAPI下单后生成部分充值记录 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public BaseResponse<Boolean> insertVCRecharge(DtoVirtualCard po) { |
| | | String orderNumber = po.getOrderNumber(); |
| | | Long virtualId = po.getVirtualId(); |
| | | Long clientId = po.getClientId(); |
| | | Integer rechargeAmount = po.getRechargeAmount(); |
| | | |
| | | // 验证该虚拟卡账户是否存在并取出当前账户余额 |
| | | SeVirtualCard seVirtualCard = seVirtualCardMapper.selectByPrimaryKey(virtualId); |
| | | if(seVirtualCard == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.NO_ACCOUNT.getMessage()); |
| | | } |
| | | Double money = seVirtualCard.getMoney(); |
| | | |
| | | // 添加充值记录 |
| | | SeVcRecharge seVcRecharge = new SeVcRecharge(); |
| | | seVcRecharge.setVcId(virtualId); |
| | | seVcRecharge.setClientId(clientId); |
| | | seVcRecharge.setMoney(money); |
| | | seVcRecharge.setOrderNumber(orderNumber); |
| | | seVcRecharge.setRechargeAmount(rechargeAmount); |
| | | seVcRecharge.setOrderTime(new Date()); |
| | | seVcRecharge.setOrderState(OrderStateENUM.NON_PAYMENT.getCode()); |
| | | Integer rec = seVcRechargeMapper.insert(seVcRecharge); |
| | | if(rec == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } |
| | | |
| | | /** |
| | | * 修改虚拟卡充值记录 |
| | | * 微信支付通知后: |
| | | * 1. 更新充值表:充值后余额、支付完成时间、订单状态 |
| | | * 2. 更新虚拟卡表:账户余额、最后操作、最后操作时间 |
| | | * @param orderNumber 订单编号 |
| | | * @return |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public BaseResponse<Boolean> updateVCRecharge(String orderNumber, Date rechargeTime) { |
| | | SeVcRecharge seVcRecharge = seVcRechargeMapper.getVCRechargeByorderNumber(orderNumber); |
| | | if(seVcRecharge == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_NOT_EXIST.getMessage()); |
| | | } |
| | | |
| | | Long virtualId = seVcRecharge.getVcId(); |
| | | Double money = seVcRecharge.getMoney(); |
| | | Integer rechargeAmount = seVcRecharge.getRechargeAmount(); |
| | | Double afterRrecharge = money + rechargeAmount; |
| | | |
| | | seVcRecharge.setAfterRecharge(afterRrecharge); |
| | | seVcRecharge.setRechargeTime(rechargeTime); |
| | | seVcRecharge.setOrderState(OrderStateENUM.PAID.getCode()); |
| | | Integer rec = seVcRechargeMapper.updateByPrimaryKeySelective(seVcRecharge); |
| | | if(rec == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_FAIL.getMessage()); |
| | | } |
| | | |
| | | SeVirtualCard seVirtualCard = seVirtualCardMapper.selectByPrimaryKey(virtualId); |
| | | if(seVirtualCard == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage()); |
| | | } |
| | | seVirtualCard.setMoney(afterRrecharge); |
| | | seVirtualCard.setLastOperate(LastOperateENUM.RECHARGE.getCode()); |
| | | seVirtualCard.setLastOperateTime(new Date()); |
| | | Integer rec2 = seVirtualCardMapper.updateByPrimaryKeySelective(seVirtualCard); |
| | | if(rec2 == null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_FAIL.getMessage()); |
| | | } |
| | | return BaseResponseUtils.buildSuccess(true) ; |
| | | } |
| | | |
| | | /** |
| | | * 修改虚拟卡充值记录(废弃) |
| | | * 微信小程序支付通知后修改:余额、充值后余额、充值完成时间 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Integer updateVCRecharge(SeVcRecharge po) { |
| | | return seVcRechargeMapper.updateByPrimaryKeySelective(po); |
| | | } |
| | | |
| | | /** |
| | | * 根据虚拟卡号获取订单列表 |
| | | * @param virtualId |
| | | * @return |
| | | */ |
| | | public List<VoOrders> selectOrders(Long virtualId) { |
| | | List<VoOrders> rsVo = seVcRechargeMapper.getOrders(virtualId); |
| | | return rsVo ; |
| | | } |
| | | |
| | | /** |
| | | * 根据退款ID获取退款对象 |
| | | * @param refundId |
| | | * @return |
| | | */ |
| | | public SeVcRefund selectRefundByRefundId(Long refundId) { |
| | | return seVcRefundMapper.selectByPrimaryKey(refundId); |
| | | } |
| | | |
| | | /** |
| | | * 添加退款申请 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Long addRefund(SeVcRefund po) { |
| | | seVcRefundMapper.insert(po); |
| | | return po.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 修改退款记录 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Integer updateRefund(SeVcRefund po) { |
| | | return seVcRefundMapper.updateByPrimaryKeySelective(po); |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号获取其各笔退款金额 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | public List<Integer> selectRefundAmount(String orderNumber) { |
| | | List<Integer> rsVo = seVcRefundMapper.getRefundAmount(orderNumber); |
| | | return rsVo; |
| | | } |
| | | |
| | | /** |
| | | * 添加退款分项 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Long addRefundItem(SeVcRefundItem po) { |
| | | seVcRefundItemMapper.insert(po); |
| | | return po.getRefundId(); |
| | | } |
| | | |
| | | /** |
| | | * 编辑退款分项 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | public Integer updateRefundItem(SeVcRefundItem po) { |
| | | return seVcRefundItemMapper.updateByPrimaryKeySelective(po); |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号生成退款单号 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | public String generateRefundNumber(String orderNumber) { |
| | | String refundNumber = seVcRefundItemMapper.getLastRefundNumber(orderNumber); |
| | | if(refundNumber == null) { |
| | | refundNumber = orderNumber + "01"; |
| | | return refundNumber; |
| | | } |
| | | |
| | | String a = String.format("%02d", (Integer.parseInt(refundNumber.substring(29,30).trim()) + 1)); |
| | | return a; |
| | | } |
| | | |
| | | /** |
| | | * 根据订单号获取充值金额,调用退款申请接口使用 |
| | | * @param orderNumber |
| | | * @return |
| | | */ |
| | | public Integer getRechargeAmountByOrderNumber(String orderNumber) { |
| | | return seVcRechargeMapper.getRechargeAmountByOrderNumber(orderNumber); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 根据退款通知接口返回的退款单号反查退款ID,查询该退款ID下未退款记录数量 |
| | | * @param refundNumber |
| | | * @return |
| | | */ |
| | | public Integer getNoRefundedCount(String refundNumber) { |
| | | return seVcRefundItemMapper.getNoRefundedCount(refundNumber); |
| | | } |
| | | |
| | | /** |
| | | * 根据退款单号获取退款ID,退款通知后更新退款表所需 |
| | | * @param refundNumber |
| | | * @return |
| | | */ |
| | | public Long getRefundIdByRefundNumber(String refundNumber) { |
| | | return seVcRefundItemMapper.getRefundIdByRefundNumber(refundNumber); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | import org.hibernate.validator.constraints.Length; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 21:09 |
| | | * @LastEditTime 2024-03-08 21:09 |
| | | * @Description |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "退款审核传入对象") |
| | | public class DtoAudit { |
| | | public static final long serialVersionUID = 202403082109001L; |
| | | |
| | | /** |
| | | * 虚拟卡退款ID |
| | | */ |
| | | @Schema(description = "虚拟卡退款ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡退款ID不能为空") |
| | | private Long refundId; |
| | | |
| | | /** |
| | | * 审核人ID |
| | | */ |
| | | @Schema(description = "审核人ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "审核ID不能为空") |
| | | private Long auditor; |
| | | |
| | | /** |
| | | * 审核备注 |
| | | */ |
| | | @Schema(description = "审核备注", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @Length(max = 200) |
| | | private String remarks; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Positive; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 20:17 |
| | | * @LastEditTime 2024-03-08 20:17 |
| | | * @Description |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "用户退款传入对象") |
| | | public class DtoRefund { |
| | | public static final long serialVersionUID = 202403080858001L; |
| | | |
| | | /** |
| | | * 虚拟卡编号 |
| | | */ |
| | | @Schema(description = "虚拟卡编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡编号不能为空") |
| | | private Long virtualId; |
| | | |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | @Positive(message = "充值金额必须为大于0的整数") |
| | | private Integer refundAmount; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 9:40 |
| | | * @LastEditTime 2024-03-06 9:40 |
| | | * @Description |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "虚拟卡充值传入对象") |
| | | public class DtoVirtualCard { |
| | | public static final long serialVersionUID = 202403060943001L; |
| | | |
| | | /** |
| | | * 订单号 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 农户ID |
| | | */ |
| | | @Schema(description = "农户ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "农户ID不能为空") |
| | | private Long clientId; |
| | | |
| | | /** |
| | | * 虚拟卡ID |
| | | */ |
| | | @Schema(description = "虚拟卡ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡ID不能为空") |
| | | private Long virtualId; |
| | | |
| | | /** |
| | | * 充值金额 |
| | | */ |
| | | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值金额不能为空") |
| | | private Integer rechargeAmount; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 9:21 |
| | | * @LastEditTime 2024-03-06 9:21 |
| | | * @Description |
| | | */ |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum LastOperateENUM { |
| | | OPEN_ACCOUNT((byte)1, "开户"), |
| | | RECHARGE((byte)2, "充值"), |
| | | CONSUME((byte)3, "消费"), |
| | | APPLY_REFUND((byte)4, "申请退款"), |
| | | AUDIT_REFUND((byte)5, "退款审核"), |
| | | REFUND((byte)6, "退款"); |
| | | |
| | | private final Byte code; |
| | | private final String message; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 10:00 |
| | | * @LastEditTime 2024-03-06 10:00 |
| | | * @Description |
| | | */ |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrderStateENUM { |
| | | NON_PAYMENT((byte)1, "未支付"), |
| | | PAID((byte)2, "已支付"); |
| | | |
| | | private final Byte code; |
| | | private final String message; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-11 8:49 |
| | | * @LastEditTime 2024-03-11 8:49 |
| | | * @Description 退款分项的退款状态,即微信退款状态 |
| | | */ |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum RefundItemStateENUM { |
| | | NO_REFUND((byte)1, "未退款"), |
| | | REFUNDED((byte)2, "已退款"); |
| | | |
| | | private final Byte code; |
| | | private final String message; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.virtualCard.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-08 20:45 |
| | | * @LastEditTime 2024-03-08 20:45 |
| | | * @Description |
| | | */ |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum RefundStateENUM { |
| | | TO_AUDIT((byte)1, "待审核"), |
| | | TO_REFUND((byte)2, "待退款"), |
| | | REFUNDED((byte)3, "已退款"); |
| | | |
| | | private final Byte code; |
| | | private final String message; |
| | | } |
| | |
| | | } |
| | | |
| | | if(walletSv.getWalletByClientId(clientId) != null) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.WALLET_ACCOUNT_EXIST.getMessage()); |
| | | //return BaseResponseUtils.buildFail(SellResultCode.WALLET_ACCOUNT_EXIST.getMessage()); |
| | | } |
| | | |
| | | SeWallet seWallet = new SeWallet(); |
| | |
| | | import com.dy.pipIrrGlobal.voSe.VoWalletConsume; |
| | | import com.dy.pipIrrGlobal.voSe.VoWalletRecharge; |
| | | import com.dy.pipIrrGlobal.voSe.VoWalletRefund; |
| | | import com.dy.pipIrrSell.wallet.qo.QueryVo; |
| | | import com.dy.pipIrrSell.wallet.qo.QoWalletRecharge; |
| | | import com.dy.pipIrrSell.wallet.qo.QueryVo; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.dubbo.common.utils.PojoUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-webchat/src/main/java/com/dy/pipirrWebChat/payment/PayInfo.java |
| | |
| | | package com.dy.pipirrWebChat.payment; |
| | | package com.dy.pipIrrSell.wechatpay; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-02-22 20:20 |
| | | * @LastEditTime 2024-02-22 20:20 |
| | | * @date 2024-03-06 13:49 |
| | | * @LastEditTime 2024-03-06 13:49 |
| | | * @Description |
| | | */ |
| | | public class PayInfo { |
| | | /* |
| | | /** |
| | | * 小程序登录API |
| | | */ |
| | | public static String loginUrl = "https://api.weixin.qq.com/sns/jscode2session"; |
| | | |
| | | /* |
| | | /** |
| | | * 检验登录态 |
| | | */ |
| | | public static String checkSessionUrl = "https://api.weixin.qq.com/wxa/checksession"; |
| | | |
| | | /** |
| | | * 重置登录态 |
| | | */ |
| | | public static String resetUserSessionKeyUrl = "https://api.weixin.qq.com/wxa/resetusersessionkey"; |
| | | |
| | | /** |
| | | * 获取接口调用凭据 |
| | | */ |
| | | public static String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token"; |
| | | |
| | | /** |
| | | * 统一下单API |
| | | */ |
| | | //public static String orderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
| | |
| | | /* |
| | | * 支付结果通知API |
| | | */ |
| | | public static String notifyUrl = "https://www.muxiaobao.com/api/Payment/OrderNotify"; |
| | | //public static String notifyUrl = "https://www.muxiaobao.com/api/Payment/OrderNotify"; |
| | | public static String notifyUrl = "https://44978f7456.imdo.co/webchat/payment/orderNotify"; |
| | | |
| | | /* |
| | | * 查询订单API |
| | | */ |
| | | public static String queryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; |
| | | |
| | | /* |
| | | /** |
| | | * 申请退款API |
| | | */ |
| | | public static String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund"; |
| | | public static String refundUrl = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"; |
| | | |
| | | /* |
| | | * 退款通知API |
| | |
| | | /** |
| | | * 私钥文件路径 |
| | | */ |
| | | public static String certFileName = "C:\\webchat\\apiclient_key.pem"; |
| | | public static String privateCertFileName = "C:\\webchat\\apiclient_key.pem"; |
| | | |
| | | public static String publicCertFileName = "C:\\webchat\\wxp_cert.pem"; |
| | | |
| | | /* |
| | | * 微信订单号,优先使用 |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay; |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.aop.SsoAop; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.BaseResponseUtils; |
| | | import com.dy.common.webUtil.ResultCodeMsg; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefund; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRefundItem; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeWebchatLogonState; |
| | | import com.dy.pipIrrGlobal.voSe.VoClient; |
| | | import com.dy.pipIrrSell.client.ClientSv; |
| | | import com.dy.pipIrrSell.result.SellResultCode; |
| | | import com.dy.pipIrrSell.util.AesUtil; |
| | | import com.dy.pipIrrSell.util.PayHelper; |
| | | import com.dy.pipIrrSell.util.RestTemplateUtil; |
| | | import com.dy.pipIrrSell.virtualCard.VirtualCardSv; |
| | | import com.dy.pipIrrSell.virtualCard.dto.DtoVirtualCard; |
| | | import com.dy.pipIrrSell.virtualCard.enums.LastOperateENUM; |
| | | import com.dy.pipIrrSell.virtualCard.enums.RefundItemStateENUM; |
| | | import com.dy.pipIrrSell.wallet.enums.RefundStatusENUM; |
| | | import com.dy.pipIrrSell.wechatpay.dto.Code2Session; |
| | | import com.dy.pipIrrSell.wechatpay.dto.DtoOrder; |
| | | import com.dy.pipIrrSell.wechatpay.dto.OrderNotify; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | | import io.swagger.v3.oas.annotations.media.Content; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| | | import io.swagger.v3.oas.annotations.responses.ApiResponses; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.validation.Valid; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.crypto.NoSuchPaddingException; |
| | | import java.io.IOException; |
| | | import java.security.GeneralSecurityException; |
| | | import java.security.InvalidKeyException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.SignatureException; |
| | | import java.security.spec.InvalidKeySpecException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:49 |
| | | * @LastEditTime 2024-03-06 13:49 |
| | | * @Description |
| | | */ |
| | | |
| | | @Slf4j |
| | | @Tag(name = "微信支付管理", description = "微信支付各种操作") |
| | | @RestController |
| | | @RequestMapping(path="payment") |
| | | @RequiredArgsConstructor |
| | | public class PaymentCtrl { |
| | | private final PaymentSv paymentSv; |
| | | private final RestTemplateUtil restTemplateUtil; |
| | | private final PayHelper payHelper; |
| | | private final VirtualCardSv virtualCardSv; |
| | | private final ClientSv clientSv; |
| | | |
| | | private final String privateCertFileName = PayInfo.privateCertFileName; |
| | | private final String appid = PayInfo.appid; |
| | | private final String mchid = PayInfo.mchid; |
| | | private final String schema = PayInfo.schema; |
| | | private final String signType = PayInfo.signType; |
| | | private final String description = PayInfo.description; |
| | | private final String loginUrl = PayInfo.loginUrl; |
| | | private final String notifyUrl = PayInfo.notifyUrl; |
| | | private final String grantType = PayInfo.grantType; |
| | | |
| | | // 平台证书公钥 |
| | | private final Map CERTIFICATE_MAP = new HashMap(); |
| | | |
| | | /** |
| | | * 登录凭证校验 |
| | | * @param code2Session 登录凭证校验传入对象 |
| | | * @param bindingResult |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @Operation(summary = "登录凭证校验", description = "登录凭证校验") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "getSessionId") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> getSessionId(@RequestBody @Valid Code2Session code2Session, BindingResult bindingResult) throws Exception { |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | |
| | | Map<String, Object> queryParams = new HashMap<>(); |
| | | queryParams.put("appid", appid); |
| | | queryParams.put("secret", code2Session.getSecret()); |
| | | queryParams.put("js_code", code2Session.getJs_code()); |
| | | queryParams.put("grant_type", grantType); |
| | | Map<String, String> headerParams = new HashMap<>(); |
| | | JSONObject job = restTemplateUtil.get(loginUrl, queryParams, headerParams); |
| | | |
| | | if(job.getLong("errcode") != null && job.getLong("errcode") >= -1) { |
| | | return BaseResponseUtils.buildFail("登录凭证校验失败"); |
| | | } |
| | | |
| | | String openid = job.getString("openid"); |
| | | String sessionKey = job.getString("session_key"); |
| | | |
| | | // 检验登录态 |
| | | //JSONObject checkSessionKey = payHelper.checkSessionKey(appid, secret, openid, sessionKey); |
| | | //if(checkSessionKey != null) { |
| | | // Integer errcode = checkSessionKey.getInteger("errcode"); |
| | | // String errmsg = checkSessionKey.getString("errmsg"); |
| | | //} |
| | | |
| | | // 重置登录态 |
| | | //JSONObject resetUserSessionKey = payHelper.resetUserSessionKey(appid, secret, openid, sessionKey); |
| | | //if(resetUserSessionKey != null) { |
| | | // Integer errcode = checkSessionKey.getInteger("errcode"); |
| | | // String errmsg = checkSessionKey.getString("errmsg"); |
| | | // String openid_New = checkSessionKey.getString("openid"); |
| | | // String sessionKey_New = checkSessionKey.getString("session_key"); |
| | | //} |
| | | |
| | | // 添加登录态记录 |
| | | SeWebchatLogonState po = new SeWebchatLogonState(); |
| | | po.setOpenId(openid); |
| | | po.setSessionKey(sessionKey); |
| | | Date createTime = new Date(); |
| | | po.setCreateTime(createTime); |
| | | Long id = paymentSv.insert(po); |
| | | if(id == null || id <= 0) { |
| | | return BaseResponseUtils.buildFail("登录态记录添加失败"); |
| | | } |
| | | String SessionId = String.valueOf(id); |
| | | |
| | | return BaseResponseUtils.buildSuccess(SessionId) ; |
| | | } |
| | | |
| | | /** |
| | | * 下载微信支付平台证书 测试完废除 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @Operation(summary = "下载平台证书", description = "下载平台证书") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @GetMapping(path = "certificates") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> certificates() throws Exception { |
| | | String method = "GET"; |
| | | String httpUrl = "/v3/certificates"; |
| | | String nonceStr = payHelper.generateRandomString(); |
| | | Long timestamp = System.currentTimeMillis() / 1000; |
| | | |
| | | String header = schema + " " + payHelper.getToken(method, httpUrl, "", nonceStr, timestamp, privateCertFileName); |
| | | |
| | | Map<String, String> headers = new HashMap<>(); |
| | | headers.put("Authorization", header); |
| | | headers.put("Accept", "application/json"); |
| | | JSONObject job_result = restTemplateUtil.getHeaders(PayInfo.certificates,null, headers); |
| | | JSONObject job_headers = job_result.getJSONObject("headers"); |
| | | String wechatpayNonce = job_headers.getJSONArray("Wechatpay-Nonce").getString(0); |
| | | String wechatpaySerial = job_headers.getJSONArray("Wechatpay-Serial").getString(0); |
| | | String wechatpaySignature = job_headers.getJSONArray("Wechatpay-Signature").getString(0); |
| | | String wechatpaySignatureType = job_headers.getJSONArray("Wechatpay-Signature-Type").getString(0); |
| | | String wechatpayTimestamp = job_headers.getJSONArray("Wechatpay-Timestamp").getString(0); |
| | | |
| | | JSONObject job_body = job_result.getJSONObject("body"); |
| | | |
| | | // 构造验签名串 |
| | | String signatureStr = payHelper.responseSign(wechatpayTimestamp, wechatpayNonce, job_body.toJSONString()); |
| | | // 验证签名 |
| | | Boolean valid = payHelper.responseSignVerify(wechatpaySerial, signatureStr, wechatpaySignature); |
| | | |
| | | return BaseResponseUtils.buildSuccess(); |
| | | } |
| | | |
| | | /** |
| | | * JSAPI下单 |
| | | * @param order 下单请求对象,包含需要传入的参数 |
| | | * @param bindingResult |
| | | * @return |
| | | */ |
| | | @Operation(summary = "JSAPI下单", description = "JSAPI下单") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "placeOrder") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<Boolean> placeOrder(@RequestBody @Valid DtoOrder order, BindingResult bindingResult) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException { |
| | | if(bindingResult != null && bindingResult.hasErrors()){ |
| | | return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | // 接收参数:登录态ID、农户ID、虚拟卡ID、充值金额 |
| | | String sessionId = order.getSessionId(); |
| | | Long virtualId = order.getVirtualId(); |
| | | Integer rechargeAmount = order.getRechargeAmount(); |
| | | |
| | | String prepayId = ""; |
| | | SeWebchatLogonState po = paymentSv.selectOne(Long.parseLong(sessionId)); |
| | | String openid = po.getOpenId(); |
| | | |
| | | SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); |
| | | Long clientId = seVirtualCard.getClientId(); |
| | | |
| | | VoClient voClient = clientSv.getOneClient(clientId); |
| | | String clientNum = voClient.getClientNum(); |
| | | |
| | | // 生成订单号并添加充值记录 |
| | | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | String orderNumber = clientNum + dateFormat.format(new Date()); |
| | | |
| | | // 生成虚拟卡充值记录(部分字段) |
| | | DtoVirtualCard virtualCard = new DtoVirtualCard(); |
| | | virtualCard.setOrderNumber(orderNumber); |
| | | virtualCard.setClientId(clientId); |
| | | virtualCard.setVirtualId(virtualId); |
| | | virtualCard.setRechargeAmount(rechargeAmount); |
| | | BaseResponse result = virtualCardSv.insertVCRecharge(virtualCard); |
| | | if(!result.getCode().equals("0001")) { |
| | | return BaseResponseUtils.buildFail(SellResultCode.RECHARGE_ADD_FAIL.getMessage()); |
| | | } |
| | | |
| | | JSONObject job_body = new JSONObject(); |
| | | job_body.put("appid", appid); |
| | | job_body.put("mchid", mchid); |
| | | job_body.put("description", description); |
| | | job_body.put("out_trade_no", orderNumber); |
| | | job_body.put("notify_url", notifyUrl); |
| | | |
| | | //订单金额 |
| | | JSONObject job_amount = new JSONObject(); |
| | | job_amount.put("total", 1); |
| | | job_amount.put("currency", "CNY"); |
| | | job_body.put("amount", job_amount); |
| | | |
| | | //支付者 |
| | | JSONObject job_payer = new JSONObject(); |
| | | job_payer.put("openid", openid); |
| | | job_body.put("payer", job_payer); |
| | | |
| | | // 获取随机串和时间戳,放在此处以保证 |
| | | String nonceStr = payHelper.generateRandomString(); |
| | | Long timestamp = System.currentTimeMillis() / 1000; |
| | | |
| | | String method = "POST"; |
| | | String httpUrl = "/v3/pay/transactions/jsapi"; |
| | | |
| | | String body = job_body.toJSONString(); |
| | | String header = schema + " " + payHelper.getToken(method, httpUrl, body, nonceStr, timestamp, privateCertFileName); |
| | | |
| | | Map<String, String> headers = new HashMap<>(); |
| | | headers.put("Authorization", header); |
| | | headers.put("Accept", "application/json"); |
| | | headers.put("Content-Type", "application/json"); |
| | | |
| | | // 暂时注释掉,认证通过后再放开 |
| | | //JSONObject job_result = restTemplateUtil.post(PayInfo.orderUrl, body, headers); |
| | | //if(job_result != null) { |
| | | // System.out.println(job_result.toString()); |
| | | // prepayId = job_result.getString("prepay_id"); |
| | | //} |
| | | |
| | | return BaseResponseUtils.buildSuccess(prepayId) ; |
| | | } |
| | | |
| | | /** |
| | | * 支付通知/退款结果通知 |
| | | * @param headers |
| | | * @param orderNotify |
| | | * @param response |
| | | * @return |
| | | * @throws IOException |
| | | * @throws GeneralSecurityException |
| | | */ |
| | | @Operation(summary = "支付通知", description = "支付通知") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @PostMapping(path = "orderNotify", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public JSONObject orderNotify(@RequestHeader HttpHeaders headers, @RequestBody OrderNotify orderNotify, HttpServletResponse response) throws IOException, GeneralSecurityException { |
| | | JSONObject result = new JSONObject(); |
| | | |
| | | /** |
| | | * 1.验签处理 |
| | | * 从header中取出4个子参数,同时取出body |
| | | * 验时间差,超过5分钟的不处理 |
| | | * 验证签名 |
| | | * 验证书序列号,必须与某一个证书的序列号一致 |
| | | */ |
| | | String wechatpayNonce = String.valueOf(headers.get("Wechatpay-Nonce").get(0)); |
| | | String wechatpaySerial = String.valueOf(headers.get("Wechatpay-Serial").get(0)); |
| | | String wechatpaySignature = String.valueOf(headers.get("Wechatpay-Signature").get(0)); |
| | | String wechatpayTimestamp = String.valueOf(headers.get("Wechatpay-Timestamp").get(0)); |
| | | String bodyStr = JSONObject.toJSONString(orderNotify); |
| | | |
| | | // 验时间戳,时间差大于5分钟的拒绝 |
| | | Long timeDiff = (System.currentTimeMillis() / 1000 - Long.parseLong(wechatpayTimestamp))/60; |
| | | if(timeDiff > 5) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | |
| | | // 构造验签名串 |
| | | String signatureStr = payHelper.responseSign(wechatpayTimestamp, wechatpayNonce, bodyStr); |
| | | // 验证签名 |
| | | Boolean valid = payHelper.responseSignVerify(wechatpaySerial, signatureStr, wechatpaySignature); |
| | | if(!valid) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | |
| | | // 序列号验证要放在验签后,因为验签时可能会下载新的证书 |
| | | boolean SerialIsValid = false; |
| | | for (String key : payHelper.CERTIFICATE_MAP.keySet()) { |
| | | if(key.equals(wechatpaySerial)) { |
| | | SerialIsValid = true; |
| | | } |
| | | } |
| | | if(!SerialIsValid) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 解密处理 |
| | | * 1 |
| | | */ |
| | | String eventType = orderNotify.getEvent_type(); |
| | | |
| | | if(eventType != null && eventType.equals("TRANSACTION.SUCCESS")) { |
| | | // 支付成功回调 |
| | | /** |
| | | * 支付成功的回调 |
| | | * 取出通知数据对象,继而取出解密所需的associatedData和nonce,以及密文ciphertext |
| | | * 解密ciphertext得到 |
| | | */ |
| | | OrderNotify.NotifyResource notifyResource = orderNotify.getResource(); |
| | | String associatedData = notifyResource.getAssociated_data(); |
| | | String nonce = notifyResource.getNonce(); |
| | | String ciphertext = notifyResource.getCiphertext(); |
| | | |
| | | String resource = AesUtil.decryptToString(PayInfo.key.getBytes("utf-8"), associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext); |
| | | JSONObject job_resource = JSONObject.parseObject(resource); |
| | | |
| | | // 解密后取出:商户订单员、微信支付订单号、交易状态、支付完成时间 |
| | | String out_trade_no = job_resource.getString("out_trade_no"); |
| | | String transaction_id = job_resource.getString("transaction_id"); |
| | | String trade_state = job_resource.getString("trade_state"); |
| | | Date success_time = job_resource.getDate("success_time"); |
| | | |
| | | // 更新虚拟卡表及充值表响应字段 |
| | | BaseResponse result_ = virtualCardSv.updateVCRecharge(out_trade_no, success_time); |
| | | if(!result_.getCode().equals("0001")) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | } else if(eventType != null && eventType.equals("REFUND.SUCCESS")) { |
| | | // 退款成功后回调 |
| | | /** |
| | | * 退款成功的回调 |
| | | * 取出通知数据对象,继而取出解密所需的associatedData和nonce,以及密文ciphertext |
| | | * 解密ciphertext得到 |
| | | */ |
| | | OrderNotify.NotifyResource notifyResource = orderNotify.getResource(); |
| | | String associatedData = notifyResource.getAssociated_data(); |
| | | String nonce = notifyResource.getNonce(); |
| | | String ciphertext = notifyResource.getCiphertext(); |
| | | |
| | | String resource = AesUtil.decryptToString(PayInfo.key.getBytes("utf-8"), associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext); |
| | | JSONObject job_resource = JSONObject.parseObject(resource); |
| | | |
| | | // 解密后取出:商户订单员、微信支付订单号、交易状态、支付完成时间 |
| | | String out_trade_no = job_resource.getString("out_trade_no"); |
| | | String transaction_id = job_resource.getString("transaction_id"); |
| | | String out_refund_no = job_resource.getString("out_refund_no"); |
| | | String refund_status = job_resource.getString("refund_status"); |
| | | Date success_time = job_resource.getDate("success_time"); |
| | | if(!refund_status.equals("SUCCESS")) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | |
| | | // 更新虚拟卡表及充值表响应字段 |
| | | SeVcRefundItem seVcRefundItem = new SeVcRefundItem(); |
| | | seVcRefundItem.setRefundTime(success_time); |
| | | seVcRefundItem.setRefundStatus(RefundItemStateENUM.REFUNDED.getCode()); |
| | | Integer rec = virtualCardSv.updateRefundItem(seVcRefundItem); |
| | | if(rec == null && rec <= 0) { |
| | | response.setStatus(500); |
| | | result.put("code", "FAIL"); |
| | | result.put("message", "失败"); |
| | | return result; |
| | | } |
| | | |
| | | // 根据退款单号反查退款ID,根据退款ID获取退款状态是未退款的记录数量,如果是0则说明全部退款完成,更新退款表状态为已退款,将退款后金额更新到虚拟卡表 |
| | | /** |
| | | * 根据退款通知接口返回的退款单号反查退款ID,查询该退款ID下未退款记录数量 |
| | | * 如果结果为0,则该退款已经完成 |
| | | * 1. 更新退款表状态为已退款 |
| | | * 2. 将退款后余额更新到虚拟卡表中 |
| | | */ |
| | | Integer noRefundedCount = virtualCardSv.getNoRefundedCount(out_refund_no); |
| | | if(noRefundedCount != null && noRefundedCount == 0) { |
| | | // 获取退款对象并修改退款状态 |
| | | Long refundId = virtualCardSv.getRefundIdByRefundNumber(out_refund_no); |
| | | SeVcRefund seVcRefund = virtualCardSv.selectRefundByRefundId(refundId); |
| | | seVcRefund.setRefundStatus(RefundStatusENUM.REFUNDED.getCode()); |
| | | virtualCardSv.updateRefund(seVcRefund); |
| | | |
| | | // 获取虚拟卡对象并修改余额、最后操作、最后操作时间 |
| | | Long vcId = seVcRefund.getVcId(); |
| | | Double afterRefund = seVcRefund.getAfterRefund(); |
| | | SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(vcId); |
| | | seVirtualCard.setMoney(afterRefund); |
| | | seVirtualCard.setLastOperate(LastOperateENUM.REFUND.getCode()); |
| | | seVirtualCard.setLastOperateTime(new Date()); |
| | | virtualCardSv.updateVirtualCard(seVirtualCard); |
| | | } |
| | | } |
| | | |
| | | // 通知应答 |
| | | response.setStatus(200); |
| | | result.put("code", "SUCCESS"); |
| | | result.put("message", "成功"); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 再次签名 |
| | | * @param prepayId 预支付交易会话标识 |
| | | * @return 小程序调起支付参数 |
| | | * @throws Exception |
| | | */ |
| | | @Operation(summary = "再次签名", description = "再次签名") |
| | | @ApiResponses(value = { |
| | | @ApiResponse( |
| | | responseCode = ResultCodeMsg.RsCode.SUCCESS_CODE, |
| | | description = "操作结果:true:成功,false:失败(BaseResponse.content)", |
| | | content = {@Content(mediaType = MediaType.APPLICATION_JSON_VALUE, |
| | | schema = @Schema(implementation = Boolean.class))} |
| | | ) |
| | | }) |
| | | @GetMapping(path = "/signAgain") |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @SsoAop() |
| | | public BaseResponse<JSONObject> signAgain(@RequestParam("prepayId") String prepayId) throws Exception { |
| | | |
| | | // 获取随机串和时间戳,放在此处以保证 |
| | | String appid = PayInfo.appid; |
| | | String timestamp = String.valueOf(System.currentTimeMillis() / 1000); |
| | | String nonceStr = payHelper.generateRandomString(); |
| | | String pkg = "prepay_id=" + prepayId; |
| | | String message = payHelper.buildMessage_signAgain(appid, timestamp, nonceStr, pkg); |
| | | String paySign = payHelper.sign(message.getBytes("utf-8"), privateCertFileName); |
| | | |
| | | JSONObject job_result = new JSONObject(); |
| | | job_result.put("timestamp", timestamp); |
| | | job_result.put("nonceStr", nonceStr); |
| | | job_result.put("package", pkg); |
| | | job_result.put("signType", signType); |
| | | job_result.put("paySign", paySign); |
| | | |
| | | return BaseResponseUtils.buildSuccess(job_result) ; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay; |
| | | |
| | | import com.dy.pipIrrGlobal.daoSe.SeVcRechargeMapper; |
| | | import com.dy.pipIrrGlobal.daoSe.SeWebchatLogonStateMapper; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge; |
| | | import com.dy.pipIrrGlobal.pojoSe.SeWebchatLogonState; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:51 |
| | | * @LastEditTime 2024-03-06 13:51 |
| | | * @Description |
| | | */ |
| | | |
| | | @Slf4j |
| | | @Service |
| | | public class PaymentSv { |
| | | @Autowired |
| | | private SeWebchatLogonStateMapper seWebchatLogonStateMapper; |
| | | |
| | | @Autowired |
| | | private SeVcRechargeMapper seVcRechargeMapper; |
| | | |
| | | /** |
| | | * 添加登录态状态记录 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | Long insert(SeWebchatLogonState po) { |
| | | seWebchatLogonStateMapper.insert(po); |
| | | return po.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 根据登录态ID获取登录态对象 |
| | | * @param id |
| | | * @return |
| | | */ |
| | | SeWebchatLogonState selectOne(Long id) { |
| | | return seWebchatLogonStateMapper.selectByPrimaryKey(id); |
| | | } |
| | | |
| | | /** |
| | | * 添加虚拟卡充值记录 |
| | | * @param po |
| | | * @return |
| | | */ |
| | | Long insertVCRecharge(SeVcRecharge po) { |
| | | seVcRechargeMapper.insert(po); |
| | | return po.getId(); |
| | | } |
| | | } |
| File was renamed from pipIrr-platform/pipIrr-web/pipIrr-web-webchat/src/main/java/com/dy/pipirrWebChat/payment/dto/Code2Session.java |
| | |
| | | package com.dy.pipirrWebChat.payment.dto; |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-02-22 15:34 |
| | | * @LastEditTime 2024-02-22 15:34 |
| | | * @date 2024-03-06 13:53 |
| | | * @LastEditTime 2024-03-06 13:53 |
| | | * @Description |
| | | */ |
| | | |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:54 |
| | | * @LastEditTime 2024-03-06 13:54 |
| | | * @Description 下单请求对象,下单时传给JSAPI下单接口 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "下单请求对象") |
| | | public class DtoOrder { |
| | | public static final long serialVersionUID = 202403012108001L; |
| | | |
| | | /** |
| | | * 登录态ID,用来获取openID |
| | | */ |
| | | @Schema(description = "登录态ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "登录态ID不能为空") |
| | | private String sessionId; |
| | | |
| | | /** |
| | | * 虚拟卡编号,外键,用来获取虚拟卡余额 |
| | | */ |
| | | @Schema(description = "虚拟卡编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚拟卡编号不能为空") |
| | | private Long virtualId; |
| | | |
| | | /** |
| | | * 充值金额金额 |
| | | */ |
| | | @Schema(description = "支付金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "虚支付金额不能为空") |
| | | private Integer rechargeAmount; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:54 |
| | | * @LastEditTime 2024-03-06 13:54 |
| | | * @Description 支付和退款通知接收对象 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "支付和退款回调对象") |
| | | public class OrderNotify { |
| | | public static final long serialVersionUID = 202402291431001L; |
| | | |
| | | /** |
| | | * 通知ID |
| | | */ |
| | | private String id; |
| | | |
| | | /** |
| | | * 通知创建时间 |
| | | */ |
| | | private String create_time; |
| | | |
| | | /** |
| | | * 通知类型 |
| | | * 支付成功通知的类型为:TRANSACTION.SUCCESS |
| | | */ |
| | | private String event_type; |
| | | |
| | | /** |
| | | * 通知数据类型 |
| | | * 支付成功通知为:encrypt-resource |
| | | */ |
| | | private String resource_type; |
| | | |
| | | /** |
| | | * 通知数据 |
| | | */ |
| | | private NotifyResource resource; |
| | | |
| | | /** |
| | | * 回调摘要,退款通知无此属性 |
| | | */ |
| | | private String summary; |
| | | |
| | | |
| | | @Data |
| | | public class NotifyResource { |
| | | |
| | | /** |
| | | * 加密算法类型 |
| | | * 仅支持AEAD_AES_256_GCM |
| | | */ |
| | | private String algorithm; |
| | | |
| | | /** |
| | | * 数据密文 |
| | | */ |
| | | private String ciphertext; |
| | | |
| | | /** |
| | | * 附加数据 |
| | | */ |
| | | public String associated_data; |
| | | |
| | | /** |
| | | * 原始类型 |
| | | * 原始回调类型为:transaction |
| | | */ |
| | | private String original_type; |
| | | |
| | | /** |
| | | * 随机串 |
| | | */ |
| | | private String nonce; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Positive; |
| | | import lombok.Data; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-07 21:56 |
| | | * @LastEditTime 2024-03-07 21:56 |
| | | * @Description 订单对象,从充值表中取出的订单信息 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "订单对象") |
| | | public class Orders { |
| | | public static final long serialVersionUID = 202403072157001L; |
| | | |
| | | /** |
| | | * 订单号 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 充值金额 |
| | | */ |
| | | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值金额不能为空") |
| | | @Positive(message = "充值金额必须为大于0的整数") |
| | | private Integer rechargeAmount; |
| | | |
| | | /** |
| | | * 充值完成时间 |
| | | */ |
| | | @Schema(description = "充值完成时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "充值完成时间不能为空") |
| | | private Date rechargeTime; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:55 |
| | | * @LastEditTime 2024-03-06 13:55 |
| | | * @Description 退款请求对象,小程序调用接口时传参所用对象 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "退款请求对象") |
| | | public class Refund { |
| | | public static final long serialVersionUID = 202403011607001L; |
| | | |
| | | /** |
| | | * 商户订单号 |
| | | */ |
| | | @Schema(description = "商户订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "商户订单号不能为空") |
| | | private String tradeNo; |
| | | |
| | | /** |
| | | * 退款单号 |
| | | */ |
| | | @Schema(description = "退款单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private String refundNo; |
| | | |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | private Integer refund; |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:55 |
| | | * @LastEditTime 2024-03-06 13:55 |
| | | * @Description 退款请求对象,对象赋值完整后向微信请求退款 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "退款请求对象") |
| | | public class RefundRequest { |
| | | public static final long serialVersionUID = 202403011540001L; |
| | | |
| | | /** |
| | | * 商户订单号,下单时的订单号 |
| | | */ |
| | | @Schema(description = "商户订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "商户订单号不能为空") |
| | | private String out_trade_no; |
| | | |
| | | /** |
| | | * 商户退款单号,订单号前加前缀“R” |
| | | */ |
| | | @Schema(description = "商户退款单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "商户退款单号不能为空") |
| | | private String out_refund_no; |
| | | |
| | | /** |
| | | * 退款结果回调url,refundUrl |
| | | */ |
| | | @Schema(description = "退款结果回调url", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "退款结果回调url不能为空") |
| | | private String notify_url; |
| | | |
| | | /** |
| | | * 金额信息 |
| | | */ |
| | | @Schema(description = "金额信息", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | private Amount amount; |
| | | |
| | | @Data |
| | | public static class Amount { |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | private Integer refund; |
| | | |
| | | /** |
| | | * 原订单金额,根据订单号查询 |
| | | */ |
| | | @Schema(description = "原订单金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "原订单金额不能为空") |
| | | private Integer total; |
| | | |
| | | /** |
| | | * 退款币种,固定为“CNY” |
| | | */ |
| | | @Schema(description = "退款币种", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "退款币种不能为空") |
| | | private String currency; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-06 13:56 |
| | | * @LastEditTime 2024-03-06 13:56 |
| | | * @Description 退款申请返回的对象 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "退款申请返回对象") |
| | | public class RefundResponse { |
| | | public static final long serialVersionUID = 202403011431001L; |
| | | |
| | | /** |
| | | * 微信支付退款号 |
| | | */ |
| | | private String refund_id; |
| | | |
| | | /** |
| | | * 商户退款单号 |
| | | */ |
| | | private String out_refund_no; |
| | | |
| | | /** |
| | | * 微信支付订单号 |
| | | */ |
| | | private String transaction_id; |
| | | |
| | | /** |
| | | * 商户订单号 |
| | | */ |
| | | private String out_trade_no; |
| | | |
| | | /** |
| | | * 退款渠道 |
| | | */ |
| | | private String channel; |
| | | |
| | | /** |
| | | * 退款入账账户 |
| | | */ |
| | | private String user_received_account; |
| | | |
| | | /** |
| | | * 退款成功时间 |
| | | */ |
| | | private String success_time; |
| | | |
| | | /** |
| | | * 退款创建时间 |
| | | */ |
| | | private String create_time; |
| | | |
| | | /** |
| | | * 退款状态 |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * 金额信息 |
| | | */ |
| | | private Amount amount; |
| | | |
| | | |
| | | @Data |
| | | private static class Amount { |
| | | |
| | | /** |
| | | * 订单总金额 |
| | | */ |
| | | private Integer total; |
| | | |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | private Integer refund; |
| | | |
| | | /** |
| | | * 用户支付金额 |
| | | */ |
| | | private Integer payer_total; |
| | | |
| | | /** |
| | | * 用户退款金额 |
| | | */ |
| | | private Integer payer_refund; |
| | | |
| | | /** |
| | | * 应结退款金额 |
| | | */ |
| | | private Integer settlement_refund; |
| | | |
| | | /** |
| | | * 应结订单金额 |
| | | */ |
| | | private Integer settlement_total; |
| | | |
| | | /** |
| | | * 优惠退款金额 |
| | | */ |
| | | private Integer discount_refund; |
| | | |
| | | /** |
| | | * 退款币种 |
| | | */ |
| | | private String currency; |
| | | |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.dy.pipIrrSell.wechatpay.dto; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Positive; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author ZhuBaoMin |
| | | * @date 2024-03-07 21:43 |
| | | * @LastEditTime 2024-03-07 21:43 |
| | | * @Description 待退款对象,用户选择一个虚拟卡退款时,系统遍历出一个退款对象列表,由多个订单共同完成退款 |
| | | */ |
| | | |
| | | @Data |
| | | @Schema(name = "待退款对象") |
| | | public class ToRefund { |
| | | public static final long serialVersionUID = 202403072144001L; |
| | | |
| | | /** |
| | | * 订单号 |
| | | */ |
| | | @Schema(description = "订单号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotBlank(message = "订单号不能为空") |
| | | private String orderNumber; |
| | | |
| | | /** |
| | | * 退款金额 |
| | | */ |
| | | @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) |
| | | @NotNull(message = "退款金额不能为空") |
| | | @Positive(message = "退款金额必须为大于0的整数") |
| | | private Integer refundAmount; |
| | | } |
| | |
| | | <module>pipIrr-web-gis</module> |
| | | <module>pipIrr-web-sell</module> |
| | | <module>pipIrr-web-project</module> |
| | | <module>pipIrr-web-webchat</module> |
| | | </modules> |
| | | |
| | | <dependencies> |