From 5e2faddb34e79918b73dc75aca8f63048dd4526d Mon Sep 17 00:00:00 2001 From: liurunyu <lry9898@163.com> Date: 星期一, 15 七月 2024 20:53:33 +0800 Subject: [PATCH] Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV --- pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml | 3 pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java | 26 pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaBlockMapper.xml | 4 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/CardOperateCtrl.java | 8 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java | 26 pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java | 26 pipIrr-platform/pipIrr-global/src/main/resources/application-database-pj.yml | 3 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/dto/ActiveCard.java | 6 pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/client/ClientCtrl.java | 3 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java | 23 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml | 7 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java | 12 pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java | 9 pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeCardOperateMapper.xml | 2 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/AesUtil.java | 50 + pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/Refund.java | 39 + pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/ToRefund.java | 35 + pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeSv.java | 45 pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml | 29 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundRequest.java | 70 ++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java | 15 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java | 508 +++++++++++++++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java | 269 ++++++++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundResponse.java | 114 +++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/HmacSha256.java | 43 + pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PayInfo.java | 176 +++++ pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeCtrl.java | 7 pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java | 352 +++++++++++ pipIrr-platform/pipIrr-global/src/main/resources/application-database-ym.yml | 4 29 files changed, 1,868 insertions(+), 46 deletions(-) diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java index 6275ab9..f35cd89 100644 --- a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/ComSupport.java @@ -19,7 +19,6 @@ import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -46,8 +45,8 @@ */ public class ComSupport { - @Value("${mw.comSendUrl}") - private String comSendUrl; + //@Value("${mw.comSendUrl}") + protected String comSendUrl; protected static String controllerType = null; protected static Integer projectNo = null; @@ -73,6 +72,9 @@ private SeVirtualCardMapper seVirtualCardMapper; public static ComSupport comSupport; + + public ComSupport() { + } /** * 寮曞叆BaSettingsMapper @@ -124,6 +126,7 @@ job_rtu.put("rtuAddr", prController.getRtuAddr()); job_rtu.put("protocol", prController.getProtocol()); job_rtu.put("intakeId", prController.getIntakeId()); + job_rtu.put("orgTag", prController.getOrgTag()); return job_rtu; } diff --git a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java index bbdc3d0..c5c2f24 100644 --- a/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java +++ b/pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoPr/PrIntakeMapper.java @@ -113,14 +113,14 @@ List<Map<String, Object>> getNoBindingIntakes(); /** - * 鑾峰彇鍙栨按鍙f暟閲忥紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛� + * 鑾峰彇鍙栨按鍙f暟閲忥紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛夊簾寮� * @param params * @return */ Long getOnLineIntakesCount(Map<?, ?> params); /** - * 鑾峰彇鍙栨按鍙e垪琛紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛� + * 鑾峰彇鍙栨按鍙e垪琛紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛夊簾寮� * @param params * @return */ @@ -128,6 +128,14 @@ List<VoOnLineIntake> getOnLineIntakes(Map<?, ?> params); /** + * 鏍规嵁鍙栨按鍙g紪鍙疯幏鍙栧彇姘村彛瀵硅薄 + * @param params + * @return + */ + VoOnLineIntake getIntakeByName(Map<?, ?> params); + + + /** * 鏍规嵁鎿嶄綔鍛樿幏鍙栧父鐢ㄥ彇姘村彛 * @return */ diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-pj.yml b/pipIrr-platform/pipIrr-global/src/main/resources/application-database-pj.yml index c564354..76dece8 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-pj.yml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/application-database-pj.yml @@ -6,7 +6,8 @@ type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver # url: jdbc:mysql://192.168.40.166:3306/pipIrr_pj?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull - url: jdbc:mysql://8.140.179.55:3306/pipIrr_pj?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull + url: jdbc:mysql://127.0.0.1:3306/pipIrr_pj?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull +# url: jdbc:mysql://8.140.179.55:3306/pipIrr_pj?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull username: root password: dysql,;.abc!@# druid: diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml b/pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml index f9678d7..1bbe4e2 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/application-database-sp.yml @@ -6,7 +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://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: diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-ym.yml b/pipIrr-platform/pipIrr-global/src/main/resources/application-database-ym.yml index ab10469..3b1c640 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/application-database-ym.yml +++ b/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!@# diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaBlockMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaBlockMapper.xml index 93e6e80..4b4bcd7 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaBlockMapper.xml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/BaBlockMapper.xml @@ -26,7 +26,7 @@ select <include refid="Base_Column_List" /> from ba_block - where id = #{id,jdbcType=BIGINT} + where id = #{id,jdbcType=BIGINT} and deleted = 0 </select> <select id="selectAll" resultMap="BaseResultMap"> @@ -34,6 +34,7 @@ <!-- <include refid="part_Column_List" />--> <include refid="Base_Column_List" /> from ba_block + WHERE deleted = 0 </select> <select id="selectTotal" parameterType="java.util.Map" resultType="java.lang.Long"> @@ -61,6 +62,7 @@ <include refid="Base_Column_List" /> from ba_block <trim prefix="where " suffixOverrides="and"> + deleted = 0 and <if test="name != null and name != ''"> name like concat('%', #{name}, '%') and </if> diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml index af30365..3099a55 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrIntakeMapper.xml @@ -358,7 +358,7 @@ WHERE id NOT IN(SELECT intakeId FROM pr_controller) AND deleted = 0 </select> - <!--鑾峰彇鍙栨按鍙f暟閲忥紙鍦ㄧ嚎鍜屼笉鍦ㄥ厛锛�--> + <!--鑾峰彇鍙栨按鍙f暟閲忥紙鍦ㄧ嚎鍜屼笉鍦ㄥ厛锛� 搴熷純--> <select id="getOnLineIntakesCount" resultType="java.lang.Long"> SELECT COUNT(*) AS recordCount @@ -382,7 +382,7 @@ </where> </select> - <!--鑾峰彇鍙栨按鍙e垪琛紙鍦ㄧ嚎鍜屼笉鍦ㄥ厛锛�--> + <!--鑾峰彇鍙栨按鍙e垪琛紙鍦ㄧ嚎鍜屼笉鍦ㄥ厛锛� 搴熷純--> <select id="getOnLineIntakes" resultType="com.dy.pipIrrGlobal.voPr.VoOnLineIntake"> SELECT con.intakeId, @@ -413,6 +413,31 @@ </if> </select> + <!--鏍规嵁鍙栨按鍙g紪鍙疯幏鍙栧彇姘村彛瀵硅薄--> + <select id="getIntakeByName" resultType="com.dy.pipIrrGlobal.voPr.VoOnLineIntake"> + SELECT + con.intakeId, + con.rtuAddr, + inta.name AS intakeNum, + rtus.isOnLine + FROM pr_controller con + INNER JOIN pr_intake inta ON con.intakeId = inta.id + left JOIN JSON_TABLE( + #{onLineMap}, + '$[*]' COLUMNS( + rtuAddr VARCHAR(20) PATH '$.rtuAddr', + isOnLine BOOLEAN PATH '$.isOnLine' + ) + ) rtus ON con.rtuAddr = rtus.rtuAddr + <where> + <if test="intakeNum != null and intakeNum != ''"> + AND LOWER(inta.name) = #{intakeNum} + </if> + </where> + LIMIT 0,1 + + </select> + <!--鏍规嵁鎿嶄綔鍛樿幏鍙栧父鐢ㄥ彇姘村彛--> <select id="getUsedIntakes" resultType="com.dy.pipIrrGlobal.voPr.VoOnLineIntake"> SELECT diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeCardOperateMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeCardOperateMapper.xml index b39aad5..8baa1e8 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeCardOperateMapper.xml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeCardOperateMapper.xml @@ -690,5 +690,7 @@ AND ope.operate_type = 6 AND card.cardNum = #{cardNum} </where> + ORDER BY ope.operate_dt DESC + LIMIT 0,1 </select> </mapper> \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml index d828d9e..71d1989 100644 --- a/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml +++ b/pipIrr-platform/pipIrr-global/src/main/resources/mapper/SeClientCardMapper.xml @@ -56,9 +56,10 @@ <select id="getCardIdAndClientNum" resultType="java.util.Map"> <!-- SELECT id AS cardId, clientNum FROM se_client_card WHERE cardNum = #{cardNum}--> SELECT - card.id AS cardId, - cli.clientNum, - cli.id AS clientId + card.id AS cardId, + cli.clientNum, + cli.id AS clientId, + protocol FROM se_client_card card INNER JOIN se_client cli ON card.clientId = cli.id WHERE card.cardNum = #{cardNum} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java index 0fc696d..93cd402 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/common/CommandSv.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.dy.common.multiDataSource.DataSourceContext; import com.dy.common.mw.protocol.Command; import com.dy.common.webUtil.QueryResultVo; import com.dy.pipIrrGlobal.command.ComSupport; @@ -23,6 +24,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.utils.PojoUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import java.time.format.DateTimeFormatter; @@ -48,6 +51,25 @@ private final PrWaterPriceMapper prWaterPriceMapper; private final PrIntakeVcMapper prIntakeVcMapper; private final SeClientCardMapper seClientCardMapper; + + /** + * pro_mw锛氬睘鎬� + * tag浠庢帶鍒跺櫒涓幏鍙� + * key_mw锛歶rl鐨刱ey + */ + private Environment env = null; + private String pro_mw = "mw"; + private String key_mw = "comSendUrl"; + @Autowired + public CommandSv(RmCommandHistoryMapper rmCommandHistoryMapper, SeVirtualCardMapper seVirtualCardMapper, PrIntakeMapper prIntakeMapper, PrWaterPriceMapper prWaterPriceMapper, PrIntakeVcMapper prIntakeVcMapper, SeClientCardMapper seClientCardMapper, Environment env) { + this.rmCommandHistoryMapper = rmCommandHistoryMapper; + this.seVirtualCardMapper = seVirtualCardMapper; + this.prIntakeMapper = prIntakeMapper; + this.prWaterPriceMapper = prWaterPriceMapper; + this.prIntakeVcMapper = prIntakeVcMapper; + this.seClientCardMapper = seClientCardMapper; + this.env = env; + } /** * 铏氭嫙鍗D鎹㈣櫄鎷熷崱瀵硅薄 @@ -95,9 +117,9 @@ com.id = Command.defaultId; com.code = "LCD0001"; com.type = "innerCommand"; + comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); - if(response != null && response.getString("code").equals("0001")) { JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment").getJSONObject("onLineMap"); HashMap<String, Boolean> onLineMap = JSON.parseObject(attachment.toJSONString(), HashMap.class); @@ -151,9 +173,9 @@ com.id = Command.defaultId; com.code = "LCD0001"; com.type = "innerCommand"; + comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); - if(response != null && response.getString("code").equals("0001")) { JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment").getJSONObject("onLineMap"); HashMap<String, Boolean> onLineMap = JSON.parseObject(attachment.toJSONString(), HashMap.class); diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java index 84668b9..279d91c 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/valve/ValveCtrl.java @@ -22,10 +22,11 @@ import com.dy.pipIrrRemote.result.RemoteResultCode; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; import org.springframework.http.MediaType; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; @@ -47,7 +48,7 @@ @Tag(name = "骞冲彴闃�鎺у櫒鎺у埗", description = "骞冲彴闃�鎺у櫒鎺у埗") @RestController @RequestMapping(path="valve") -@RequiredArgsConstructor +//@RequiredArgsConstructor public class ValveCtrl extends ComSupport { private final CommandSv commandSv; private final SeVirtualCardMapper seVirtualCardMapper; @@ -55,6 +56,23 @@ @Value("${mw.rtuCallbackUrl_rm}") private String rtuCallbackUrl_rm; + + /** + * pro_mw锛氬睘鎬� + * tag浠庢帶鍒跺櫒涓幏鍙� + * key_mw锛歶rl鐨刱ey + */ + private Environment env = null; + private String pro_mw = "mw"; + private String key_mw = "comSendUrl"; + + @Autowired + public ValveCtrl(CommandSv commandSv, SeVirtualCardMapper seVirtualCardMapper, IDLongGenerator idLongGenerator, Environment env) { + this.commandSv = commandSv; + this.seVirtualCardMapper = seVirtualCardMapper; + this.idLongGenerator = idLongGenerator; + this.env = env; + } /** * 骞冲彴杩滅▼寮�闃� @@ -112,6 +130,8 @@ } String rtuAddr = job_rtu.getString("rtuAddr"); String protocol = job_rtu.getString("protocol"); + String orgTag = job_rtu.getString("orgTag"); + comSendUrl = env.getProperty(pro_mw + "." + orgTag + "." + key_mw); // 鐢熸垚璁㈠崟鍙� String orderNo = generateOrderNo(); @@ -229,6 +249,8 @@ } //Long intakeId = job_rtu.getLong("intakeId"); String protocol = job_rtu.getString("protocol"); + String orgTag = job_rtu.getString("orgTag"); + comSendUrl = env.getProperty(pro_mw + "." + orgTag + "." + key_mw); String commandCode = null; if(protocol.equals("p206V202404")) { diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/CardOperateCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/CardOperateCtrl.java index b607fb5..5cb744f 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/CardOperateCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/CardOperateCtrl.java @@ -107,6 +107,7 @@ * operator 鎿嶄綔浜虹紪鍙� * activeTime 寮�鍗℃椂闂� */ + String protocol = po.getProtocol(); String cardAddr = po.getCardAddr(); Integer cardCost = po.getCardCost(); Long originalCardId = po.getOriginalCardId(); @@ -120,6 +121,7 @@ * 娣诲姞鍐滄埛鍗¤褰曪紝閫�杩橀噾棰濅綔涓哄綋鍓嶄綑棰� */ SeClientCard seClientCard = new SeClientCard(); + seClientCard.setProtocol(protocol); seClientCard.setCardaddr(cardAddr); seClientCard.setCardnum(cardNum); seClientCard.setClientid(clientId); @@ -207,6 +209,7 @@ * operator 鎿嶄綔浜虹紪鍙� */ + String protocol; String cardAddr = po.getCardAddr(); String clientNum = ""; Long clientId = 0L; @@ -226,7 +229,7 @@ // 濡傛灉浼犲叆浜嗛��杩橀噾棰濓紝闇�瑕佸垽鏂�佸崱锛堣鎸傚け鐨勬按鍗★級鎸傚け鏃舵槸鍚﹀凡缁忛��娆撅紝鏃犺閫�娆惧灏戦兘鎻愮ず鐢ㄦ埛鎸傚け鏃跺凡閫�娆� if(reissueAmount != null && reissueAmount > 0) { Double tradeAmount = cardOperateSv.getTradeAmountByCardNo(cardNum); - if(tradeAmount != null) { + if(tradeAmount != null && tradeAmount > 0) { return BaseResponseUtils.buildErrorMsg(SellResultCode.THE_FEE_CANNOT_BE_REFUNDED.getMessage()); } } @@ -241,6 +244,7 @@ clientNum = map.get("clientNum").toString(); cardId = Long.parseLong(map.get("cardId").toString()); clientId = Long.parseLong(map.get("clientId").toString()); + protocol = map.get("protocol").toString(); /** * 濡傛灉鏄ˉ鍗¤皟鐢ㄧ殑寮�鍗′笖杞Щ浜嗛��杩橀噾棰濓紝闇�淇敼鎸傚け鍗′綑棰濅负0 @@ -256,6 +260,7 @@ * 娣诲姞寮�鍗¤褰曪紝閫�杩橀噾棰濆啿鍒版柊鍗′腑 */ ActiveCard activeCard = new ActiveCard(); + activeCard.setProtocol(protocol); activeCard.setCardAddr(cardAddr); activeCard.setClientId(clientId); activeCard.setOriginalCardId(cardId); @@ -279,6 +284,7 @@ map_response.put("projectNo", projectNo); map_response.put("orderNumber", orderNumber); map_response.put("cardNum", cardNum); + map_response.put("protocol", protocol); return BaseResponseUtils.buildSuccess(map_response) ; } diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/dto/ActiveCard.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/dto/ActiveCard.java index 2cbc5a0..2c3ff91 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/dto/ActiveCard.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/cardOperate/dto/ActiveCard.java @@ -17,6 +17,12 @@ public static final long serialVersionUID = 202407111129001L; /** + * 鍗忚鍚嶇О + */ + @NotBlank(message = "鍗忚涓嶈兘涓虹┖") + private String protocol; + + /** * 姘村崱鍦板潃锛屼粎淇濆瓨锛屾棤涓氬姟 */ @NotBlank(message = "姘村崱鍦板潃涓嶈兘涓虹┖") diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/client/ClientCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/client/ClientCtrl.java index 447a341..48d718c 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/client/ClientCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-sell/src/main/java/com/dy/pipIrrSell/client/ClientCtrl.java @@ -253,7 +253,8 @@ String villageName = map_districts.get("villageName").toString(); // 鐢熸垚8浣嶈鏀垮尯鍒掔紪鐮侊紝鐢熸垚鍐滄埛缂栧彿鐢� - String district8 = countyNum + townNum + villageNum; + //String district8 = countyNum + townNum + villageNum; + String district8 = String.format("%02d", Integer.parseInt(countyNum)) + String.format("%03d", Integer.parseInt(townNum)) + String.format("%03d", Integer.parseInt(villageNum)); // 鐢熸垚鍐滄埛缂栧彿 String clientNum = generateClientNum(district8); // 鐢熸垚12浣�5绾ц鏀垮尯鍒掔紪鐮佷覆鍙婂悕绉颁覆 diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java index 1bc71bc..8aedcb7 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/CommandSv.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.dy.common.multiDataSource.DataSourceContext; import com.dy.common.mw.protocol.Command; import com.dy.common.webUtil.QueryResultVo; import com.dy.pipIrrGlobal.command.ComSupport; @@ -19,6 +20,8 @@ import com.dy.pipIrrGlobal.voSe.VoVirtualCard; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -44,6 +47,24 @@ private final PrIntakeVcMapper prIntakeVcMapper; private final SeClientCardMapper seClientCardMapper; + /** + * pro_mw锛氬睘鎬� + * tag浠庢帶鍒跺櫒涓幏鍙� + * key_mw锛歶rl鐨刱ey + */ + private Environment env = null; + private String pro_mw = "mw"; + private String key_mw = "comSendUrl"; + @Autowired + public CommandSv(RmCommandHistoryMapper rmCommandHistoryMapper, SeVirtualCardMapper seVirtualCardMapper, PrIntakeMapper prIntakeMapper, PrWaterPriceMapper prWaterPriceMapper, PrIntakeVcMapper prIntakeVcMapper, SeClientCardMapper seClientCardMapper, Environment env) { + this.rmCommandHistoryMapper = rmCommandHistoryMapper; + this.seVirtualCardMapper = seVirtualCardMapper; + this.prIntakeMapper = prIntakeMapper; + this.prWaterPriceMapper = prWaterPriceMapper; + this.prIntakeVcMapper = prIntakeVcMapper; + this.seClientCardMapper = seClientCardMapper; + this.env = env; + } /** * 铏氭嫙鍗D鎹㈣櫄鎷熷崱瀵硅薄 * @param vcId @@ -71,9 +92,9 @@ com.id = Command.defaultId; com.code = "LCD0001"; com.type = "innerCommand"; + comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); - if(response != null && response.getString("code").equals("0001")) { JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment").getJSONObject("onLineMap"); HashMap<String, Boolean> onLineMap = JSON.parseObject(attachment.toJSONString(), HashMap.class); diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java index 6ad9ae6..aa0ef5e 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/command/ValveCtrl.java @@ -23,10 +23,11 @@ import com.dy.pipIrrWechat.result.WechatResultCode; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; import org.springframework.http.MediaType; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BindingResult; @@ -47,7 +48,7 @@ @Tag(name = "灏忕▼搴忛榾鎺у櫒鎺у埗", description = "灏忕▼搴忛榾鎺у櫒鎺у埗") @RestController @RequestMapping(path = "valve") -@RequiredArgsConstructor +//@RequiredArgsConstructor public class ValveCtrl extends ComSupport { private final CommandSv commandSv; private final SeVirtualCardMapper seVirtualCardMapper; @@ -55,6 +56,23 @@ @Value("${mw.rtuCallbackUrl_wx}") private String rtuCallbackUrl_wx; + + /** + * pro_mw锛氬睘鎬� + * tag浠庢帶鍒跺櫒涓幏鍙� + * key_mw锛歶rl鐨刱ey + */ + private Environment env = null; + private String pro_mw = "mw"; + private String key_mw = "comSendUrl"; + + @Autowired + public ValveCtrl(CommandSv commandSv, SeVirtualCardMapper seVirtualCardMapper, IDLongGenerator idLongGenerator, Environment env) { + this.commandSv = commandSv; + this.seVirtualCardMapper = seVirtualCardMapper; + this.idLongGenerator = idLongGenerator; + this.env = env; + } /** * 灏忕▼搴忚繙绋嬪紑闃� @@ -126,6 +144,8 @@ } String rtuAddr = job_rtu.getString("rtuAddr"); String protocol = job_rtu.getString("protocol"); + String orgTag = job_rtu.getString("orgTag"); + comSendUrl = env.getProperty(pro_mw + "." + orgTag + "." + key_mw); // 鐢熸垚璁㈠崟鍙� String orderNo = generateOrderNo(); @@ -232,6 +252,8 @@ } Long intakeId = job_rtu.getLong("intakeId"); String protocol = job_rtu.getString("protocol"); + String orgTag = job_rtu.getString("orgTag"); + comSendUrl = env.getProperty(pro_mw + "." + orgTag + "." + key_mw); String commandCode = null; if (protocol.equals("p206V202404")) { diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeCtrl.java index 45ee4ed..5ddabb6 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeCtrl.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeCtrl.java @@ -30,15 +30,14 @@ private final IntakeSv intakeSv; /** - * 鑾峰彇鍙栨按鍙e垪琛紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛� + * 鑾峰彇鍙栨按鍙o紙鍦ㄧ嚎鍜屼笉鍦ㄧ嚎锛� * @param qo * @return */ @GetMapping(path = "all_intakes") - public BaseResponse<QueryResultVo<List<VoOnLineIntake>>> getAllIntakes(OnLineIntakesQO qo) { + public BaseResponse<QueryResultVo<VoOnLineIntake>> getAllIntakes(OnLineIntakesQO qo) { try { - QueryResultVo<List<VoOnLineIntake>> res = intakeSv.selectOnLineIntakes(qo); - return BaseResponseUtils.buildSuccess(res); + return BaseResponseUtils.buildSuccess(intakeSv.selectOnLineIntakes(qo)); } catch (Exception e) { log.error("鏌ヨ鍙栨按鍙e紓甯�", e); return BaseResponseUtils.buildException(e.getMessage()); diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeSv.java index 0e6fd7f..32c3ed8 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeSv.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/intake/IntakeSv.java @@ -3,15 +3,16 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.dy.common.multiDataSource.DataSourceContext; import com.dy.common.mw.protocol.Command; import com.dy.common.webUtil.BaseResponse; -import com.dy.common.webUtil.QueryResultVo; import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper; import com.dy.pipIrrGlobal.voPr.VoOnLineIntake; import com.dy.pipIrrWechat.intake.qo.OnLineIntakesQO; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.common.utils.PojoUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -41,20 +42,33 @@ @Autowired private RestTemplate restTemplate; - protected static String mwUrlSendCom = "http://127.0.0.1:8070/rtuMw/com/send" ; + //protected static String mwUrlSendCom = "http://127.0.0.1:8070/rtuMw/com/send" ; + protected String comSendUrl; + /** + * pro_mw锛氬睘鎬� + * tag浠庢帶鍒跺櫒涓幏鍙� + * key_mw锛歶rl鐨刱ey + */ + private Environment env = null; + private String pro_mw = "mw"; + private String key_mw = "comSendUrl"; + @Autowired + public IntakeSv(Environment env) { + this.env = env; + } /** - * 鑾峰彇鍙栨按鍙e垪琛� + * 鑾峰彇鍙栨按鍙� * @return */ - public QueryResultVo<List<VoOnLineIntake>> selectOnLineIntakes(OnLineIntakesQO qo) { + public VoOnLineIntake selectOnLineIntakes(OnLineIntakesQO qo) { Command com = new Command() ; com.id = Command.defaultId; com.code = "LCD0001"; com.type = "innerCommand"; + comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); - if(response != null && response.getString("code").equals("0001")) { JSONObject attachment = response.getJSONObject("content").getJSONObject("attachment").getJSONObject("onLineMap"); HashMap<String, Boolean> onLineMap = JSON.parseObject(attachment.toJSONString(), HashMap.class); @@ -68,18 +82,16 @@ } qo.setOnLineMap(jsonArray.toJSONString()); - Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(qo) ; - Long itemTotal = prIntakeMapper.getOnLineIntakesCount(params); + // 濡傛灉 intakeNum 涓嶄负绌猴紝鍒欒浆涓哄皬鍐欏啀鍐欏叆qo瀵硅薄 + String intakeNum = qo.getIntakeNum(); + if(intakeNum != null) { + qo.setIntakeNum(intakeNum.toLowerCase()); + } - QueryResultVo<List<VoOnLineIntake>> rsVo = new QueryResultVo<>() ; - rsVo.pageSize = qo.pageSize ; - rsVo.pageCurr = qo.pageCurr ; - rsVo.calculateAndSet(itemTotal, params); - rsVo.obj = prIntakeMapper.getOnLineIntakes(params); - return rsVo; + Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(qo) ; + return prIntakeMapper.getIntakeByName(params); } else { - QueryResultVo<List<VoOnLineIntake>> rsVo = new QueryResultVo<>(); - return rsVo; + return new VoOnLineIntake(); } } @@ -93,6 +105,7 @@ com.id = Command.defaultId; com.code = "LCD0001"; com.type = "innerCommand"; + comSendUrl = env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + key_mw); JSONObject response = (JSONObject) JSON.toJSON(sendCom2Mw(com)); if(response != null && response.getString("code").equals("0001")) { @@ -117,7 +130,7 @@ * @return */ protected BaseResponse sendCom2Mw(Command com){ - String url = UriComponentsBuilder.fromUriString(mwUrlSendCom) + String url = UriComponentsBuilder.fromUriString(comSendUrl) .build() .toUriString(); HttpHeaders headers = new HttpHeaders(); diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java index df5e385..ee429dc 100644 --- a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/result/WechatResultCode.java @@ -29,7 +29,6 @@ */ RTU_NOT_EXIST(20001, "闃�鎺у櫒涓嶅瓨鍦�"), //RTU_ADDR_CANNOT_BE_NULL(20002, "闃�鎺у櫒鍦板潃涓嶈兘涓虹┖"); - CLIENT_CARD_NOT_EXIST(30001, "姘村崱涓嶅瓨鍦�"), /** @@ -45,7 +44,19 @@ VALIDATION_TIMEOUT(20004, "楠岃瘉瓒呮椂"), PHONE_NUMBER_IS_ERROR(20004, "鎵嬫満鍙烽敊璇紝闈炴敞鍐屽啘鎴�"), INVALID_CODE(20004, "鏃犳晥鐨勪复鏃剁櫥褰曞嚟璇�"), - LOGIN_FAIL(20004, "鐧诲綍澶辫触"); + LOGIN_FAIL(20004, "鐧诲綍澶辫触"), + + /** + * 铏氭嫙鍗� + */ + ABNORMAL(10001, "閫�娆惧紓甯�"), + PROCESSING(10001, "閫�娆惧鐞嗕腑"), + VC_OPEN_ACCOUNT_FAIL(90002, "铏氭嫙鍗¤处鎴锋敞鍐屽け璐�"), + CARD_NUMBER_OVERRUN(10002, "姘村崱缂栧彿宸叉弧"), + VIRTUAL_CARD_NOT_EXIST(90006, "铏氭嫙鍗¤处鎴蜂笉瀛樺湪"), + RECHARGE_NOT_EXIST(90006, "鍏呭�艰褰曚笉瀛樺湪"), + RECHARGE_FAIL(90006, "鍏呭�煎け璐�"), + NO_ACCOUNT(40001, "鎮ㄦ寚瀹氱殑铏氭嫙鍗℃湭娉ㄥ唽"); private final Integer code; private final String message; diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/AesUtil.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/AesUtil.java new file mode 100644 index 0000000..7a629c2 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/AesUtil.java @@ -0,0 +1,50 @@ +package com.dy.pipIrrWechat.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-07-15 10:18 + * @LastEditTime 2024-07-15 10:18 + * @Description + */ +public class AesUtil { + static final int KEY_LENGTH_BYTE = 32; + static final int TAG_LENGTH_BIT = 128; + + /** + * 瑙e瘑 + * @param apiV3Key apiV3瀵嗛挜 + * @param associatedData 闄勫姞鏁版嵁 + * @param nonce 闅忔満涓� + * @param ciphertext 鏁版嵁瀵嗘枃 + * @return 瑙e瘑鍚庡瓧绗︿覆 + * @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); + } + } +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/HmacSha256.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/HmacSha256.java new file mode 100644 index 0000000..9f5e7c2 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/HmacSha256.java @@ -0,0 +1,43 @@ +package com.dy.pipIrrWechat.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-07-15 10:19 + * @LastEditTime 2024-07-15 10:19 + * @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; + } +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java new file mode 100644 index 0000000..3aa2522 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java @@ -0,0 +1,508 @@ +package com.dy.pipIrrWechat.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.pipIrrWechat.result.WechatResultCode; +import com.dy.pipIrrWechat.virtualCard.VirtualCardSv; +import com.dy.pipIrrWechat.wechatpay.PayInfo; +import com.dy.pipIrrWechat.wechatpay.dto.Refund; +import com.dy.pipIrrWechat.wechatpay.dto.RefundRequest; +import com.dy.pipIrrWechat.wechatpay.dto.RefundResponse; +import com.dy.pipIrrWechat.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-07-15 10:11 + * @LastEditTime 2024-07-15 10:11 + * @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鐜涓嶆敮鎸丷SA", 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 绛惧悕淇℃伅锛孒TTP澶翠腑鐨勭鍚嶄俊鎭� + * HTTP澶达細Authorization: 璁よ瘉绫诲瀷 绛惧悕淇℃伅 + * 璁よ瘉绫诲瀷锛學ECHATPAY2-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 璇锋眰杩斿洖鐨刡ody + * @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"); + //headers.put("User-Agent", "https://zh.wikipedia.org/wiki/User_agent"); + + 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鍒嗛挓鏃舵墠灏嗚瘉涔﹀瓨鍌╩ap + 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(); + + // 鍒濆鍖朣HA256withRSA鍓嶉潰鍣� + Signature signature = Signature.getInstance("SHA256withRSA"); + // 鐢ㄥ井淇″钩鍙板叕閽ュ鍓嶉潰鍣ㄨ繘琛屽垵濮嬪寲 + signature.initVerify(certificate); + + // 灏嗘瀯閫犵殑楠岀鍚嶄覆鏇存柊鍒扮鍚嶅櫒涓� + signature.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + + // 璇锋眰澶翠腑寰俊鏈嶅姟鍣ㄨ繑鍥炵殑绛惧悕鐢˙ase64瑙g爜锛屼娇鐢ㄧ鍚嶅櫒杩涜楠岃瘉 + 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(WechatResultCode.PROCESSING.getMessage()); + } else { + // 閫�娆惧紓甯� + return BaseResponseUtils.buildError(WechatResultCode.ABNORMAL.getMessage()); + } + } +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java new file mode 100644 index 0000000..e53ea94 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardCtrl.java @@ -0,0 +1,269 @@ +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.virtualCard.dto.DtoRegist; +import com.dy.pipIrrWechat.virtualCard.dto.DtoVcRecharge; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * @author ZhuBaoMin + * @date 2024-07-15 9:55 + * @LastEditTime 2024-07-15 9:55 + * @Description + */ + +@Slf4j +@Tag(name = "铏氭嫙鍗$鐞�", description = "铏氭嫙鍗$鐞�") +@RestController +@RequestMapping(path="virtual_card") +@RequiredArgsConstructor +@Validated +public class VirtualCardCtrl { + private final VirtualCardSv virtualCardSv; + 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()) ; + } + } + + /** + * 鏍规嵁铏氭嫙鍗D鑾峰彇铏氭嫙鍗″璞� + * @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){ + 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)); + /** + * 鏍规嵁琛屾斂鍖哄垝涓诧紙areaCode锛夊湪铏氭嫙鍗¤〃涓拡瀵硅櫄鎷熷崱缂栧彿锛坴cNum锛夎繘琛屾ā绯婃煡璇� + * 濡傛灉5浣嶉『搴忓彿宸茬粡杈惧埌鏈�澶у�硷紝鎻愮ず鐢ㄦ埛鑱旂郴绯荤粺绠$悊鍛� + * 濡傛灉5浣嶉『搴忓彿鏈揪鍒版渶澶у�硷紝鍒欏姞1 + * cardNum涓烘柊鐨勫崱鍙� + */ + String vcNum = Optional.ofNullable(virtualCardSv.getVcCardNumOfMax(areaCode)).orElse(""); + if(vcNum != null && vcNum.trim().length() > 0) { + Integer number = Integer.parseInt(vcNum.substring(12)); + number = number + 1; + if(number > 65535) { + return BaseResponseUtils.buildFail(WechatResultCode.CARD_NUMBER_OVERRUN.getMessage()); + } + vcNum = vcNum.substring(0, 12) + String.format("%05d", number); + } else { + vcNum = areaCode + "00001"; + } + + SeVirtualCard seVirtualCard = new SeVirtualCard(); + seVirtualCard.setVcNum(Long.parseLong(vcNum)); + seVirtualCard.setClientId(clientId); + seVirtualCard.setMoney(0d); + seVirtualCard.setLastOperate(LastOperateENUM.OPEN_ACCOUNT.getCode()); + seVirtualCard.setLastOperateTime(new Date()); + seVirtualCard.setInUse((byte) 0); + seVirtualCard.setCreateTime(new Date()); + Long rec = virtualCardSv.insertVirtualCard(seVirtualCard); + if(rec == null) { + return BaseResponseUtils.buildFail(WechatResultCode.VC_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 = "鎿嶄綔缁撴灉锛歵rue锛氭垚鍔燂紝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(); + // + // // 鏍规嵁铏氭嫙鍗D鑾峰彇铏氭嫙鍗″璞� + // SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); + // if(seVirtualCard == null) { + // return BaseResponseUtils.buildFail(WechatResultCode.VIRTUAL_CARD_NOT_EXIST.getMessage()); + // } + // Long clientId = seVirtualCard.getClientId(); + // Double money = seVirtualCard.getMoney(); + // + // // 楠岃瘉閫�娆鹃噾棰濇槸鍚﹀ぇ浜庝綑棰� + // if(refundAmount > money) { + // return BaseResponseUtils.buildFail(WechatResultCode.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(WechatResultCode.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 = "鎿嶄綔缁撴灉锛歵rue锛氭垚鍔燂紝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()); + // } + // + // // 鏍规嵁閫�娆綢D鑾峰彇閫�娆惧璞★紝骞舵洿鏂板鏍镐汉銆佸鏍告椂闂淬�佸鏍稿娉ㄣ�侀��娆剧姸鎬佸瓧娈� + // 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(WechatResultCode.AUDIT_REFUND_FAIL.getMessage()); + // } + // + // // 瀹屾垚瀹℃牳鍚庤幏鍙栧緟閫�娆捐鍗曞垪琛� + // List<ToRefund> list_ToRefund = payHelper.getToRefunds(virtualId, refundAmount); + // if(list_ToRefund == null || list_ToRefund.size() <=0) + // return BaseResponseUtils.buildFail(WechatResultCode.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) ; + //} + + /** + * 鑾峰彇铏氭嫙鍗″厖鍊艰褰� + * @return + */ + @GetMapping(path = "/getVcRechargeRecords") + @SsoAop() + public BaseResponse<QueryResultVo<List<VoVcRecharge>>> getVcRechargeRecords(DtoVcRecharge dtoVcRecharge){ + try { + QueryResultVo<List<VoVcRecharge>> res = virtualCardSv.getVcRechargeRecords(dtoVcRecharge); + return BaseResponseUtils.buildSuccess(res); + } catch (Exception e) { + log.error("鑾峰彇铏氭嫙鍗″厖鍊艰褰曞紓甯�", e); + return BaseResponseUtils.buildException(e.getMessage()) ; + } + } +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java new file mode 100644 index 0000000..2f4a5ff --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/virtualCard/VirtualCardSv.java @@ -0,0 +1,352 @@ +package com.dy.pipIrrWechat.virtualCard; + +import com.dy.common.webUtil.BaseResponse; +import com.dy.common.webUtil.BaseResponseUtils; +import com.dy.common.webUtil.QueryResultVo; +import com.dy.pipIrrGlobal.daoSe.*; +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.pipIrrGlobal.voSe.VoVcRecharge; +import com.dy.pipIrrGlobal.voSe.VoVirtualCard; +import com.dy.pipIrrWechat.virtualCard.dto.DtoVcRecharge; +import com.dy.pipIrrWechat.virtualCard.dto.DtoVirtualCard; +import com.dy.pipIrrWechat.virtualCard.enums.LastOperateENUM; +import com.dy.pipIrrWechat.virtualCard.enums.OrderStateENUM; +import com.dy.pipIrrWechat.result.WechatResultCode; +import lombok.extern.slf4j.Slf4j; +import org.apache.dubbo.common.utils.PojoUtils; +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; +import java.util.Map; + +/** + * @author ZhuBaoMin + * @date 2024-07-15 9:39 + * @LastEditTime 2024-07-15 9:39 + * @Description + */ + +@Slf4j +@Service +public class VirtualCardSv { + @Autowired + private SeVirtualCardMapper seVirtualCardMapper; + + @Autowired + private SeVcRechargeMapper seVcRechargeMapper; + + @Autowired + private SeVcRefundMapper seVcRefundMapper; + + @Autowired + private SeVcRefundItemMapper seVcRefundItemMapper; + + @Autowired + private SeClientMapper seClientMapper; + + /** + * 鏍规嵁鍐滄埛ID鑾峰彇5绾ц鏀垮尯鍒掍唬鐮侊紝娉ㄥ唽铏氭嫙鍗′娇鐢� + * @param clientId 鍐滄埛ID + * @return 5绾ц鏀垮尯鍒掍唬鐮� + */ + public Long getAreaCodeById(Long clientId) { + return seClientMapper.getAreaCodeById(clientId); + } + + /** + * 鑾峰彇鍐滄埛鍏ㄩ儴铏氭嫙鍗� + * @return + */ + public List<VoVirtualCard> getVCs(Long clientId) { + return seVirtualCardMapper.getVCs(clientId); + } + + /** + * 鏍规嵁铏氭嫙鍗D鑾峰彇铏氭嫙鍗″璞� + * @param vcId + * @return + */ + public VoVirtualCard getVcById(Long vcId) { + return seVirtualCardMapper.getVcById(vcId); + } + + /** + * 娉ㄥ唽铏氭嫙鍗� + * @param po + * @return + */ + public Long insertVirtualCard(SeVirtualCard po) { + seVirtualCardMapper.insert(po); + return po.getId(); + } + + /** + * 鏍规嵁琛屾斂鍖哄垝涓叉ā绯婃煡璇㈣櫄鎷熷崱缂栧彿锛屾敞鍐岃櫄鎷熷崱浣跨敤 + * @param areaCode + * @return + */ + String getVcCardNumOfMax(String areaCode) { + return seVirtualCardMapper.getVcCardNumOfMax(areaCode); + } + + /** 搴熷純 + * 楠岃瘉鍐滄埛鏄惁鎷ユ湁鎸囧畾鍚嶇О鐨勮櫄鎷熷崱 + * @param po + * @return + */ + //public Integer getRecordCountByName(DtoRegist po) { + // return seVirtualCardMapper.getRecordCountByName(po.getClientId(), po.getVcName()); + //} + + /** + * 淇敼铏氭嫙鍗� + * 鍏呭�笺�佹秷璐广�佺敵璇烽��娆俱�佸鏍搁��娆炬椂闇�瑕佷慨鏀硅櫄鎷熷崱鐨勶細浣欓銆佹渶鍚庢搷浣溿�佹渶鍚庢搷浣滄椂闂� + * @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(WechatResultCode.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(WechatResultCode.RECHARGE_FAIL.getMessage()); + } + return BaseResponseUtils.buildSuccess(true) ; + } + + /** + * 鏍规嵁璁㈠崟鍙疯幏鍙栬櫄鎷熷崱鍏呭�煎璞� + * @param orderNumber + * @return + */ + public SeVcRecharge getVCRechargeByorderNumber(String orderNumber) { + return seVcRechargeMapper.getVCRechargeByorderNumber(orderNumber); + } + + /** + * 淇敼铏氭嫙鍗″厖鍊艰褰� + * 寰俊鏀粯閫氱煡鍚庯細 + * 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(WechatResultCode.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(WechatResultCode.RECHARGE_FAIL.getMessage()); + } + + SeVirtualCard seVirtualCard = seVirtualCardMapper.selectByPrimaryKey(virtualId); + if(seVirtualCard == null) { + return BaseResponseUtils.buildFail(WechatResultCode.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(WechatResultCode.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 ; + } + + /** + * 鏍规嵁閫�娆綢D鑾峰彇閫�娆惧璞� + * @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; + } + + /** + * 鏍规嵁璁㈠崟鍙疯幏鍙栧厖鍊奸噾棰濓紝璋冪敤閫�娆剧敵璇锋帴鍙d娇鐢� + * @param orderNumber + * @return + */ + public Integer getRechargeAmountByOrderNumber(String orderNumber) { + return seVcRechargeMapper.getRechargeAmountByOrderNumber(orderNumber); + + } + + /** + * 鏍规嵁閫�娆鹃�氱煡鎺ュ彛杩斿洖鐨勯��娆惧崟鍙峰弽鏌ラ��娆綢D锛屾煡璇㈣閫�娆綢D涓嬫湭閫�娆捐褰曟暟閲� + * @param refundNumber + * @return + */ + public Integer getNoRefundedCount(String refundNumber) { + return seVcRefundItemMapper.getNoRefundedCount(refundNumber); + } + + /** + * 鏍规嵁閫�娆惧崟鍙疯幏鍙栭��娆綢D锛岄��娆鹃�氱煡鍚庢洿鏂伴��娆捐〃鎵�闇� + * @param refundNumber + * @return + */ + public Long getRefundIdByRefundNumber(String refundNumber) { + return seVcRefundItemMapper.getRefundIdByRefundNumber(refundNumber); + } + + /** + * 鑾峰彇铏氭嫙鍗″厖鍊艰褰� + * @param dtoVcRecharge + * @return + */ + public QueryResultVo<List<VoVcRecharge>> getVcRechargeRecords(DtoVcRecharge dtoVcRecharge){ + Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(dtoVcRecharge); + Long itemTotal = seVirtualCardMapper.getRechargeRecordCount(params); + + QueryResultVo<List<VoVcRecharge>> rsVo = new QueryResultVo<>(); + rsVo.pageSize = dtoVcRecharge.pageSize; + rsVo.pageCurr = dtoVcRecharge.pageCurr; + + rsVo.calculateAndSet(itemTotal, params); + rsVo.obj = seVirtualCardMapper.getVcRechargeRecords(params); + + return rsVo; + } +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PayInfo.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PayInfo.java new file mode 100644 index 0000000..690e30a --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/PayInfo.java @@ -0,0 +1,176 @@ +package com.dy.pipIrrWechat.wechatpay; + +/** + * @author ZhuBaoMin + * @date 2024-07-15 10:26 + * @LastEditTime 2024-07-15 10:26 + * @Description + */ +public class PayInfo { + /** + * 灏忕▼搴忕櫥褰旳PI + */ + 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"; + public static String orderUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"; + + /** + * 骞冲彴璇佷功涓嬭浇URL + */ + public static String certificates = "https://api.mch.weixin.qq.com/v3/certificates"; + + /* + * 鏀粯缁撴灉閫氱煡API + */ + public static String notifyUrl = "https://44978f7456.imdo.co/sell/payment/orderNotify"; + + /* + * 鏌ヨ璁㈠崟API + */ + public static String queryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; + + /** + * 鐢宠閫�娆続PI + */ + public static String refundUrl = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"; + + /* + * 閫�娆鹃�氱煡API + */ + public static String refundNotifyUrl = "https://www.muxiaobao.com/wxpay/pay.action"; + + /* + * 閫�娆炬煡璇PI + */ + public static String refundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery"; + + /* + * 灏忕▼搴忓敮涓�鏍囪瘑 + */ + //public static String appid = "wxbc2b6a00dd904ead"; + public static String appid = "wxf773810cd5643196"; + + /* + * 灏忕▼搴忕殑 app secret + */ + //public static String secret = "796ffe3e9921f756db0499e80d6ed0cd"; + public static String secret = "080d4f947095551e988cfe9338e27f15"; + + /* + * 灏忕▼搴忕殑鎺堟潈绫诲瀷锛岀櫥褰曞嚟璇佹牎楠屼娇鐢� + */ + public static String grantType = "authorization_code"; + + /* + * 鍟嗘埛鍙�(寰俊鏀粯鍒嗛厤鐨勫晢鎴峰彿) + */ + public static String mchid = "1640721520"; + + /* + * 鍟嗘埛骞冲彴璁剧疆鐨勫瘑閽ey + */ + public static String key = "DaYuJieShuiYanJiuYuan20230412ABC"; + + /** + * 鍟嗘埛API璇佷功搴忓垪鍙� + */ + public static String serial_no = "52D65AA66405C738670377F467178F4C950E1606"; + + /* + * 缁堢IP锛岃皟鐢ㄥ井淇℃敮浠楢PI鐨勬満鍣↖P + */ + public static String addrIp = "47.104.211.89"; + + /* + * 闅忔満瀛楃涓诧紝闀垮害瑕佹眰鍦�32浣嶄互鍐� + */ + //public static String nonceStr = PayHelper.generateRandomString(); + + /* + * 鏃堕棿鎴� 浠�1970骞�1鏈�1鏃�00:00:00鑷充粖鐨勭鏁�,鍗冲綋鍓嶇殑鏃堕棿 + */ + //public static Long timeStamp = PayHelper.getTimeStamp(); + + /* + * 浜ゆ槗绫诲瀷锛屽皬绋嬪簭鍙栧�糐SAPI + */ + public static String tradeType = "JSAPI"; + + /* + * 绛惧悕绫诲瀷 + */ + //public static String signType = "MD5"; + public static String signType = "RSA"; + + /* + * 鍟嗗搧鎻忚堪 鍟嗗搧绠�鍗曟弿杩帮紝璇ュ瓧娈佃鎸夌収瑙勮寖浼犻�� + */ + //public static String body = "澶х鐮旂┒闄�-姘磋垂"; + public static String description = "澶х鐮旂┒闄�-姘磋垂"; + + /* + * 闄勫姞鏁版嵁锛屽湪鏌ヨAPI鍜屾敮浠橀�氱煡涓師鏍疯繑鍥烇紝鍙綔涓鸿嚜瀹氫箟鍙傛暟浣跨敤 + */ + public static String attach = "澶╂触"; + + /* + * 绛惧悕锛屽弬涓庣鍚嶅弬鏁帮細appid銆乤ttach銆乵ch_id銆乶once_str銆乥ody銆乷ut_trade_no銆乼otal_fee銆乻pbill_create_ip銆乶otify_url銆乼rade_type銆乷penid + */ + public String sign = ""; + + /** + * HTTP澶磋璇佺被鍨� + */ + public static String schema = "WECHATPAY2-SHA256-RSA2048"; + + /** + * 绉侀挜鏂囦欢璺緞 + */ + public static String privateCertFileName = "C:\\webchat\\apiclient_key.pem"; + + public static String publicCertFileName = "C:\\webchat\\wxp_cert.pem"; + + /* + * 寰俊璁㈠崟鍙凤紝浼樺厛浣跨敤 + */ + public static String transactionid = ""; + + /* + * 鍟嗘埛绯荤粺鍐呴儴璁㈠崟鍙� + */ + public static String out_trade_no = ""; + + /* + * 鍟嗘埛閫�娆惧崟鍙� + */ + public static String out_refund_no = ""; + + /* + * 閫�娆鹃噾棰� + */ + public static Float refundfee; + + /* + * 璁㈠崟閲戦 + */ + public static Float totalfee; +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/Refund.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/Refund.java new file mode 100644 index 0000000..cfdff37 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/Refund.java @@ -0,0 +1,39 @@ +package com.dy.pipIrrWechat.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-07-15 10:28 + * @LastEditTime 2024-07-15 10:28 + * @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; +} diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundRequest.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundRequest.java new file mode 100644 index 0000000..bf1f6f0 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundRequest.java @@ -0,0 +1,70 @@ +package com.dy.pipIrrWechat.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-07-15 10:29 + * @LastEditTime 2024-07-15 10:29 + * @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; + + /** + * 鍟嗘埛閫�娆惧崟鍙凤紝璁㈠崟鍙峰墠鍔犲墠缂�鈥淩鈥� + */ + @Schema(description = "鍟嗘埛閫�娆惧崟鍙�", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @NotBlank(message = "鍟嗘埛閫�娆惧崟鍙蜂笉鑳戒负绌�") + private String out_refund_no; + + /** + * 閫�娆剧粨鏋滃洖璋僽rl锛宺efundUrl + */ + @Schema(description = "閫�娆剧粨鏋滃洖璋僽rl", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @NotBlank(message = "閫�娆剧粨鏋滃洖璋僽rl涓嶈兘涓虹┖") + private String notify_url; + + /** + * 閲戦淇℃伅 + */ + @Schema(description = "閲戦淇℃伅", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + private RefundRequest.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; + + /** + * 閫�娆惧竵绉嶏紝鍥哄畾涓衡�淐NY鈥� + */ + @Schema(description = "閫�娆惧竵绉�", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @NotBlank(message = "閫�娆惧竵绉嶄笉鑳戒负绌�") + private String currency; + } +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundResponse.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundResponse.java new file mode 100644 index 0000000..6144eef --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/RefundResponse.java @@ -0,0 +1,114 @@ +package com.dy.pipIrrWechat.wechatpay.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * @author ZhuBaoMin + * @date 2024-07-15 10:30 + * @LastEditTime 2024-07-15 10:30 + * @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 RefundResponse.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; + + } + +} \ No newline at end of file diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/ToRefund.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/ToRefund.java new file mode 100644 index 0000000..95765d5 --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/wechatpay/dto/ToRefund.java @@ -0,0 +1,35 @@ +package com.dy.pipIrrWechat.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-07-15 10:32 + * @LastEditTime 2024-07-15 10:32 + * @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; +} -- Gitblit v1.8.0