diff --git a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java index ee68ade9e..1539b3649 100644 --- a/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/OrderService.java @@ -738,7 +738,11 @@ public class OrderService { data.setStopReasonMsg("人工结算订单,操作人:" + SecurityUtils.getUsername()); // 停止原因 // 结算订单 - orderBasicInfoService.settleOrder(data, orderBasicInfo); + // orderBasicInfoService.settleOrder(data, orderBasicInfo); + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractOrderLogic orderLogic = OrderLogicFactory.getOrderLogic(mode); + orderLogic.settleOrder(data, orderBasicInfo); // 发送停止充电指令 pileRemoteService.remoteStopCharging(orderBasicInfo.getPileSn(), orderBasicInfo.getConnectorCode()); @@ -975,6 +979,9 @@ public class OrderService { } else if (AdapayEventEnum.refund_succeeded.getValue().equals(type)) { // 退款成功 refundSucceeded(data); + } else if (AdapayEventEnum.refund_failed.getValue().equals(type)) { + // 退款失败 + refundFailed(data); } else if (AdapayEventEnum.corp_member_failed.getValue().equals(type)) { // 开户失败 删除 corpMemberFailed(data); @@ -1117,13 +1124,47 @@ public class OrderService { * 汇付退款成功 */ private void refundSucceeded(String data) { + log.info("退款成功 data:{}", JSON.toJSONString(data)); // 保存退款回调记录 adapayRefundRecordService.saveAdapayRefundRecord(data); + + JSONObject jsonObject = JSON.parseObject(data); + JSONObject reason = jsonObject.getJSONObject("reason"); + if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { + // 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额 + UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO(); + String memberId = reason.getString("memberId"); + dto.setMemberId(memberId); + dto.setUpdatePrincipalBalance(new BigDecimal(jsonObject.getString("refund_amt"))); // 更新会员本金金额,单位元 + dto.setType(MemberWalletEnum.TYPE_OUT.getValue()); + dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue()); + memberBasicInfoService.updateMemberBalance(dto); + + // 收到回调,删除缓存 + String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; + redisCache.deleteObject(redisKey); + } + } + + /** + * 退款失败 + * @param data + */ + private void refundFailed(String data) { + log.info("退款失败 data:{}", JSON.toJSONString(data)); + JSONObject jsonObject = JSON.parseObject(data); + JSONObject reason = jsonObject.getJSONObject("reason"); + if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { + String memberId = reason.getString("memberId"); + + // 收到回调,删除缓存 + String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; + redisCache.deleteObject(redisKey); + } } /** * 对公账户创建失败 - * @param data */ private void corpMemberFailed(String data) { // 删除表中的记录 @@ -1143,7 +1184,6 @@ public class OrderService { /** * 对公账户创建成功 - * @param data */ private void corpMemberSucceeded(String data) { JSONObject jsonObject = JSON.parseObject(data); diff --git a/jsowell-admin/src/main/resources/application-dev.yml b/jsowell-admin/src/main/resources/application-dev.yml index 7224b24b0..64cea6c53 100644 --- a/jsowell-admin/src/main/resources/application-dev.yml +++ b/jsowell-admin/src/main/resources/application-dev.yml @@ -38,8 +38,8 @@ spring: master: url: jdbc:mysql://192.168.2.2:3306/jsowell_dev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: jsowell_dev - #url: jdbc:mysql://192.168.2.2:3306/jsowell_prd_copy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - #username: jsowell_prd_copy + #url: jdbc:mysql://121.40.174.65:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + #username: jsowell password: 123456 # 从库数据源 slave: diff --git a/jsowell-admin/src/main/resources/application-pre.yml b/jsowell-admin/src/main/resources/application-pre.yml new file mode 100644 index 000000000..eec87a18d --- /dev/null +++ b/jsowell-admin/src/main/resources/application-pre.yml @@ -0,0 +1,184 @@ +# 项目相关配置 +jsowell: + # 文件路径 示例( Windows配置D:/jsowell/uploadPath,Linux配置 /home/jsowell/uploadPath) + profile: /var/ftp/firmware + +# 数据源配置 +spring: + # redis 配置 + redis: + # 地址 + host: 127.0.0.1 + # 端口,默认为6379 + port: 6379 + # 数据库索引 + database: 0 + # 账号 + # username: jsowell + # 密码 + password: 123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://127.0.0.1:3306/jsowell_prd?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: jsowell + password: js@160829 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: jsowell + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# Swagger配置 +swagger: + # 是否开启swagger + enabled: false + # 请求前缀 + pathMapping: /dev-api + +# 日志配置 +logging: + level: + com.jsowell: info + org.springframework: warn + + +# 二维码前缀 +qrcodeurl: + prefix: https://api.jsowellcloud.com + +# Minio配置 +minio: + url: http://localhost:9000 + accessKey: minioadmin + secretKey: minioadmin + bucketName: jsowell + +aliyunoss: + # 地域节点 + endpoint: http://oss-cn-shanghai.aliyuncs.com + # AccessKey + accessKeyId: LTAI5tBgCN4xuxQF1HV9rf7t + # AccessKey 秘钥 + accessKeySecret: tsxMyujk6KY9h0e4Bx0D7ld16PBUyW + # bucket名称 + bucketName: ydc-oss-prod + # bucket下文件夹的路径 + filehost: img + # 访问域名 + # url: https://ydc-oss-prod.oss-cn-shanghai.aliyuncs.com + url: https://img.jsowellcloud.com + +########################微信支付参数####################################### +#微信商户号 +wechat: + mchId: 1632405339 + #商家API证书序列号 + mchSerialNo: 7596EF543159D21D25F199F82B9045FB9A82D7E0 + #商户在微信公众平台申请服务号对应的APPID + appId: wxbb3e0d474569481d + #回调报文解密V3密钥key + v3Key: bbac689f4654b209de4d6944808ec80b + #微信获取平台证书列表地址 + certificates: + url: https://api.mch.weixin.qq.com/v3/certificates + #微信统一下单Navtive的API地址,用于二维码支付 + unifiedOrder: + url: https://api.mch.weixin.qq.com/v3/pay/transactions/native + #微信统一下单JSAPI的API地址,用于微信小程序 + jsurl: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi + # 申请退款API + refund: + jsurl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds + #异步接收微信支付结果通知的回调地址 + callback: https://api.jsowellcloud.com/uniapp/pay/wechatPayCallback + #异步接收微信退款结果通知的回调地址 + refundCallback: https://api.jsowellcloud.com/uniapp/pay/wechatPayRefundCallback + #商户证书私钥路径 + key: + path: /usr/local/1632405339_20221125_cert/apiclient_key.pem +########################微信支付参数####################################### + +# 汇付支付 +adapay: + debugFlag: false + prodMode: true + callback: https://api.jsowellcloud.com/uniapp/pay/adapayCallback + jsowell: + apiKey: api_live_b9bff039-0598-4491-88e7-06ca6dc7289e + mockApiKey: api_test_15662261-8123-4b51-95d9-ad0af60eab53 + rsaPrivateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOl7qJyrkrks7FKnBPr/Sngub897Ni5Bkn5pEa81zfs+4LrYsuWZQ8G1n7Q8/rjH4G/T7vPX+So41vNU74Sqn6E1b3BpW+wWBULhs9p1JSPT7Kzima4FmPigUr80NLrlVKn5bW+V4/odpN+bJWvpxdd024edHAD8mXX1M1N1lU5ZAgMBAAECgYA+mxbiM6tbFe2kV/6g4vVv9luq0cn8az7BwKCqT44U8Y5G67ZElG0zsuTI6pYOrCHFOpnXLrE0HhudEchL1YiJqW/SDKaoC4oDZf5nybhh11kOR3N5maLqvUz/WxdNy17th/2XxqVfTTu752X9yeeoXDj89N5OxyMl0jmxlhWbgQJBAPeoitR7FCxcjKtcKsEyrtV3T0H2WtQ2Pbku7CGe6VCtL4+DJNeUentn7plBj4IhbH3EwNmyCYzNlfp0X2d8fWkCQQDxWONjt1vV/dyKQYRvSVw/SWQWlR7g2OnHZokU2SNeewiCX2umCdYKh0doN0JHbSTLOGG5IA3+6Vxam+9hzPtxAkEAjr+QHf8/Vn6V+mOqpSdgjNwzS/MC0ZTeKPI52vsswnrAkjjmMHh9zMnQRnf6juhTD38sJY6wYH9TdkRDhXPFGQJATiFYe4+AS2ZDXv6WwPAezN4VaLodpOyTwdmPxxAEQzHRL2N0levZPs9MbpB1BGpw3tkBycx2u28QVsTkWeTiAQJAGRsAVr6Rhhdaq2vTjt9orhMVwt6BCoSQ0zzHSYilv4PMOtSu1Pyt4K8BDv3gjEyAi1GtE7kkJ0dcbsvOGiLzqQ== + appId: app_d0c80cb1-ffc8-48cb-a030-fe9bec823aaa + wechatAppId: wxbb3e0d474569481d + xixiao: + apiKey: api_live_8690aad5-18df-4c94-ba8c-4f9499721c65 + mockApiKey: api_test_a2944395-e6ba-4d59-969a-f629b7a9e53e + rsaPrivateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJ608yEkr5Fxj3ID9fIzavuwW/orgjlD1SIrmZVTwLFzM+ljnr/iFMRRhjJZZGImO+ySj296N+VPujHiiQZqymgIACdORs3YyRvxOeWQoPKiik21mOiF7RRw2GIOQEzqo0MKeJ/qdK89FvwnAIZKRXl+ccH/VTTr68VGWuiLWEK3AgMBAAECgYACsMCaZDvRtGIhJa4KsBJ1N9UnVYt8mwjG7oRJAsV2fKR5pWWwjQ2bEmK7Acbw3wMPDKD/28uMyKA4bkWyZScPO5T2Mhvo28AVOfdsbBht70iKzBAXuqHhHd99+AEmQL9ZcoCYCvoP2JqV8cHp5sXGEvncm9VRsjs3iSTsBYu0WQJBANB6x0DCPnAFXYnKvtBcBmF4jU8pO0iIGtx/ZR/N0pRTbL7cIvh+z6ZqtWo880Xbcli6i1qwZl1ctWwV0yKArOsCQQDC4dN6e8/Gj3FubXLmyLfIrbq7BuHW8kg19t0/wmAXunpkBtFhAA2FD7FYGg+/l6/f6YqWX8nSUr6pFZQI0Z5lAkARvBANIzj6gIpXeWbIBLwKOJ4UuNYxMlrOnQu2K+UY9wvOJJ3Y87ioWHV8RxkOvT856wyFt3HNyWAphKXETpvnAkEAnIjJ1ktW9FXJtfph3bABt0acg5eelYmcqQP2aT1W9BhMMMYtLi3drjCRsYOVfL55fXBYajrcoHzoOmZjtsWw5QJBAM/Wpk6L7BLVi357icleuivPtKsP04Ix5afUpgiFmssEheiLAxr+Zs5/nk/HM6V4Pk8kA0ILaNbRqjfAF5ZnAvk= + appId: app_7848ccb2-f7e7-4841-a968-fbf02cc265ad + wechatAppId: wx20abc5210391649c + +#高德地图相关配置 +aMap: + merchantPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC10OGVHfh4manoO2DE7xA8TipooKDt5WDpazYAKYKs3Rx5auWPoGEdERe1wyOQAJ34DmEULacTv2/mdjarLptL/sj3ba7XVDdAphNzrrIzLsNuzTqK9gxF5EeAAeo06H26rLrXmIvOL0KEsUuwxzuyFB0k3HZc8xM9yl3MXtv2Z0PpiYbvd32sd7HFZiM+H2ldzBZlXp2vC7ca0aj/BckIeWY/vJo5k400glTrcu8FSZbLRaMEzmJEyssVZzh2gPwvPVHoYvRIXpkiqNghyRWmKywC+h07fz21t94yhj+f/rGiK3YY3gv5S2xJ1NgmDfjmJvFMB3o00QH/GlJaiLcNAgMBAAECggEAL25ruyQTcxrbWWtMJnQbbzARHjRxZz6E1sASWV566a/RQtehRaPYUeXoopFi0KlojJLrvoDeamdxwNSsFGJXPy8brHjfuOsOcv4gavhzIqkbcOd3U1M3BnC0Om/FcsIIMs/m+mGgb0yi9Mzv6xE+wIlAxSICeuMq7N7DM5K3nYMIWhbE8kIrurMUpalH+s1FDL3FMOdRgM8L7yAjGoXZUtal6aDwTOsDkjlRmt+IuvqTjREtdBUZRLjKSU2b/3+Z42OOrkongYF74KPuQ1LmQ6Qa1D0O2b37A5ne8VbFjHai8E59Ol2PYwggajqj00G5x3KBUFJYiIhUApq6lXxywQKBgQDjgLExqhi6Op1G1Q0W5W/bKMrHshtcJawsO8C+PBxxPV9Da+5ZkguW4a1ErGCCPI0SVVW1QCTrPyrbJHyw9LteX98cnY6PGy1XVXWL+mKOK0jwL+yV299dMpk4R6u5+oO5ZX9WfoNsF3rEvfMiQxFSaH9HMR7q9GySno3NSzLW0QKBgQDMlyfqhnkDEY/rgRTo42FpX1KVf9JOP0L9+B2Q7Rec7iARuT6/qSxoV6PwNyYixyjbXx8xJQHoUDTRSgY5v543Nmh+bLOyR5NfNRqEmYpKtb0T4qB57jBMiVXcoIPXwcb7yVscAvI/rycDqEkOVgTqRdR0FW7q/svF9EuTzjNjfQKBgQDXtP7NY0U81jSno3xcuECdoQjb3WEZttKPwjwXY7FoIVPA/oYpQVNhxSrfUT3UXos31deFGoOm1ebRj7/2nKVHb0mBvVYdFByikPH6PfbSa/IlYptE4AviNwaWGUaW+ROKZtUc8qmzhHOwNZZhZwv2ggQkQUvaZNTJFDLJc0KJ8QKBgQDD/wr+YlUL24dE1iRx92Maz3cOQaX30CMdqtSoQnqcnIOcdxrmAevJCizDtBGUv7ckcbwwGIP7SttOpNvR9wBbZIQ2mWyNHoTQcM82uOEDMZgxtKqIJOegavEWq6+iwsEd9YiTDT+GQwXdOxrB4SZUSRF/JAlelzogKik9MA2LAQKBgG5cjf9V+6Ka2QjxkIV73/h5P5f08fUNAkLGiUjnH+eozsC3PGnifSwLVlfun8iHDXLwOtUK9xzGJ3yd/a8e9BBhZ8Xyd3Fqz2+q4cxorAz0UhZUnwDPUuLdEABntansYMhkrsOcXAiIQmFmMlgoHmbVHpFmWBy7VL3w2xDn1UM1 + aMapPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArqmh0JZrIhk+tMbF+VE63WaqqLRs+OHZkX3HGyr4cokujgdZb0kAq4jBJa/VjWK2qDXHr2KpoY2/ppmA73oJvNPcuVxR6nwYddcASg6uFCK/vfH5PKVV0W/xKTeOIQ6NTd0wRFZs9zNo1endqgQDvn1d1Rvl1r+18MJ3BXLMjkzCUUurgeO84AIlksYV5Z46hoScyXjSc8lsmwX5r7cwHLajFXdjKo1yOCbzClMqLM29THYuegwHFcT/zp64Nd7+nawWWuPOgfkr0MTGrNCkV8ywpbyG0XVewMkdN6pTaZNvhMnLH00VkXASPB51vUjhs4WBiFZth9q3rZBkaEYSMQIDAQAB + appId: 202306150188103814 + # apiUrl: https://restapi.amap.com/rest/openmp/devgw?key=7967738241f0a580b5a1342f43793a61 + apiUrl: https://restapi.amap.com/rest/openmp/gw?key=7967738241f0a580b5a1342f43793a61 + openId: 2089000923284502 \ No newline at end of file diff --git a/jsowell-admin/src/test/java/SpringBootTestController.java b/jsowell-admin/src/test/java/SpringBootTestController.java index 05fcbc768..9f89e8b29 100644 --- a/jsowell-admin/src/test/java/SpringBootTestController.java +++ b/jsowell-admin/src/test/java/SpringBootTestController.java @@ -1939,7 +1939,7 @@ public class SpringBootTestController { .valleyUsedElectricity("0") .build(); - orderBasicInfoService.settleOrder(data, orderInfo); + // orderBasicInfoService.settleOrder(data, orderInfo); } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java index df0b5b189..cbbd9a2bb 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java @@ -23,6 +23,8 @@ import com.jsowell.pile.domain.ThirdPartyStationRelation; import com.jsowell.pile.domain.ThirdpartyParkingConfig; import com.jsowell.pile.dto.lutongyunting.BindCouponDTO; import com.jsowell.pile.service.*; +import com.jsowell.pile.service.orderlogic.AbstractOrderLogic; +import com.jsowell.pile.service.orderlogic.OrderLogicFactory; import com.jsowell.pile.vo.base.ThirdPartyStationRelationVO; import com.jsowell.pile.vo.web.PileStationVO; import com.jsowell.thirdparty.lianlian.service.LianLianService; @@ -67,10 +69,7 @@ public class TransactionRecordsRequestHandler extends AbstractHandler { private IOrderBasicInfoService orderBasicInfoService; @Autowired - private IPileAuthCardService pileAuthCardService; - - @Autowired - private IThirdPartySettingInfoService thirdPartySettingInfoService; + private IPileMerchantInfoService pileMerchantInfoService; @Autowired private LianLianService lianLianService; @@ -78,9 +77,6 @@ public class TransactionRecordsRequestHandler extends AbstractHandler { @Autowired private IThirdPartyStationRelationService thirdPartyStationRelationService; - @Autowired - private IMemberPlateNumberRelationService memberPlateNumberRelationService; - @Autowired private IPileStationInfoService pileStationInfoService; @@ -625,7 +621,11 @@ public class TransactionRecordsRequestHandler extends AbstractHandler { // 结算订单操作 try { - orderBasicInfoService.settleOrder(data, orderBasicInfo); + // orderBasicInfoService.settleOrder(data, orderBasicInfo); + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); + AbstractOrderLogic orderLogic = OrderLogicFactory.getOrderLogic(mode); + orderLogic.settleOrder(data, orderBasicInfo); } catch (Exception e) { log.error("结算订单发生异常", e); } diff --git a/jsowell-pile/src/main/java/com/jsowell/adapay/operation/PaymentRefundOperation.java b/jsowell-pile/src/main/java/com/jsowell/adapay/operation/PaymentRefundOperation.java new file mode 100644 index 000000000..d7cc4fc5b --- /dev/null +++ b/jsowell-pile/src/main/java/com/jsowell/adapay/operation/PaymentRefundOperation.java @@ -0,0 +1,19 @@ +package com.jsowell.adapay.operation; + +import lombok.*; + +import java.math.BigDecimal; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class PaymentRefundOperation extends AdapayOperationInfo{ + private String paymentId; + private BigDecimal refundAmt; + private String wechatAppId; + private String memberId; + private String scenarioType; + private String orderCode; +} diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/IPileMerchantInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/IPileMerchantInfoService.java index ace40cf95..c9c532749 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/IPileMerchantInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/IPileMerchantInfoService.java @@ -110,7 +110,9 @@ public interface IPileMerchantInfoService { String getDelayModeByWechatAppId(String wechatAppId); - /** + String getDelayModeByMerchantId(String merchantId); + + /** * 通过merchantId获取一级运营商信息 */ PileMerchantInfo getFirstLevelMerchantByMerchantId(String merchantId); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index 06df5037c..d9c5a96e3 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -38,6 +38,8 @@ import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.mapper.OrderBasicInfoMapper; import com.jsowell.pile.service.*; +import com.jsowell.pile.service.orderlogic.AbstractOrderLogic; +import com.jsowell.pile.service.orderlogic.OrderLogicFactory; import com.jsowell.pile.transaction.dto.ClearingBillTransactionDTO; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; @@ -445,7 +447,12 @@ public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { .flatUsedElectricity(Constants.ZERO) .valleyUsedElectricity(Constants.ZERO) .build(); - settleOrder(data, orderInfo); + // settleOrder(data, orderInfo); + + // 新逻辑 + String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderInfo.getMerchantId()); + AbstractOrderLogic orderLogic = OrderLogicFactory.getOrderLogic(mode); + orderLogic.settleOrder(data, orderInfo); } /** diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileMerchantInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileMerchantInfoServiceImpl.java index b445ce823..e8a2a856b 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileMerchantInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileMerchantInfoServiceImpl.java @@ -422,6 +422,20 @@ public class PileMerchantInfoServiceImpl implements IPileMerchantInfoService { return merchant.getDelayMode(); } + /** + * 通过运营商id查询一级运营商配置的delayMode + * @param merchantId + * @return + */ + @Override + public String getDelayModeByMerchantId(String merchantId) { + PileMerchantInfo merchant = getFirstLevelMerchantByMerchantId(merchantId); + if (merchant == null) { + return null; + } + return merchant.getAppId(); + } + @Override public PileMerchantInfo getFirstLevelMerchantByMerchantId(String merchantId) { if (StringUtils.isBlank(merchantId)) { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/AbstractOrderLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/AbstractOrderLogic.java index 0e7f1fbfe..c0c4bd25b 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/AbstractOrderLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/AbstractOrderLogic.java @@ -15,10 +15,7 @@ import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.domain.*; -import com.jsowell.pile.dto.BasicPileDTO; -import com.jsowell.pile.dto.GenerateOrderDTO; -import com.jsowell.pile.dto.PayOrderDTO; -import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO; +import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.service.TransactionService; import com.jsowell.pile.vo.uniapp.PileConnectorDetailVO; @@ -31,6 +28,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import javax.annotation.Resource; import java.math.BigDecimal; @@ -45,6 +43,9 @@ import java.util.Map; public abstract class AbstractOrderLogic implements InitializingBean { protected Logger logger = LoggerFactory.getLogger(this.getClass()); + @Value("${adapay.callback}") + protected String ADAPAY_CALLBACK_URL; + @Resource protected IOrderBasicInfoService orderBasicInfoService; @@ -116,7 +117,21 @@ public abstract class AbstractOrderLogic implements InitializingBean { */ public abstract void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo); + /** + * 订单退款 + */ + public abstract void refundOrder(OrderBasicInfo orderBasicInfo); + /** + * 余额充值 + */ + public abstract Map rechargeBalance(WeixinPayDTO dto); + + /** + * 余额退款 + * @param dto + */ + public abstract void refundBalance(ApplyRefundDTO dto); /** * 订单支付成功 支付回调 diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/DelayMerchantOrderLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/DelayMerchantOrderLogic.java index eead0e30b..27b2e9e9d 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/DelayMerchantOrderLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/DelayMerchantOrderLogic.java @@ -3,10 +3,18 @@ package com.jsowell.pile.service.orderlogic; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.huifu.adapay.core.exception.BaseAdaPayException; +import com.huifu.adapay.model.Payment; +import com.jsowell.adapay.common.CreateAdaPaymentParam; +import com.jsowell.adapay.config.AbstractAdapayConfig; +import com.jsowell.adapay.factory.AdapayConfigFactory; import com.jsowell.adapay.operation.PaymentReverseOperation; import com.jsowell.adapay.response.PaymentReverseResponse; +import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; import com.jsowell.common.enums.AcquirerEnum; @@ -15,14 +23,13 @@ import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.adapay.MerchantDelayModeEnum; import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; +import com.jsowell.common.util.AdapayUtil; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.IdUtils; +import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; -import com.jsowell.pile.dto.ApplyRefundDTO; -import com.jsowell.pile.dto.GenerateOrderDTO; -import com.jsowell.pile.dto.PayOrderDTO; -import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO; +import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.MemberVO; import com.jsowell.pile.vo.web.BalanceDeductionAmountVO; @@ -30,6 +37,7 @@ import com.jsowell.pile.vo.web.BillingTemplateVO; import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO; import com.jsowell.wxpay.dto.WechatSendMsgDTO; import org.apache.commons.collections4.CollectionUtils; +import org.springframework.cglib.beans.BeanMap; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -367,21 +375,7 @@ public class DelayMerchantOrderLogic extends AbstractOrderLogic { transactionService.doUpdateOrder(dto); // 订单退款 - try { - String payMode = orderBasicInfo.getPayMode(); - if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { - // 余额支付 - balancePaymentOrderRefund(orderBasicInfo); - } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { - // 微信支付 - onlinePaymentOrderRefund(orderBasicInfo); - } else { - // 白名单支付 - logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); - } - } catch (Exception e) { - logger.error("{}-订单退款逻辑异常orderCode:{}", this.getClass().getSimpleName(), orderBasicInfo.getOrderCode(), e); - } + refundOrder(orderBasicInfo); // 将卡/vin状态解锁 if (!StringUtils.equals("0000000000000000", data.getLogicCard())) { @@ -416,10 +410,134 @@ public class DelayMerchantOrderLogic extends AbstractOrderLogic { } } + @Override + public void refundOrder(OrderBasicInfo orderBasicInfo) { + try { + String payMode = orderBasicInfo.getPayMode(); + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { + // 余额支付 + balancePaymentOrderRefund(orderBasicInfo); + } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { + // 微信支付 + onlinePaymentOrderRefund(orderBasicInfo); + } else { + // 白名单支付 + logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); + } + } catch (Exception e) { + logger.error("{}-订单退款逻辑异常orderCode:{}", this.getClass().getSimpleName(), orderBasicInfo.getOrderCode(), e); + } + } + + /** + * 余额充值 + * + * @param dto + */ + @Override + public Map rechargeBalance(WeixinPayDTO dto) { + // 获取支付配置 + AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); + if (config == null) { + throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); + } + logger.info("使用汇付支付充值余额 支付配置参数:{}", JSON.toJSONString(config)); + + String goodsTitle = "充值余额"; + String goodsDesc = "会员充值余额"; + + // 查询延时支付模式,由一级运营商配置决定 + String delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId()); + String payMode = MerchantDelayModeEnum.getAdapayPayMode(delayMode); + // 封装对象 + // String payMode = Constants.ADAPAY_PAY_MODE_DELAY; // 汇付延时分账 + CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); + createAdaPaymentParam.setOrder_no(SnowflakeIdWorker.getSnowflakeId()); + createAdaPaymentParam.setPay_amt(AdapayUtil.formatAmount(dto.getAmount())); + // createAdaPaymentParam.setApp_id(ADAPAY_APP_ID); // 移动到配置文件中 + createAdaPaymentParam.setApp_id(config.getAdapayAppId()); // 移动到配置文件中 + createAdaPaymentParam.setPay_channel("wx_lite"); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求 + createAdaPaymentParam.setGoods_title(goodsTitle); + createAdaPaymentParam.setGoods_desc(goodsDesc); + createAdaPaymentParam.setExpend(JSONObject.toJSONString(ImmutableMap.of("open_id", dto.getOpenId()))); + // 异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 + createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL); + Map map = Maps.newHashMap(); + map.put("type", ScenarioEnum.BALANCE.getValue()); + map.put("payMode", payMode); + map.put("memberId", dto.getMemberId()); + createAdaPaymentParam.setDescription(JSON.toJSONString(map)); + // 延时分账 + if (StringUtils.isNotBlank(payMode)) { + createAdaPaymentParam.setPay_mode(payMode); + } + try { + logger.info("创建汇付支付参数:{}", JSONObject.toJSONString(createAdaPaymentParam)); + Map response = Payment.create(BeanMap.create(createAdaPaymentParam), config.getWechatAppId()); + logger.info("创建汇付支付参数反参:{}", JSONObject.toJSONString(response)); + if (response != null && !response.isEmpty()) { + JSONObject jsonObject = JSONObject.parseObject(response.get("expend").toString()); + JSONObject pay_info = jsonObject.getJSONObject("pay_info"); + return JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() { + }); + } + } catch (BaseAdaPayException e) { + logger.error("汇付-获取支付对象发生异常", e); + } + return null; + } + + /** + * 余额退款 + * + * @param dto + */ + @Override + public void refundBalance(ApplyRefundDTO dto) { + // 做个拦截,如果前一笔退款没有完成,就抛异常 + String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + dto.getMemberId(); + PaymentReverseResponse redisResult = redisCache.getCacheObject(redisKey); + if (Objects.nonNull(redisResult)) { + throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_REFUNDS_ARE_IN_PROGRESS_ERROR); + } + + // 查会员余额 + MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); + if (memberVO == null) { + throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_NOT_FOUND_ERROR); + } + + // 校验退款金额 + BigDecimal principalBalance = memberVO.getPrincipalBalance(); + BigDecimal refundAmount = dto.getRefundAmount(); + if (refundAmount.compareTo(principalBalance) > 0) { + throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR); + } + + // 查询用户充值余额订单 过滤掉已经退款的充值订单 + List list = calculateTheBalanceDeductionAmount(dto.getMemberId(), refundAmount); + for (BalanceDeductionAmountVO vo : list) { + String paymentId = vo.getPaymentId(); + BigDecimal deductionAmount = vo.getDeductionAmount(); + + // 调汇付的交易撤销接口 + PaymentReverseResponse request = adapayService.createPaymentReverseRequest(paymentId, deductionAmount, + dto.getWechatAppId(), dto.getMemberId(), ScenarioEnum.BALANCE.getValue(), null); + + if (request != null && request.isNotFailed()) { + memberAdapayRecordService.updateRefundAmount(paymentId, deductionAmount); + + // 放缓存 + redisCache.setCacheObject(redisKey, request, CacheConstants.cache_expire_time_30m); + } + } + } + /** * 余额支付订单退款 */ - private void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo) { + @Transactional(rollbackFor = Exception.class) + public void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo) { logger.info("{}-余额支付订单退款start orderBasicInfo:{}", this.getClass().getSimpleName(), JSON.toJSONString(orderBasicInfo)); // 订单编号 String orderCode = orderBasicInfo.getOrderCode(); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/NotDelayMerchantOrderLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/NotDelayMerchantOrderLogic.java index a63763aa5..a8d222a90 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/NotDelayMerchantOrderLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/orderlogic/NotDelayMerchantOrderLogic.java @@ -2,9 +2,17 @@ package com.jsowell.pile.service.orderlogic; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.TypeReference; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.huifu.adapay.core.exception.BaseAdaPayException; +import com.huifu.adapay.model.Payment; +import com.jsowell.adapay.common.CreateAdaPaymentParam; +import com.jsowell.adapay.config.AbstractAdapayConfig; +import com.jsowell.adapay.factory.AdapayConfigFactory; import com.jsowell.adapay.response.RefundResponse; +import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; import com.jsowell.common.enums.AcquirerEnum; @@ -13,14 +21,13 @@ import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.adapay.MerchantDelayModeEnum; import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; +import com.jsowell.common.util.AdapayUtil; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.IdUtils; +import com.jsowell.common.util.id.SnowflakeIdWorker; import com.jsowell.pile.domain.*; -import com.jsowell.pile.dto.ApplyRefundDTO; -import com.jsowell.pile.dto.GenerateOrderDTO; -import com.jsowell.pile.dto.PayOrderDTO; -import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO; +import com.jsowell.pile.dto.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.vo.uniapp.MemberVO; import com.jsowell.pile.vo.web.BalanceDeductionAmountVO; @@ -28,7 +35,9 @@ import com.jsowell.pile.vo.web.BillingTemplateVO; import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO; import com.jsowell.wxpay.dto.WechatSendMsgDTO; import org.apache.commons.collections4.CollectionUtils; +import org.springframework.cglib.beans.BeanMap; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.text.ParseException; @@ -350,21 +359,7 @@ public class NotDelayMerchantOrderLogic extends AbstractOrderLogic{ transactionService.doUpdateOrder(dto); // 订单退款 - try { - String payMode = orderBasicInfo.getPayMode(); - if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { - // 余额支付 - balancePaymentOrderRefund(orderBasicInfo); - } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { - // 微信支付 - onlinePaymentOrderRefund(orderBasicInfo); - } else { - // 白名单支付 - logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); - } - } catch (Exception e) { - logger.error("{}-订单退款逻辑异常orderCode:{}", this.getClass().getSimpleName(), orderBasicInfo.getOrderCode(), e); - } + refundOrder(orderBasicInfo); // 将卡/vin状态解锁 if (!StringUtils.equals("0000000000000000", data.getLogicCard())) { @@ -387,6 +382,129 @@ public class NotDelayMerchantOrderLogic extends AbstractOrderLogic{ logger.info("结算订单end:{} OrderTransactionDTO:{}", orderBasicInfo.getOrderCode(), JSONObject.toJSONString(dto)); } + @Override + public void refundOrder(OrderBasicInfo orderBasicInfo) { + try { + String payMode = orderBasicInfo.getPayMode(); + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { + // 余额支付 + balancePaymentOrderRefund(orderBasicInfo); + } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { + // 微信支付 + onlinePaymentOrderRefund(orderBasicInfo); + } else { + // 白名单支付 + logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); + } + } catch (Exception e) { + logger.error("{}-订单退款逻辑异常orderCode:{}", this.getClass().getSimpleName(), orderBasicInfo.getOrderCode(), e); + } + } + + /** + * 余额充值 + * + * @param dto + */ + @Override + public Map rechargeBalance(WeixinPayDTO dto) { + // 获取支付配置 + AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId()); + if (config == null) { + throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR); + } + logger.info("使用汇付支付充值余额 支付配置参数:{}", JSON.toJSONString(config)); + + String goodsTitle = "充值余额"; + String goodsDesc = "会员充值余额"; + + // 查询延时支付模式,由一级运营商配置决定 + String delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId()); + String payMode = MerchantDelayModeEnum.getAdapayPayMode(delayMode); + // 封装对象 + // String payMode = Constants.ADAPAY_PAY_MODE_DELAY; // 汇付延时分账 + CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); + createAdaPaymentParam.setOrder_no(SnowflakeIdWorker.getSnowflakeId()); + createAdaPaymentParam.setPay_amt(AdapayUtil.formatAmount(dto.getAmount())); + // createAdaPaymentParam.setApp_id(ADAPAY_APP_ID); // 移动到配置文件中 + createAdaPaymentParam.setApp_id(config.getAdapayAppId()); // 移动到配置文件中 + createAdaPaymentParam.setPay_channel("wx_lite"); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求 + createAdaPaymentParam.setGoods_title(goodsTitle); + createAdaPaymentParam.setGoods_desc(goodsDesc); + createAdaPaymentParam.setExpend(JSONObject.toJSONString(ImmutableMap.of("open_id", dto.getOpenId()))); + // 异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 + createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL); + Map map = Maps.newHashMap(); + map.put("type", ScenarioEnum.BALANCE.getValue()); + map.put("payMode", payMode); + map.put("memberId", dto.getMemberId()); + createAdaPaymentParam.setDescription(JSON.toJSONString(map)); + // 延时分账 + if (StringUtils.isNotBlank(payMode)) { + createAdaPaymentParam.setPay_mode(payMode); + } + try { + logger.info("创建汇付支付参数:{}", JSONObject.toJSONString(createAdaPaymentParam)); + Map response = Payment.create(BeanMap.create(createAdaPaymentParam), config.getWechatAppId()); + logger.info("创建汇付支付参数反参:{}", JSONObject.toJSONString(response)); + if (response != null && !response.isEmpty()) { + JSONObject jsonObject = JSONObject.parseObject(response.get("expend").toString()); + JSONObject pay_info = jsonObject.getJSONObject("pay_info"); + return JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() { + }); + } + } catch (BaseAdaPayException e) { + logger.error("汇付-获取支付对象发生异常", e); + } + return null; + } + + /** + * 余额退款 + * + * @param dto + */ + @Override + public void refundBalance(ApplyRefundDTO dto) { + // 做个拦截,如果前一笔退款没有完成,就抛异常 + String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + dto.getMemberId(); + RefundResponse redisResult = redisCache.getCacheObject(redisKey); + if (Objects.nonNull(redisResult)) { + throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_REFUNDS_ARE_IN_PROGRESS_ERROR); + } + + // 查会员余额 + MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); + if (memberVO == null) { + throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_NOT_FOUND_ERROR); + } + + // 校验退款金额 + BigDecimal principalBalance = memberVO.getPrincipalBalance(); + BigDecimal refundAmount = dto.getRefundAmount(); + if (refundAmount.compareTo(principalBalance) > 0) { + throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR); + } + + // 查询用户充值余额订单 过滤掉已经退款的充值订单 + List list = calculateTheBalanceDeductionAmount(dto.getMemberId(), refundAmount); + for (BalanceDeductionAmountVO vo : list) { + String paymentId = vo.getPaymentId(); + BigDecimal deductionAmount = vo.getDeductionAmount(); + + // 调汇付的交易退款接口 + RefundResponse response = adapayService.createRefundRequest(paymentId, refundAmount, + dto.getWechatAppId(), dto.getMemberId(), ScenarioEnum.ORDER.getValue(), dto.getOrderCode()); + + if (response != null && response.isNotFailed()) { + memberAdapayRecordService.updateRefundAmount(paymentId, deductionAmount); + + // 放缓存 + redisCache.setCacheObject(redisKey, response, CacheConstants.cache_expire_time_30m); + } + } + } + // uniApp 发送停止充电订阅消息 private void sendMsg(OrderBasicInfo orderBasicInfo) { try { @@ -404,7 +522,8 @@ public class NotDelayMerchantOrderLogic extends AbstractOrderLogic{ * * @param orderBasicInfo */ - private void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo) { + @Transactional(rollbackFor = Exception.class) + public void balancePaymentOrderRefund(OrderBasicInfo orderBasicInfo) { logger.info("{}-余额支付订单退款start orderBasicInfo:{}", this.getClass().getSimpleName(), JSON.toJSONString(orderBasicInfo)); // 订单编号 String orderCode = orderBasicInfo.getOrderCode(); diff --git a/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WechatPayConfig.java b/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WechatPayConfig.java index 511c166f2..0a04880fc 100644 --- a/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WechatPayConfig.java +++ b/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WechatPayConfig.java @@ -5,11 +5,9 @@ import com.jsowell.wxpay.common.WeChatPayParameter; import com.jsowell.wxpay.utils.WechatPayUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -@Order(value = 2) -@Component +// @Order(value = 2) +// @Component public class WechatPayConfig implements CommandLineRunner { /** * 公众号appid diff --git a/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WeixinLoginProperties.java b/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WeixinLoginProperties.java index 31a38be68..5fb089e7f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WeixinLoginProperties.java +++ b/jsowell-pile/src/main/java/com/jsowell/wxpay/config/WeixinLoginProperties.java @@ -2,9 +2,8 @@ package com.jsowell.wxpay.config; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -@Component +// @Component public class WeixinLoginProperties implements InitializingBean { @Value("${weixin.login.gateway}")