pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/webFilter/WXDataSourceNameSetFilter.java
@@ -22,6 +22,9 @@ @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { String ds = DataSourceContext.get(); System.out.println(ds); HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; String wxDataSourceName = httpRequest.getHeader("tag"); if(wxDataSourceName != null && wxDataSourceName.trim().length() > 0){ @@ -30,6 +33,7 @@ DataSourceContext.set(wxDataSourceName); } else { log.info("用户未选择数据源"); DataSourceContext.set("ym"); } filterChain.doFilter(servletRequest, servletResponse); pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java
@@ -143,7 +143,7 @@ */ protected RmCommandHistory getComHistory(Long comId, String commandCode, String commandName, Long intakeId, String rtuAddr, String protocol, Object param, Long operator ) { RmCommandHistory rmCommandHistory = new RmCommandHistory(); rmCommandHistory.setId(comId); rmCommandHistory.setComId(comId); rmCommandHistory.setCommandCode(commandCode); //rmCommandHistory.setCommandName(CodeV202404.getCodeName(commandCode)); rmCommandHistory.setCommandName(commandName); @@ -259,13 +259,13 @@ // 创建命令日志对象并添加到数据库中 RmCommandHistory rmCommandHistory = getComHistory(comId, commandCode, commandName, intakeId, rtuAddr, protocol, param, operator); rmCommandHistoryMapper.insert(rmCommandHistory); comId = rmCommandHistory.getId(); comId = rmCommandHistory.getComId(); // 回调异常 if(!response_CallBack.getCode().equals("0001")) { // 命令日志执行结果改为失败 rmCommandHistory = new RmCommandHistory(); rmCommandHistory.setId(comId); rmCommandHistory.setComId(comId); rmCommandHistory.setResult((byte)0); rmCommandHistoryMapper.updateByPrimaryKeySelective(rmCommandHistory); return BaseResponseUtils.buildErrorMsg(response_CallBack.getContent().toString()); @@ -280,7 +280,7 @@ */ rmCommandHistory = new RmCommandHistory(); rmCommandHistory.setId(comId); rmCommandHistory.setComId(comId); rmCommandHistory.setResult((byte) 0); rmCommandHistoryMapper.updateByPrimaryKeySelective(rmCommandHistory); return BaseResponseUtils.buildErrorMsg(CommandResultCode.GET_RESULT_IN_ONE_MINUTE.getMessage()); @@ -298,7 +298,7 @@ * 更新执行结果、返回结果时间、结果内容 */ rmCommandHistory = new RmCommandHistory(); rmCommandHistory.setId(comId); rmCommandHistory.setComId(comId); rmCommandHistory.setResult((byte)0); rmCommandHistory.setResultTime(new Date()); rmCommandHistory.setResultText((JSONObject)JSON.toJSON(response_CallBack.getContent())); @@ -330,7 +330,7 @@ // 更新命令日志:执行结果、返回结果时间、结果内容 rmCommandHistory = new RmCommandHistory(); rmCommandHistory.setId(comId); rmCommandHistory.setComId(comId); rmCommandHistory.setResult((byte)1); rmCommandHistory.setResultTime(new Date()); rmCommandHistory.setResultText((JSONObject)JSON.toJSON(myData)); pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoRm/RmCommandHistory.java
@@ -40,7 +40,7 @@ */ @JSONField(serializeUsing = ObjectWriterImplToString.class) @TableId(type = IdType.INPUT) private Long id; private Long comId; /** * 功能码 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoCommand.java
@@ -19,7 +19,7 @@ private static final long serialVersionUID = 1L; @JSONField(serializeUsing= ObjectWriterImplToString.class) private Long id; private Long comId; private String commandName; pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoUnclosedValve.java
@@ -3,8 +3,6 @@ import com.dy.common.po.BaseEntity; import lombok.Data; import java.util.Date; /** * @author ZhuBaoMin * @date 2024-05-24 16:30 @@ -16,7 +14,7 @@ public class VoUnclosedValve implements BaseEntity { private static final long serialVersionUID = 202405241634001L; private String commandCode; //private String commandCode; private String intakeNum; @@ -28,5 +26,5 @@ private String vcNum; private Date openTime; //private Date openTime; } pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voSe/VoVirtualCard.java
@@ -1,5 +1,7 @@ package com.dy.pipIrrGlobal.voSe; import com.alibaba.fastjson2.annotation.JSONField; import com.alibaba.fastjson2.writer.ObjectWriterImplToString; import com.dy.common.po.BaseEntity; import lombok.Data; @@ -14,9 +16,11 @@ public class VoVirtualCard implements BaseEntity { private static final long serialVersionUID = 202405240815001L; private String id; @JSONField(serializeUsing= ObjectWriterImplToString.class) private Long id; private String vcNum; @JSONField(serializeUsing= ObjectWriterImplToString.class) private Long vcNum; private Double money; pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml
@@ -6,8 +6,8 @@ type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver # url: jdbc:mysql://192.168.40.166:3306/pipIrr_sp?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull # url: jdbc:mysql://127.0.0.1:3306/pipIrr_sp?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull url: jdbc:mysql://8.140.179.55:3306/pipIrr_sp?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull url: jdbc:mysql://127.0.0.1:3306/pipIrr_sp?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull # url: jdbc:mysql://8.140.179.55:3306/pipIrr_sp?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull username: root password: dysql,;.abc!@# druid: pipIrr-platform/pipIrr-global/src/main/resources/application-database-ym.yml
@@ -5,8 +5,8 @@ #name: ym type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.40.166:3306/pipIrr_ym?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull # url: jdbc:mysql://127.0.0.1:3306/pipIrr_ym?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull # url: jdbc:mysql://192.168.40.166:3306/pipIrr_ym?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull url: jdbc:mysql://127.0.0.1:3306/pipIrr_ym?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull # url: jdbc:mysql://8.140.179.55:3306/pipIrr_ym?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull username: root password: dysql,;.abc!@# pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmCommandHistoryMapper.xml
@@ -4,7 +4,7 @@ <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoRm.RmCommandHistory"> <!--@mbg.generated--> <!--@Table rm_command_history--> <id column="id" jdbcType="BIGINT" property="id" /> <id column="com_id" jdbcType="BIGINT" property="comId" /> <result column="command_code" jdbcType="VARCHAR" property="commandCode" /> <result column="command_name" jdbcType="VARCHAR" property="commandName" /> <result column="intake_id" jdbcType="BIGINT" property="intakeId" /> @@ -19,7 +19,7 @@ </resultMap> <sql id="Base_Column_List"> <!--@mbg.generated--> id, command_code, command_name, intake_id, rtu_addr, protocol, param, send_time, `operator`, com_id, command_code, command_name, intake_id, rtu_addr, protocol, param, send_time, `operator`, `result`, result_time, result_text </sql> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> @@ -27,20 +27,20 @@ select <include refid="Base_Column_List" /> from rm_command_history where id = #{id,jdbcType=BIGINT} where com_id = #{id,jdbcType=BIGINT} </select> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> <!--@mbg.generated--> delete from rm_command_history where id = #{id,jdbcType=BIGINT} where com_id = #{id,jdbcType=BIGINT} </delete> <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandHistory"> <!--@mbg.generated--> insert into rm_command_history (id, command_code, command_name, insert into rm_command_history (com_id, command_code, command_name, intake_id, rtu_addr, protocol, param, send_time, `operator`, `result`, result_time, result_text) values (#{id,jdbcType=BIGINT}, #{commandCode,jdbcType=VARCHAR}, #{commandName,jdbcType=VARCHAR}, #{intakeId,jdbcType=BIGINT}, values (#{comId,jdbcType=BIGINT}, #{commandCode,jdbcType=VARCHAR}, #{commandName,jdbcType=VARCHAR}, #{intakeId,jdbcType=BIGINT}, #{rtuAddr,jdbcType=VARCHAR}, #{protocol,jdbcType=VARCHAR}, #{param,jdbcType= JAVA_OBJECT, typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler}, #{sendTime,jdbcType=TIMESTAMP}, #{operator,jdbcType=BIGINT}, #{result,jdbcType=TINYINT}, #{resultTime,jdbcType=TIMESTAMP}, #{resultText,jdbcType= JAVA_OBJECT, typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler}) @@ -49,8 +49,8 @@ <!--@mbg.generated--> insert into rm_command_history <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null"> id, <if test="comId != null"> com_id, </if> <if test="commandCode != null"> command_code, @@ -87,8 +87,8 @@ </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null"> #{id,jdbcType=BIGINT}, <if test="comId != null"> #{comId,jdbcType=BIGINT}, </if> <if test="commandCode != null"> #{commandCode,jdbcType=VARCHAR}, @@ -163,7 +163,7 @@ result_text = #{resultText,jdbcType= JAVA_OBJECT, typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler}, </if> </set> where id = #{id,jdbcType=BIGINT} where com_id = #{comId,jdbcType=BIGINT} </update> <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandHistory"> <!--@mbg.generated--> @@ -179,19 +179,17 @@ `result` = #{result,jdbcType=TINYINT}, result_time = #{resultTime,jdbcType=TIMESTAMP}, result_text = #{resultText,jdbcType= JAVA_OBJECT, typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler} where id = #{id,jdbcType=BIGINT} where com_id = #{comId,jdbcType=BIGINT} </update> <!--根据操作员ID获取未关阀记录(包含在线情况)--> <select id="getUnclosedValves" resultType="com.dy.pipIrrGlobal.voRm.VoUnclosedValve"> SELECT com.command_code AS commandCode, inta.name AS intakeNum, rtus.isOnLine, com.rtu_addr AS rtuAddr, com.param ->>'$.orderNo' AS orderNo, com.param ->>'$.icCardNo' AS vcNum, com.send_time AS openTime (SELECT param ->>'$.orderNo' AS orderNo FROM rm_command_history WHERE rtu_addr = com.rtu_addr ORDER BY send_time desc LIMIT 0,1) AS orderNo FROM rm_command_history com INNER JOIN pr_controller con ON com.rtu_addr = con.rtuAddr INNER JOIN pr_intake inta ON con.intakeId = inta.id @@ -214,7 +212,7 @@ AND param ->>'$.orderNo' = com.param ->>'$.orderNo' ) </where> ORDER BY com.send_time DESC GROUP BY inta.name, rtus.isOnLine, com.rtu_addr, com.param ->>'$.icCardNo' </select> <!--根据取水口ID获取该取水口未关阀参数--> @@ -270,7 +268,7 @@ <!--根据指定条件获取命令日志历史记录--> <select id="getCommandHistories" resultType="com.dy.pipIrrGlobal.voRm.VoCommand"> SELECT his.id, his.com_id AS comId, his.command_name AS commandName, inta.name AS intakeName, his.rtu_addr AS rtuAddr, pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientMapper.xml
@@ -396,7 +396,7 @@ <!--根据农户编号获取5级行政区划串areaCode,补卡过程中开新卡使用--> <select id="getAreaCodeById" resultType="java.lang.Long"> SELECT districtNum FROM se_client WHERE id = ${clientId} SELECT districtNum FROM se_client WHERE id = #{clientId} </select> <!--根据农户编号获取农户ID--> pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeVirtualCardMapper.xml
@@ -170,7 +170,8 @@ <!--获取农户全部虚拟卡--> <select id="getVCs" resultType="com.dy.pipIrrGlobal.voSe.VoVirtualCard"> SELECT CAST(id AS char) AS id, <!-- CAST(id AS char) AS id,--> id, vc_num AS vcNum, money, in_use AS inUse, @@ -190,7 +191,7 @@ <!--根据虚拟卡ID获取虚拟卡对象--> <select id="getVcById" resultType="com.dy.pipIrrGlobal.voSe.VoVirtualCard"> SELECT CAST(id AS char) AS id, id, vc_num AS vcNum, money, in_use AS inUse, pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java
@@ -95,7 +95,7 @@ */ public Long insert(RmCommandHistory po) { rmCommandHistoryMapper.insert(po); return po.getId(); return po.getComId(); } /** pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java
@@ -145,7 +145,7 @@ ComCd92_A2Vo param = new ComCd92_A2Vo(); param.controllerType = controllerType; param.projectNo = projectNo; param.icCardNo = vc.getVcNum(); param.icCardNo = vc.getVcNum().toString(); param.waterRemain = 0.0; param.moneyRemain = vc.getMoney(); param.waterPrice = waterPrice; @@ -176,7 +176,7 @@ // 创建视图 Com97Vo param = new Com97Vo() ; param.icCardNo = vc.getVcNum(); param.icCardNo = vc.getVcNum().toString(); param.moneyRemain = vc.getMoney(); param.waterPrice = waterPrice; param.orderNo = orderNo; pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/wechatpay/PayInfo.java
@@ -38,10 +38,10 @@ */ public static String certificates = "https://api.mch.weixin.qq.com/v3/certificates"; /* /** * 支付结果通知API */ public static String notifyUrl = "https://44978f7456.imdo.co/sell/payment/orderNotify"; public static String notifyUrl = "https://44978f7456.imdo.co/wx/payment/orderNotify"; /* * 查询订单API pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java
@@ -145,7 +145,7 @@ */ public Long insert(RmCommandHistory po) { rmCommandHistoryMapper.insert(po); return po.getId(); return po.getComId(); } /** pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java
@@ -159,7 +159,7 @@ ComCd92_A2Vo param = new ComCd92_A2Vo(); param.controllerType = controllerType; param.projectNo = projectNo; param.icCardNo = vc.getVcNum(); param.icCardNo = vc.getVcNum().toString(); param.waterRemain = 0.0; param.moneyRemain = vc.getMoney(); param.waterPrice = waterPrice; @@ -191,7 +191,7 @@ // 创建视图 Com97Vo param = new Com97Vo(); param.icCardNo = vc.getVcNum(); param.icCardNo = vc.getVcNum().toString(); param.moneyRemain = vc.getMoney(); param.waterPrice = waterPrice; param.orderNo = orderNo; pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java
@@ -49,6 +49,7 @@ /** * 虚拟卡 */ AREA_CODE_MISTAKE(10001, "该农户行政区划异常"), ABNORMAL(10001, "退款异常"), PROCESSING(10001, "退款处理中"), VC_OPEN_ACCOUNT_FAIL(90002, "虚拟卡账户注册失败"), @@ -56,7 +57,14 @@ VIRTUAL_CARD_NOT_EXIST(90006, "虚拟卡账户不存在"), RECHARGE_NOT_EXIST(90006, "充值记录不存在"), RECHARGE_FAIL(90006, "充值失败"), NO_ACCOUNT(40001, "您指定的虚拟卡未注册"); RECHARGE_ADD_FAIL(10001, "充值记录添加失败"), NO_ACCOUNT(40001, "您指定的虚拟卡未注册"), VIRTUAL_CARD_CLIENT_NOT_EXIST(40001, "虚拟卡所属农户不存在"), /** * 位置支付 */ SESSION_ID_ERROR(50001, "登录态ID错误"); private final Integer code; private final String message; pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/SeClientToVoClient.java
New file @@ -0,0 +1,29 @@ package com.dy.pipIrrWechat.virtualCard; import com.dy.pipIrrGlobal.pojoSe.SeClient; import com.dy.pipIrrGlobal.voSe.VoClient; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; /** * @author ZhuBaoMin * @date 2023-12-25 15:54 * @LastEditTime 2023-12-25 15:54 * @Description */ @Mapper public interface SeClientToVoClient { SeClientToVoClient INSTANCT = Mappers.getMapper(SeClientToVoClient.class); @Mapping(target = "name", source = "name") @Mapping(target = "clientNum", source = "clientnum") @Mapping(target = "phone", source = "phone") @Mapping(target = "idCard", source = "idcard") //@Mapping(target = "cardCount", source = "cardCount") @Mapping(target = "address", source = "address") @Mapping(target = "operateDt", source = "operatedt") @Mapping(target = "typeId", source = "typeid") VoClient po2vo(SeClient po); } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java
@@ -1,17 +1,16 @@ package com.dy.pipIrrWechat.virtualCard; import com.dy.common.aop.SsoAop; import com.dy.common.webUtil.BaseResponse; import com.dy.common.webUtil.BaseResponseUtils; import com.dy.common.webUtil.QueryResultVo; import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; import com.dy.pipIrrGlobal.voSe.VoVcRecharge; import com.dy.pipIrrGlobal.voSe.VoVirtualCard; import com.dy.pipIrrWechat.util.PayHelper; import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM; import com.dy.pipIrrWechat.result.WechatResultCode; import com.dy.pipIrrWechat.util.PayHelper; import com.dy.pipIrrWechat.virtualCard.dto.DtoRegist; import com.dy.pipIrrWechat.virtualCard.dto.DtoVcRecharge; import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -43,53 +42,25 @@ private final PayHelper payHelper; /** * 获取农户全部虚拟卡 * @return */ @GetMapping(path = "/get") @SsoAop() public BaseResponse<List<VoVirtualCard>> getVCs(Long clientId){ try { List<VoVirtualCard> res = virtualCardSv.getVCs(clientId); return BaseResponseUtils.buildSuccess(res); } catch (Exception e) { log.error("获取支付方式记录异常", e); return BaseResponseUtils.buildException(e.getMessage()) ; } } /** * 根据虚拟卡ID获取虚拟卡对象 * @param vcId * @return */ @GetMapping(path = "/getVcById") @SsoAop() public BaseResponse<VoVirtualCard> getVcById(@RequestParam Long vcId){ try { return BaseResponseUtils.buildSuccess(virtualCardSv.getVcById(vcId)); } catch (Exception e) { log.error("获取支付方式记录异常", e); return BaseResponseUtils.buildException(e.getMessage()) ; } } /** * 虚拟卡账号注册 * 注册虚拟卡 * @param po * @param bindingResult * @return */ @PostMapping(path = "add_vc") @SsoAop() public BaseResponse<Boolean> addVC(@RequestBody @Valid DtoRegist po, BindingResult bindingResult){ public BaseResponse<Boolean> addVC(@RequestBody @Valid DtoRegist po, BindingResult bindingResult) { if(bindingResult != null && bindingResult.hasErrors()){ return BaseResponseUtils.buildFail(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); } Long clientId = po.getClientId(); // 获取5级行政区划串areaCode String areaCode = String.valueOf(virtualCardSv.getAreaCodeById(clientId)); Long areaCodeL = virtualCardSv.getAreaCodeById(clientId); if(areaCodeL == null) { return BaseResponseUtils.buildErrorMsg(WechatResultCode.AREA_CODE_MISTAKE.getMessage()); } String areaCode = String.valueOf(areaCodeL); /** * 根据行政区划串(areaCode)在虚拟卡表中针对虚拟卡编号(vcNum)进行模糊查询 * 如果5位顺序号已经达到最大值,提示用户联系系统管理员 @@ -101,7 +72,7 @@ Integer number = Integer.parseInt(vcNum.substring(12)); number = number + 1; if(number > 65535) { return BaseResponseUtils.buildFail(WechatResultCode.CARD_NUMBER_OVERRUN.getMessage()); return BaseResponseUtils.buildErrorMsg(WechatResultCode.CARD_NUMBER_OVERRUN.getMessage()); } vcNum = vcNum.substring(0, 12) + String.format("%05d", number); } else { @@ -118,9 +89,38 @@ seVirtualCard.setCreateTime(new Date()); Long rec = virtualCardSv.insertVirtualCard(seVirtualCard); if(rec == null) { return BaseResponseUtils.buildFail(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage()); return BaseResponseUtils.buildErrorMsg(WechatResultCode.VC_OPEN_ACCOUNT_FAIL.getMessage()); } return BaseResponseUtils.buildSuccess(true) ; } /** * 获取农户全部虚拟卡 * @return */ @GetMapping(path = "/get") public BaseResponse<List<VoVirtualCard>> getVCs(Long clientId){ try { return BaseResponseUtils.buildSuccess(virtualCardSv.getVCs(clientId)); } catch (Exception e) { log.error("获取支付方式记录异常", e); return BaseResponseUtils.buildException(e.getMessage()) ; } } /** * 根据虚拟卡ID获取虚拟卡对象 * @param vcId * @return */ @GetMapping(path = "/getVcById") public BaseResponse<VoVirtualCard> getVcById(@RequestParam Long vcId){ try { return BaseResponseUtils.buildSuccess(virtualCardSv.getVcById(vcId)); } catch (Exception e) { log.error("获取支付方式记录异常", e); return BaseResponseUtils.buildException(e.getMessage()) ; } } /** @@ -140,7 +140,6 @@ //}) //@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()); @@ -198,7 +197,6 @@ //}) //@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()); @@ -256,7 +254,6 @@ * @return */ @GetMapping(path = "/getVcRechargeRecords") @SsoAop() public BaseResponse<QueryResultVo<List<VoVcRecharge>>> getVcRechargeRecords(DtoVcRecharge dtoVcRecharge){ try { QueryResultVo<List<VoVcRecharge>> res = virtualCardSv.getVcRechargeRecords(dtoVcRecharge); pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PayInfo.java
@@ -38,10 +38,10 @@ */ public static String certificates = "https://api.mch.weixin.qq.com/v3/certificates"; /* /** * 支付结果通知API */ public static String notifyUrl = "https://44978f7456.imdo.co/sell/payment/orderNotify"; public static String notifyUrl = "https://44978f7456.imdo.co/wx/payment/orderNotify"; /* * 查询订单API pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PaymentCtrl.java
New file @@ -0,0 +1,511 @@ package com.dy.pipIrrWechat.wechatpay; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.dy.common.webUtil.BaseResponse; import com.dy.common.webUtil.BaseResponseUtils; import com.dy.common.webUtil.ResultCodeMsg; import com.dy.pipIrrGlobal.pojoSe.*; import com.dy.pipIrrGlobal.voSe.VoClient; import com.dy.pipIrrWechat.result.WechatResultCode; import com.dy.pipIrrWechat.util.AesUtil; import com.dy.pipIrrWechat.util.PayHelper; import com.dy.pipIrrWechat.util.RestTemplateUtil; import com.dy.pipIrrWechat.virtualCard.VirtualCardSv; import com.dy.pipIrrWechat.virtualCard.dto.DtoVirtualCard; import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM; import com.dy.pipIrrWechat.virtualCard.enums.RefundItemStateENUM; import com.dy.pipIrrWechat.wechatpay.dto.Code2Session; import com.dy.pipIrrWechat.wechatpay.dto.DtoOrder; import com.dy.pipIrrWechat.wechatpay.dto.NotifyResource; import com.dy.pipIrrWechat.wechatpay.dto.OrderNotify; import com.dy.pipIrrWechat.wechatpay.enums.RefundStatusENUM; 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.HttpServletRequest; 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.BufferedReader; 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-07-16 15:05 * @LastEditTime 2024-07-16 15:05 * @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 String privateCertFileName = com.dy.pipIrrWechat.wechatpay.PayInfo.privateCertFileName; private final String appid = com.dy.pipIrrWechat.wechatpay.PayInfo.appid; private final String secret = com.dy.pipIrrWechat.wechatpay.PayInfo.secret; private final String mchid = com.dy.pipIrrWechat.wechatpay.PayInfo.mchid; private final String schema = com.dy.pipIrrWechat.wechatpay.PayInfo.schema; private final String signType = com.dy.pipIrrWechat.wechatpay.PayInfo.signType; private final String description = com.dy.pipIrrWechat.wechatpay.PayInfo.description; private final String loginUrl = com.dy.pipIrrWechat.wechatpay.PayInfo.loginUrl; private final String notifyUrl = com.dy.pipIrrWechat.wechatpay.PayInfo.notifyUrl; private final String grantType = com.dy.pipIrrWechat.wechatpay.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) 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()); } String phoneNumber = code2Session.getPhoneNumber(); String jsCode = code2Session.getJs_code(); Map<String, Object> queryParams = new HashMap<>(); queryParams.put("appid", appid); queryParams.put("secret", secret); queryParams.put("js_code", jsCode); 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"); Long clientId = paymentSv.getClientIdByPhone(phoneNumber); String SessionId = ""; if(clientId != null) { // 添加微信用户账户记录 SeOpenId seOpenId = new SeOpenId(); seOpenId.setClientId(clientId); seOpenId.setOpenId(openid); seOpenId.setSessionKey(sessionKey); seOpenId.setCreateTime(new Date()); Long rec = paymentSv.addOpenId(seOpenId); if(rec != null) { SessionId = String.valueOf(rec); } return BaseResponseUtils.buildSuccess(SessionId); } else { return BaseResponseUtils.buildError(WechatResultCode.PHONE_NUMBER_IS_ERROR.getMessage()); } } /** * 下载微信支付平台证书 测试完废除 * @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) 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(com.dy.pipIrrWechat.wechatpay.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 预支付交易会话标识(有效期2小时) */ @PostMapping(path = "placeOrder") @Transactional(rollbackFor = Exception.class) 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、充值金额(分) Long sessionId = order.getSessionId(); Long virtualId = order.getVcId(); Integer rechargeAmount = order.getRechargeAmount(); String prepayId = ""; SeOpenId po = paymentSv.selectOne(sessionId); if(po == null) { return BaseResponseUtils.buildErrorMsg(WechatResultCode.SESSION_ID_ERROR.getMessage()); } String openid = po.getOpenId(); SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); if(seVirtualCard == null) { return BaseResponseUtils.buildErrorMsg(WechatResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage()); } Long clientId = seVirtualCard.getClientId(); VoClient voClient = paymentSv.getOneClient(clientId); if(voClient == null) { return BaseResponseUtils.buildErrorMsg(WechatResultCode.VIRTUAL_CARD_CLIENT_NOT_EXIST.getMessage()); } String clientNum = voClient.getClientNum(); // 生成订单号并添加充值记录 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String orderNumber = clientNum + dateFormat.format(new Date()); // 生成虚拟卡充值记录(部分字段) DtoVirtualCard virtualCard = new DtoVirtualCard(); virtualCard.setVirtualId(virtualId); virtualCard.setClientId(clientId); virtualCard.setOrderNumber(orderNumber); virtualCard.setRechargeAmount(rechargeAmount); BaseResponse result = virtualCardSv.insertVCRecharge(virtualCard); if(!result.getCode().equals("0001")) { return BaseResponseUtils.buildErrorMsg(WechatResultCode.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", rechargeAmount); 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(com.dy.pipIrrWechat.wechatpay.PayInfo.orderUrl, body, headers); if(job_result == null) { return BaseResponseUtils.buildFail(WechatResultCode.RECHARGE_ADD_FAIL.getMessage()); } return BaseResponseUtils.buildSuccess(job_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) public BaseResponse<JSONObject> signAgain(@RequestParam("prepayId") String prepayId) throws Exception { // 获取随机串和时间戳,放在此处以保证 String appid = com.dy.pipIrrWechat.wechatpay.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) ; } /** * 支付通知/退款结果通知 * @param headers * @param request * @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) public JSONObject orderNotify(@RequestHeader HttpHeaders headers, HttpServletRequest request, HttpServletResponse response) throws IOException, GeneralSecurityException { JSONObject result = new JSONObject(); /** * 1.验签处理 * 从header中取出4个子参数 * 验时间差,超过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)); // 获取body内容 BufferedReader reader = request.getReader(); StringBuilder stringBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } String bodyStr = stringBuilder.toString(); // body转对象 OrderNotify orderNotify = JSON.parseObject(bodyStr, OrderNotify.class); // 验时间戳,时间差大于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; } // 解密处理 String eventType = orderNotify.getEvent_type(); if(eventType != null && eventType.equals("TRANSACTION.SUCCESS")) { // 支付成功回调 /** * 支付成功的回调 * 取出通知数据对象,继而取出解密所需的associatedData和nonce,以及密文ciphertext * 解密ciphertext得到 */ NotifyResource notifyResource = orderNotify.getResource(); String associatedData = notifyResource.getAssociated_data(); String nonce = notifyResource.getNonce(); String ciphertext = notifyResource.getCiphertext(); String resource = AesUtil.decryptToString(com.dy.pipIrrWechat.wechatpay.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"); // 如果当前订单状态为未支付状态,则更新虚拟卡表及充值表响应字段 SeVcRecharge seVcRecharge = virtualCardSv.getVCRechargeByorderNumber(out_trade_no); if(seVcRecharge != null && seVcRecharge.getOrderState() == 1) { 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得到 */ 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; } } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PaymentSv.java
New file @@ -0,0 +1,83 @@ package com.dy.pipIrrWechat.wechatpay; import com.dy.pipIrrGlobal.daoSe.SeClientMapper; import com.dy.pipIrrGlobal.daoSe.SeOpenIdMapper; import com.dy.pipIrrGlobal.daoSe.SeVcRechargeMapper; import com.dy.pipIrrGlobal.pojoSe.SeClient; import com.dy.pipIrrGlobal.pojoSe.SeOpenId; import com.dy.pipIrrGlobal.pojoSe.SeVcRecharge; import com.dy.pipIrrGlobal.voSe.VoClient; import com.dy.pipIrrWechat.virtualCard.SeClientToVoClient; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author ZhuBaoMin * @date 2024-07-16 15:03 * @LastEditTime 2024-07-16 15:03 * @Description */ @Slf4j @Service public class PaymentSv { @Autowired private SeVcRechargeMapper seVcRechargeMapper; @Autowired private SeOpenIdMapper seOpenIdMapper; @Autowired private SeClientMapper seClientMapper; /** * 根据登录态ID获取登录态对象 * @param sessionId * @return */ SeOpenId selectOne(Long sessionId) { return seOpenIdMapper.selectByPrimaryKey(sessionId); } /** * 添加虚拟卡充值记录 * @param po * @return */ Long insertVCRecharge(SeVcRecharge po) { seVcRechargeMapper.insert(po); return po.getId(); } /** * 根据主键获取农户对象 * @param id 农户主键 * @return 农户对象 */ public VoClient getOneClient(Long id) { SeClient seClient = seClientMapper.selectByPrimaryKey(id); VoClient voClient = SeClientToVoClient.INSTANCT.po2vo(seClient); return voClient; } /** * 根据电话号码获取农户ID * @param phoneNumber * @return */ public Long getClientIdByPhone(String phoneNumber) { return seClientMapper.getClientIdByPhone(phoneNumber); } /** * 添加微信用户账户记录 * @param po * @return */ public Long addOpenId(SeOpenId po) { seOpenIdMapper.insert(po); //return po.getClientId(); return po.getId(); } } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/Code2Session.java
New file @@ -0,0 +1,45 @@ package com.dy.pipIrrWechat.wechatpay.dto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; /** * @author ZhuBaoMin * @date 2024-07-16 15:13 * @LastEditTime 2024-07-16 15:13 * @Description */ @Data @Schema(name = "登录凭证校验传入对象") public class Code2Session { public static final long serialVersionUID = 202402221335001L; /** * 小程序 appId */ @Schema(description = "小程序 appId", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotBlank(message = "小程序 appId不能为空") private String appid; /** * 小程序 appSecret */ @Schema(description = "小程序 appSecret", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotBlank(message = "小程序 appSecret不能为空") private String secret; /** * js_code */ @Schema(description = "js_code", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotBlank(message = "js_code不能为空") private String js_code; /** * 手机号 */ @NotBlank(message = "手机号不能为空") private String phoneNumber; } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/DtoOrder.java
New file @@ -0,0 +1,39 @@ package com.dy.pipIrrWechat.wechatpay.dto; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; /** * @author ZhuBaoMin * @date 2024-07-16 15:14 * @LastEditTime 2024-07-16 15:14 * @Description */ @Data @Schema(name = "下单请求对象") public class DtoOrder { public static final long serialVersionUID = 202403012108001L; /** * 登录态ID,用来获取openID */ @Schema(description = "登录态ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotNull(message = "登录态ID不能为空") private Long sessionId; /** * 虚拟卡ID,用来获取虚拟卡余额 */ @Schema(description = "虚拟卡编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotNull(message = "虚拟卡ID不能为空") private Long vcId; /** * 充值金额金额 */ @Schema(description = "支付金额", requiredMode = Schema.RequiredMode.NOT_REQUIRED) @NotNull(message = "虚支付金额不能为空") private Integer rechargeAmount; } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/NotifyResource.java
New file @@ -0,0 +1,40 @@ package com.dy.pipIrrWechat.wechatpay.dto; import lombok.Data; /** * @author ZhuBaoMin * @date 2024-07-16 15:14 * @LastEditTime 2024-07-16 15:14 * @Description */ @Data public class NotifyResource { /** * 原始类型 * 原始回调类型为:transaction */ private String original_type; /** * 加密算法类型 * 仅支持AEAD_AES_256_GCM */ private String algorithm; /** * 数据密文 */ private String ciphertext; /** * 附加数据 */ public String associated_data; /** * 随机串 */ private String nonce; } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/OrderNotify.java
New file @@ -0,0 +1,50 @@ package com.dy.pipIrrWechat.wechatpay.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** * @author ZhuBaoMin * @date 2024-07-16 15:15 * @LastEditTime 2024-07-16 15:15 * @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; } pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/enums/RefundStatusENUM.java
New file @@ -0,0 +1,21 @@ package com.dy.pipIrrWechat.wechatpay.enums; import lombok.AllArgsConstructor; import lombok.Getter; /** * @author ZhuBaoMin * @date 2024-07-16 15:17 * @LastEditTime 2024-07-16 15:17 * @Description */ @Getter @AllArgsConstructor public enum RefundStatusENUM { NO_REFUND((byte)1, "未退款"), REFUNDED((byte)2, "已退款"); private final Byte code; private final String message; }