From b394cc6d13b6ca8ac08e6fe33936a69680c0d82e Mon Sep 17 00:00:00 2001 From: RuicyWu <1063154311@qq.com> Date: Tue, 21 Apr 2026 20:04:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../org/chenyon/assets/AssetsController.java | 20 + .../chenyon/assets/AssetsQueryService.java | 25 +- .../assets/vo/AssetsPageQueryCondition.java | 47 ++ .../java/org/chenyon/assets/vo/AssetsVo.java | 24 +- .../java/org/chenyon/bill/BillController.java | 38 ++ .../java/org/chenyon/bill/BillService.java | 9 + .../org/chenyon/bill/BillStatusUpdateVo.java | 15 + .../java/org/chenyon/bill/UnpaidBillVo.java | 41 ++ .../java/org/chenyon/constants/OaApiUrl.java | 12 + .../contract/ContractQueryCondition.java | 18 + .../org/chenyon/contract/ContractService.java | 28 +- .../chenyon/fallback/FallbackController.java | 4 +- .../java/org/chenyon/file/AttachmentVo.java | 22 + .../chenyon/file/OaFileHandlerService.java | 47 +- .../org/chenyon/file/OaFileLocalSubRef.java | 9 + .../chenyon/location/IpLocationService.java | 27 +- .../chenyon/location/LocateController.java | 54 +- .../java/org/chenyon/message/Message.java | 28 + .../chenyon/message/MessageController.java | 17 +- .../java/org/chenyon/message/MessageDao.xml | 4 +- .../message/MessageQueryCondition.java | 18 + .../org/chenyon/message/MessageService.java | 38 +- .../java/org/chenyon/message/MessageVo.java | 38 ++ .../org/chenyon/message/SubcribeMsgMode.java | 7 + .../chenyon/message/SubscribeMsgSender.java | 6 + .../message/WeAppMiniProgramMsgSender.java | 111 ++++ .../java/org/chenyon/notice/NoticeVo.java | 8 +- .../java/org/chenyon/oa/OaAssetService.java | 10 + .../java/org/chenyon/oa/OaBillService.java | 5 + .../java/org/chenyon/oa/OaNoticeService.java | 16 +- .../java/org/chenyon/oa/SeeyonHttpClient.java | 11 +- .../java/org/chenyon/oa/asset/OaAssetsVo.java | 43 +- .../org/chenyon/oa/notice/OaNoticeVo.java | 111 ++++ .../java/org/chenyon/pay/CreateOrderResp.java | 28 + src/main/java/org/chenyon/pay/Goods.java | 30 +- .../java/org/chenyon/pay/LocalKvRedis.java | 76 +++ src/main/java/org/chenyon/pay/Order.java | 52 -- .../java/org/chenyon/pay/OrderService.java | 240 +++++++++ src/main/java/org/chenyon/pay/OrderVo.java | 80 +++ src/main/java/org/chenyon/pay/SubOrder.java | 20 + src/main/java/org/chenyon/pay/TmHttpUtil.java | 190 +++++++ .../java/org/chenyon/pay/TmPayService.java | 51 +- .../org/chenyon/pay/TmPaySignatureUtils.java | 69 +++ .../java/org/chenyon/pay/TmTokenService.java | 133 +++++ .../org/chenyon/pay/UnifiedOrderRequest.java | 45 +- src/main/java/org/chenyon/pay/WeAppOrder.java | 86 +++ .../java/org/chenyon/pay/WeAppOrderDao.java | 8 + .../java/org/chenyon/pay/WeAppOrderDao.xml | 13 + .../java/org/chenyon/pay/WeAppSubOrder.java | 56 ++ .../org/chenyon/pay/WeAppSubOrderDao.java | 15 + .../java/org/chenyon/pay/WeAppSubOrderDao.xml | 7 + .../org/chenyon/pay/shopcar/GoodsInfo.java | 32 ++ .../chenyon/pay/shopcar/MiniPayRequest.java | 58 +++ .../chenyon/pay/shopcar/RetCommParams.java | 16 + .../java/org/chenyon/pay/shopcar/SatInfo.java | 105 ++++ .../shopcar/ShopCarOrderCreateRequest.java | 493 ++++++++++++++++++ .../pay/shopcar/ShopCarOrderQueryRequest.java | 79 +++ .../chenyon/pay/shopcar/TmPayOrderRespVo.java | 23 + .../chenyon/pay/shopcar/TmPayResponse.java | 22 + .../java/org/chenyon/pay/shopcar/VaFld.java | 81 +++ .../potential/PotentialController.java | 17 +- .../org/chenyon/potential/ViewRecordVo.java | 9 + .../reservation/ReservateController.java | 2 +- .../org/chenyon/user/LoginController.java | 17 + src/main/java/org/chenyon/user/UserDao.java | 3 +- src/main/java/org/chenyon/user/UserDao.xml | 5 +- .../java/org/chenyon/user/UserService.java | 17 +- src/main/java/org/chenyon/user/UserVo.java | 9 + .../java/org/chenyon/vr/VrDataController.java | 29 ++ .../java/org/chenyon/vr/VrDataService.java | 45 ++ src/main/java/org/chenyon/vr/VrDataVo.java | 33 ++ src/main/java/org/chenyon/vr/VrSpace.java | 61 +++ src/main/java/org/chenyon/vr/Vrhotspot.java | 40 ++ .../chenyon/pay/TmPayTokenServiceTest.java | 27 + 75 files changed, 3143 insertions(+), 192 deletions(-) create mode 100644 src/main/java/org/chenyon/bill/BillStatusUpdateVo.java create mode 100644 src/main/java/org/chenyon/bill/UnpaidBillVo.java create mode 100644 src/main/java/org/chenyon/file/AttachmentVo.java create mode 100644 src/main/java/org/chenyon/message/SubcribeMsgMode.java create mode 100644 src/main/java/org/chenyon/message/SubscribeMsgSender.java create mode 100644 src/main/java/org/chenyon/message/WeAppMiniProgramMsgSender.java create mode 100644 src/main/java/org/chenyon/pay/CreateOrderResp.java create mode 100644 src/main/java/org/chenyon/pay/LocalKvRedis.java delete mode 100644 src/main/java/org/chenyon/pay/Order.java create mode 100644 src/main/java/org/chenyon/pay/OrderService.java create mode 100644 src/main/java/org/chenyon/pay/OrderVo.java create mode 100644 src/main/java/org/chenyon/pay/TmHttpUtil.java create mode 100644 src/main/java/org/chenyon/pay/TmPaySignatureUtils.java create mode 100644 src/main/java/org/chenyon/pay/TmTokenService.java create mode 100644 src/main/java/org/chenyon/pay/WeAppOrder.java create mode 100644 src/main/java/org/chenyon/pay/WeAppOrderDao.java create mode 100644 src/main/java/org/chenyon/pay/WeAppOrderDao.xml create mode 100644 src/main/java/org/chenyon/pay/WeAppSubOrder.java create mode 100644 src/main/java/org/chenyon/pay/WeAppSubOrderDao.java create mode 100644 src/main/java/org/chenyon/pay/WeAppSubOrderDao.xml create mode 100644 src/main/java/org/chenyon/pay/shopcar/GoodsInfo.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/MiniPayRequest.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/RetCommParams.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/SatInfo.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/ShopCarOrderCreateRequest.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/ShopCarOrderQueryRequest.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/TmPayOrderRespVo.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/TmPayResponse.java create mode 100644 src/main/java/org/chenyon/pay/shopcar/VaFld.java create mode 100644 src/main/java/org/chenyon/vr/VrDataController.java create mode 100644 src/main/java/org/chenyon/vr/VrDataService.java create mode 100644 src/main/java/org/chenyon/vr/VrDataVo.java create mode 100644 src/main/java/org/chenyon/vr/VrSpace.java create mode 100644 src/main/java/org/chenyon/vr/Vrhotspot.java create mode 100644 src/test/java/org/chenyon/pay/TmPayTokenServiceTest.java diff --git a/pom.xml b/pom.xml index 5adc37a..6bd4ef8 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ com.maxmind.geoip2 geoip2 - 2.12.0 + 2.15.0 org.lionsoul diff --git a/src/main/java/org/chenyon/assets/AssetsController.java b/src/main/java/org/chenyon/assets/AssetsController.java index c935b33..d3cf862 100644 --- a/src/main/java/org/chenyon/assets/AssetsController.java +++ b/src/main/java/org/chenyon/assets/AssetsController.java @@ -63,4 +63,24 @@ public class AssetsController { return ResultMessage.success(new AssetsVo()); } + @GetMapping("/getBizZones") + public ResultMessage getBizZones() { + try { + return ResultMessage.success(assetsQueryService.getBizZones()); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return ResultMessage.success(new ArrayList<>()); + } + + @GetMapping("/getFeatures") + public ResultMessage getFeatures() { + try { + return ResultMessage.success(assetsQueryService.getFeatures()); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return ResultMessage.success(new ArrayList<>()); + } + } diff --git a/src/main/java/org/chenyon/assets/AssetsQueryService.java b/src/main/java/org/chenyon/assets/AssetsQueryService.java index 203c42b..d2982eb 100644 --- a/src/main/java/org/chenyon/assets/AssetsQueryService.java +++ b/src/main/java/org/chenyon/assets/AssetsQueryService.java @@ -45,8 +45,9 @@ public class AssetsQueryService { assetsVo.setAssetsName(oaAssetsVo.getAssetsName()); assetsVo.setDetailImgs(oaFileHandlerService.getUrls(true,oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(),"AssetsDetailImg",oaAssetsVo.getDetailImg())); assetsVo.setVrImgs(oaFileHandlerService.getUrls(true,oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(),"AssetsVrImg",oaAssetsVo.getVrImg())); - if(assetsVo.getDetailImgs() != null && assetsVo.getDetailImgs().size() > 1) { - assetsVo.setCoverImgUrl(assetsVo.getDetailImgs().get(0)); + List assetsCoverImg = oaFileHandlerService.getUrls(true, oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(), "AssetsCoverImg", oaAssetsVo.getCoverImg()); + if(assetsCoverImg != null && assetsCoverImg.size() >= 1) { + assetsVo.setCoverImgUrl(assetsCoverImg.get(0)); } assetsVoList.add(assetsVo); } @@ -54,6 +55,14 @@ public class AssetsQueryService { return pageResult; } + public List getBizZones() throws Exception { + return oaAssetService.getBizZones(); + } + + public List getFeatures() throws Exception { + return oaAssetService.getFeatures(); + } + public AssetsVo getAssetsById(String id) throws Exception { OaAssetsVo oaAssetsVo = oaAssetService.queryAssetsDetail(id); AssetsVo assetsVo = new AssetsVo(); @@ -76,12 +85,20 @@ public class AssetsQueryService { assetsVo.setLongitude(oaAssetsVo.getLongitude()); assetsVo.setLayout(oaAssetsVo.getLayout()); assetsVo.setUnitNo(oaAssetsVo.getUnitNo()); + assetsVo.setOrientation(oaAssetsVo.getOrientation()); + assetsVo.setBizZone(oaAssetsVo.getBizZone()); + List features = oaAssetsVo.getFeatures() == null ? new ArrayList<>() : oaAssetsVo.getFeatures(); + if(oaAssetsVo.getRenovationStatus() != null) { + features.add(oaAssetsVo.getRenovationStatus()); + } + assetsVo.setFeatures(features); assetsVo.setManagerName(oaAssetsVo.getManagerName()); assetsVo.setManagerPhone(oaAssetsVo.getManagerPhone()); assetsVo.setDetailImgs(oaFileHandlerService.getUrls(true,oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(),"AssetsDetailImg",oaAssetsVo.getDetailImg())); assetsVo.setVrImgs(oaFileHandlerService.getUrls(true,oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(),"AssetsVrImg",oaAssetsVo.getVrImg())); - if(assetsVo.getDetailImgs() != null) { - assetsVo.setCoverImgUrl(assetsVo.getDetailImgs().get(0)); + List assetsCoverImg = oaFileHandlerService.getUrls(true, oaAssetsVo.getAssetsNo(), oaAssetsVo.getFormId(), "AssetsCoverImg", oaAssetsVo.getCoverImg()); + if(assetsCoverImg != null && assetsCoverImg.size() >= 1) { + assetsVo.setCoverImgUrl(assetsCoverImg.get(0)); } return assetsVo; } diff --git a/src/main/java/org/chenyon/assets/vo/AssetsPageQueryCondition.java b/src/main/java/org/chenyon/assets/vo/AssetsPageQueryCondition.java index 4bfc8bb..ebd81f6 100644 --- a/src/main/java/org/chenyon/assets/vo/AssetsPageQueryCondition.java +++ b/src/main/java/org/chenyon/assets/vo/AssetsPageQueryCondition.java @@ -2,6 +2,8 @@ package org.chenyon.assets.vo; import org.rcy.framework.api.entity.PageQueryRequest; +import java.util.List; + public class AssetsPageQueryCondition extends PageQueryRequest { private String assetsNo;//资产编号 @@ -13,6 +15,11 @@ public class AssetsPageQueryCondition extends PageQueryRequest { private String assetsName;//资产名称 private String cusNo; //客商编码 private String keyWord; //关键字 + private String bizZone; //商圈 + private String rentFeeRange; + private String layout; + private String renovationStatus; //装修状态 + private String features; //特点 public String getAssetsType() { return assetsType; @@ -85,4 +92,44 @@ public class AssetsPageQueryCondition extends PageQueryRequest { public void setKeyWord(String keyWord) { this.keyWord = keyWord; } + + public String getRentFeeRange() { + return rentFeeRange; + } + + public void setRentFeeRange(String rentFeeRange) { + this.rentFeeRange = rentFeeRange; + } + + public String getLayout() { + return layout; + } + + public void setLayout(String layout) { + this.layout = layout; + } + + public String getBizZone() { + return bizZone; + } + + public void setBizZone(String bizZone) { + this.bizZone = bizZone; + } + + public String getRenovationStatus() { + return renovationStatus; + } + + public void setRenovationStatus(String renovationStatus) { + this.renovationStatus = renovationStatus; + } + + public String getFeatures() { + return features; + } + + public void setFeatures(String features) { + this.features = features; + } } diff --git a/src/main/java/org/chenyon/assets/vo/AssetsVo.java b/src/main/java/org/chenyon/assets/vo/AssetsVo.java index 5d889d2..58ae7eb 100644 --- a/src/main/java/org/chenyon/assets/vo/AssetsVo.java +++ b/src/main/java/org/chenyon/assets/vo/AssetsVo.java @@ -24,10 +24,12 @@ public class AssetsVo implements Serializable { private String unitNo; //单元号 private String floorNo; //楼层号 private String roomNo; //房间号 - private Boolean hasLift;//有无电梯 + private String hasLift;//有无电梯 private String layout; //户型 private String orientation; //朝向 private String assetsAddress; //资产地址 + private String bizZone; //商圈 + private List features; //特色 public String getManagerName() { return managerName; @@ -165,11 +167,11 @@ public class AssetsVo implements Serializable { this.roomNo = roomNo; } - public Boolean getHasLift() { + public String getHasLift() { return hasLift; } - public void setHasLift(Boolean hasLift) { + public void setHasLift(String hasLift) { this.hasLift = hasLift; } @@ -196,4 +198,20 @@ public class AssetsVo implements Serializable { public void setAssetsAddress(String assetsAddress) { this.assetsAddress = assetsAddress; } + + public String getBizZone() { + return bizZone; + } + + public void setBizZone(String bizZone) { + this.bizZone = bizZone; + } + + public List getFeatures() { + return features; + } + + public void setFeatures(List features) { + this.features = features; + } } diff --git a/src/main/java/org/chenyon/bill/BillController.java b/src/main/java/org/chenyon/bill/BillController.java index 73f17e0..e3ac995 100644 --- a/src/main/java/org/chenyon/bill/BillController.java +++ b/src/main/java/org/chenyon/bill/BillController.java @@ -1,5 +1,7 @@ package org.chenyon.bill; +import org.chenyon.pay.OrderService; +import org.chenyon.pay.OrderVo; import org.chenyon.user.LoginCheck; import org.chenyon.user.UserContext; import org.rcy.framework.api.entity.PageResult; @@ -17,6 +19,8 @@ public class BillController { @Autowired private BillService billService; + @Autowired + private OrderService orderService; @LoginCheck @PostMapping("/pageQueryContractBill") @@ -95,4 +99,38 @@ public class BillController { } return ResultMessage.success(0); } + + @LoginCheck + @PostMapping("/pay") + public ResultMessage payBill(@RequestBody OrderVo orderVo) { + try { + UserContext userContext = UserContext.get(); + if(userContext == null || userContext.getCusNo() == null) { + return ResultMessage.error(); + } + orderVo.setPayer(userContext.getCusNo()); + orderVo.setPayerOpenId(userContext.getOpenId()); + orderVo.setPayStatus("unpaid"); + orderVo.setPayerName(userContext.getUsername()); + return ResultMessage.success(orderService.createOrder(orderVo)); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return ResultMessage.success(0); + } + + @LoginCheck + @GetMapping("/updateRentBillStatus") + public ResultMessage updateRentBillStatus() { + try { + UserContext userContext = UserContext.get(); + if(userContext == null || userContext.getCusNo() == null) { + return ResultMessage.success(0); + } + return ResultMessage.success(billService.countUnpayWaeBills(userContext.getCusNo())); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return ResultMessage.success(0); + } } diff --git a/src/main/java/org/chenyon/bill/BillService.java b/src/main/java/org/chenyon/bill/BillService.java index 8c2794c..3972b67 100644 --- a/src/main/java/org/chenyon/bill/BillService.java +++ b/src/main/java/org/chenyon/bill/BillService.java @@ -3,6 +3,7 @@ package org.chenyon.bill; import org.chenyon.oa.OaBillService; import org.chenyon.oa.bill.OaBillVo; import org.chenyon.oa.bill.OaPayRecordVo; +import org.chenyon.pay.OrderService; import org.rcy.framework.api.entity.PageResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -15,6 +16,8 @@ public class BillService { @Autowired private OaBillService oaBillService; + @Autowired + private OrderService orderService; public PageResult pageQueryContractBill(BillQueryCondition condition) throws Exception { return oaBillService.pageQueryContractBill(condition); @@ -39,4 +42,10 @@ public class BillService { return oaBillService.countUnpayWaeBills(params); } + public String getBillPayReceiver(String billNo,String bizType) throws Exception { + Map params = new HashMap<>(); + params.put("billNo",billNo); + params.put("bizType",bizType); + return oaBillService.getBillPayReceiver(params); + } } diff --git a/src/main/java/org/chenyon/bill/BillStatusUpdateVo.java b/src/main/java/org/chenyon/bill/BillStatusUpdateVo.java new file mode 100644 index 0000000..1e0a6e6 --- /dev/null +++ b/src/main/java/org/chenyon/bill/BillStatusUpdateVo.java @@ -0,0 +1,15 @@ +package org.chenyon.bill; + +import java.util.List; + +public class BillStatusUpdateVo { + private List billIds; + + public List getBillIds() { + return billIds; + } + + public void setBillIds(List billIds) { + this.billIds = billIds; + } +} diff --git a/src/main/java/org/chenyon/bill/UnpaidBillVo.java b/src/main/java/org/chenyon/bill/UnpaidBillVo.java new file mode 100644 index 0000000..0c30b7c --- /dev/null +++ b/src/main/java/org/chenyon/bill/UnpaidBillVo.java @@ -0,0 +1,41 @@ +package org.chenyon.bill; + +public class UnpaidBillVo { + + private String billNo; + private String payee; + private String amount; + private String bizType; + + public String getBillNo() { + return billNo; + } + + public void setBillNo(String billNo) { + this.billNo = billNo; + } + + public String getPayee() { + return payee; + } + + public void setPayee(String payee) { + this.payee = payee; + } + + public String getAmount() { + return amount; + } + + public void setAmount(String amount) { + this.amount = amount; + } + + public String getBizType() { + return bizType; + } + + public void setBizType(String bizType) { + this.bizType = bizType; + } +} diff --git a/src/main/java/org/chenyon/constants/OaApiUrl.java b/src/main/java/org/chenyon/constants/OaApiUrl.java index 911a350..9f4b5f6 100644 --- a/src/main/java/org/chenyon/constants/OaApiUrl.java +++ b/src/main/java/org/chenyon/constants/OaApiUrl.java @@ -21,6 +21,14 @@ public final class OaApiUrl { * 查询资产详情 */ public static final String QUERY_ASSETS_DETAIL = "/assets/detail"; + /** + * 获取所有商圈信息 + */ + public static final String QUERY_ALL_BIZZONE = "/assets/getBizZones"; + /** + * 获取所有商圈信息 + */ + public static final String QUERY_ALL_FEATURE = "/assets/getFeatures"; /** * 分页查询合同 */ @@ -61,6 +69,10 @@ public final class OaApiUrl { * 统计未缴租金账单数 */ public static final String COUNT_UNPAY_RENT_BILLS = "/bill/countUnpay/rent"; + /** + * 获取账单收款方 + */ + public static final String BILL_PAY_RECEIVER = "/bill/payreceiver"; /** * 统计未缴水电费账单数 */ diff --git a/src/main/java/org/chenyon/contract/ContractQueryCondition.java b/src/main/java/org/chenyon/contract/ContractQueryCondition.java index eaa48a9..2ff32c7 100644 --- a/src/main/java/org/chenyon/contract/ContractQueryCondition.java +++ b/src/main/java/org/chenyon/contract/ContractQueryCondition.java @@ -9,6 +9,8 @@ public class ContractQueryCondition extends PageQueryRequest { private String formmainId; private String signStatus; private String signWay; + private String startDate; + private String endDate; public String getCusNo() { return cusNo; @@ -49,4 +51,20 @@ public class ContractQueryCondition extends PageQueryRequest { public void setSignWay(String signWay) { this.signWay = signWay; } + + public String getStartDate() { + return startDate; + } + + public void setStartDate(String startDate) { + this.startDate = startDate; + } + + public String getEndDate() { + return endDate; + } + + public void setEndDate(String endDate) { + this.endDate = endDate; + } } diff --git a/src/main/java/org/chenyon/contract/ContractService.java b/src/main/java/org/chenyon/contract/ContractService.java index a5a805f..42fe190 100644 --- a/src/main/java/org/chenyon/contract/ContractService.java +++ b/src/main/java/org/chenyon/contract/ContractService.java @@ -61,9 +61,9 @@ public class ContractService { if(oaContractVo.getAssetsVos() != null) { List assetsVos = oaContractVo.getAssetsVos(); OaAssetsVo assetsVo = assetsVos.get(0); - List assetsDetailImgs = oaFileHandlerService.getUrls(true,assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsDetailImg", assetsVo.getDetailImg()); - if(assetsDetailImgs != null) { - contractVo.setCoverImgUrl(assetsDetailImgs.get(0)); + List assetsCoverImg = oaFileHandlerService.getUrls(true, assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsCoverImg", assetsVo.getCoverImg()); + if(assetsCoverImg != null && assetsCoverImg.size() >= 1) { + contractVo.setCoverImgUrl(assetsCoverImg.get(0)); } } contractVo.setSignStatus(convertSignStatus(contractVo.getSignStatus())); @@ -82,6 +82,16 @@ public class ContractService { for (OaContractVo oaContractVo : oaContractVos) { ContractVo contractVo = new ContractVo(); BeanUtils.copyProperties(oaContractVo, contractVo); + if(oaContractVo.getAssetsVos() != null) { + List contractAssetsVos = new ArrayList<>(); + for (OaAssetsVo assetsVo : oaContractVo.getAssetsVos()) { + ContractAssetsVo contractAssetsVo = new ContractAssetsVo(); + contractAssetsVo.setAssetsNo(assetsVo.getAssetsNo()); + contractAssetsVo.setAssetsName(assetsVo.getAssetsName()); + contractAssetsVos.add(contractAssetsVo); + } + contractVo.setAssetsInfos(contractAssetsVos); + } contractVos.add(contractVo); } return contractVos; @@ -93,7 +103,7 @@ public class ContractService { condition.setPageNo(pageNo); condition.setPageSize(pageSize); OaAssetsVo assetsVo = oaContractService.pageQueryContractAssets(condition); - List assetsDetailImgs = oaFileHandlerService.getUrls(true,assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsDetailImg", assetsVo.getDetailImg()); + List assetsCoverImgs = oaFileHandlerService.getUrls(true, assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsCoverImg", assetsVo.getCoverImg()); ContractAssetsVo assetsInfo = new ContractAssetsVo(); BeanUtils.copyProperties(assetsVo, assetsInfo); RentFeeInfo rentFeeInfo = new RentFeeInfo(); @@ -101,8 +111,8 @@ public class ContractService { rentFeeInfo.setRentFee(Double.parseDouble(assetsVo.getRentFee())); } assetsInfo.setFeeInfo(rentFeeInfo); - if(assetsDetailImgs != null) { - assetsInfo.setCover(assetsDetailImgs.get(0)); + if(assetsCoverImgs != null) { + assetsInfo.setCover(assetsCoverImgs.get(0)); } return assetsInfo; } @@ -122,7 +132,7 @@ public class ContractService { BeanUtils.copyProperties(oaContractVo, contractVo); List assetsVos = oaContractVo.getAssetsVos(); OaAssetsVo assetsVo = assetsVos.get(0); - List assetsDetailImgs = oaFileHandlerService.getUrls(true,assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsDetailImg", assetsVo.getDetailImg()); + List assetsCoverImgs = oaFileHandlerService.getUrls(true, assetsVo.getAssetsNo(), assetsVo.getFormId(), "AssetsCoverImg", assetsVo.getCoverImg()); List eContractUrl = oaFileHandlerService.getUrls(false,cusNo,oaContractVo.getContractNo(),oaContractVo.getFormId(),"eContractFile",oaContractVo.geteContractFile()); ContractAssetsVo assetsInfo = new ContractAssetsVo(); BeanUtils.copyProperties(assetsVo, assetsInfo); @@ -131,8 +141,8 @@ public class ContractService { rentFeeInfo.setRentFee(Double.parseDouble(assetsVo.getRentFee())); } assetsInfo.setFeeInfo(rentFeeInfo); - if(assetsDetailImgs != null) { - assetsInfo.setCover(assetsDetailImgs.get(0)); + if(assetsCoverImgs != null) { + assetsInfo.setCover(assetsCoverImgs.get(0)); } if(eContractUrl != null) { contractVo.seteContractUrl(eContractUrl.get(0)); diff --git a/src/main/java/org/chenyon/fallback/FallbackController.java b/src/main/java/org/chenyon/fallback/FallbackController.java index c8c0730..cb3f446 100644 --- a/src/main/java/org/chenyon/fallback/FallbackController.java +++ b/src/main/java/org/chenyon/fallback/FallbackController.java @@ -1,7 +1,5 @@ package org.chenyon.fallback; -import org.chenyon.discharge.DisChargeApplyQueryCondition; -import org.chenyon.discharge.DisChargeApplyVo; import org.chenyon.oa.OaFallBackService; import org.chenyon.user.LoginCheck; import org.chenyon.user.UserContext; @@ -57,7 +55,7 @@ public class FallbackController { try { UserContext userContext = UserContext.get(); if(userContext == null || userContext.getCusNo() == null) { - return ResultMessage.success("您还未实名"); + return ResultMessage.error("您还未实名"); } submitVo.setCusNo(userContext.getCusNo()); submitVo.setTenantType(userContext.getUserType().equals("0") ? "个人" : "单位"); diff --git a/src/main/java/org/chenyon/file/AttachmentVo.java b/src/main/java/org/chenyon/file/AttachmentVo.java new file mode 100644 index 0000000..a5c4151 --- /dev/null +++ b/src/main/java/org/chenyon/file/AttachmentVo.java @@ -0,0 +1,22 @@ +package org.chenyon.file; + +public class AttachmentVo { + private String fileName; + private String fileUrl; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } +} diff --git a/src/main/java/org/chenyon/file/OaFileHandlerService.java b/src/main/java/org/chenyon/file/OaFileHandlerService.java index 2eead7c..57baca9 100644 --- a/src/main/java/org/chenyon/file/OaFileHandlerService.java +++ b/src/main/java/org/chenyon/file/OaFileHandlerService.java @@ -8,9 +8,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @Service @@ -46,14 +44,38 @@ public class OaFileHandlerService { oaFileLocalRefVo.setSubRefIds(oaFileVo.getSubRefIds()); oaFileLocalRefVo.setViewPublic(viewPublic); oaFileLocalRefVo.setOwner(owner); - return refLocalUrl(oaFileLocalRefVo); + Map map = refLocalUrl(oaFileLocalRefVo); + return new ArrayList<>(map.keySet()); + } + + public List getAttachmentUrls(Boolean viewPublic,String owner,String bizId, String formId, String oaFieldFlag, OaFileVo oaFileVo){ + if(bizId == null || formId == null || oaFieldFlag == null || oaFileVo == null) { + return null; + } + OaFileLocalRefVo oaFileLocalRefVo = new OaFileLocalRefVo(); + oaFileLocalRefVo.setBizId(bizId); + oaFileLocalRefVo.setOaFormId(formId); + oaFileLocalRefVo.setOaFieldFlag(oaFieldFlag); + oaFileLocalRefVo.setRefId(oaFileVo.getMainRefId()); + oaFileLocalRefVo.setSubRefIds(oaFileVo.getSubRefIds()); + oaFileLocalRefVo.setViewPublic(viewPublic); + oaFileLocalRefVo.setOwner(owner); + Map map = refLocalUrl(oaFileLocalRefVo); + List attachmentVos = new ArrayList<>(); + for (String key : map.keySet()) { + AttachmentVo attachmentVo = new AttachmentVo(); + attachmentVo.setFileUrl(key); + attachmentVo.setFileName(map.get(key)); + attachmentVos.add(attachmentVo); + } + return attachmentVos; } public List getUrls(Boolean viewPublic,String bizId, String formId, String oaFieldFlag, OaFileVo oaFileVo){ return getUrls(viewPublic,null,bizId,formId,oaFieldFlag,oaFileVo); } - public List refLocalUrl(OaFileLocalRefVo oaFileLocalRefVo) { + public Map refLocalUrl(OaFileLocalRefVo oaFileLocalRefVo) { OaFileFindCondition condition1 = new OaFileFindCondition(); condition1.setBizId(oaFileLocalRefVo.getBizId()); condition1.setOaFormId(oaFileLocalRefVo.getOaFormId()); @@ -64,7 +86,7 @@ public class OaFileHandlerService { List subRefInfos = oaFileLocalSubRefDao.findFileInfoByMainRefId(localRefDb.getRefId()); //先删除旧的 Set subRefSet = oaFileLocalRefVo.getSubRefIds().stream().collect(Collectors.toSet()); - List nSubUrls = new ArrayList<>(); + Map nSubUrls = new HashMap<>(); for (OaFileLocalSubRef subRefInfo : subRefInfos) { if (!subRefSet.contains(subRefInfo.getRefId())) { //删除子表 @@ -77,7 +99,7 @@ public class OaFileHandlerService { tempFile.delete(); } }else { - nSubUrls.add(subRefInfo.getUrl()); + nSubUrls.put(subRefInfo.getUrl(),subRefInfo.getFileName()); } } Set dbSubRefSet = subRefInfos.stream().map(s -> s.getRefId()).collect(Collectors.toSet()); @@ -89,7 +111,7 @@ public class OaFileHandlerService { return nSubUrls; } //附件信息完全删除 - List ncSubUrls = new ArrayList<>(); + Map ncSubUrls = new HashMap<>(); List subRefIds = oaFileLocalRefVo.getSubRefIds(); for (String subRefId : subRefIds) { try { @@ -113,17 +135,20 @@ public class OaFileHandlerService { return ncSubUrls; } - private void reBuildSubRef(String bizType,String subRefId, String mainRefId, Boolean isPublic, String owner, List nSubUrls) { + private void reBuildSubRef(String bizType,String subRefId, String mainRefId, Boolean isPublic, String owner, Map nSubUrls) { //新增 OaFileLocalSubRef oaFileLocalSubRef = new OaFileLocalSubRef(); oaFileLocalSubRef.setRefId(subRefId); oaFileLocalSubRef.setMainRefId(mainRefId); //调OA接口写入文件 try { - String subUrl = seeyonHttpClient.downloadFile(bizType,OaApiUrl.FILE_DOWNLOAD,subRefId, isPublic, owner); + Map resMap = seeyonHttpClient.downloadFile(bizType, OaApiUrl.FILE_DOWNLOAD, subRefId, isPublic, owner); + String subUrl = resMap.get("url"); + String oriFileName = resMap.get("fileName"); oaFileLocalSubRef.setUrl(subUrl); + oaFileLocalSubRef.setFileName(oriFileName); oaFileLocalSubRefDao.save(oaFileLocalSubRef); - nSubUrls.add(subUrl); + nSubUrls.put(subUrl,oriFileName); } catch (Exception e) { } diff --git a/src/main/java/org/chenyon/file/OaFileLocalSubRef.java b/src/main/java/org/chenyon/file/OaFileLocalSubRef.java index 42832c4..be212fe 100644 --- a/src/main/java/org/chenyon/file/OaFileLocalSubRef.java +++ b/src/main/java/org/chenyon/file/OaFileLocalSubRef.java @@ -11,6 +11,7 @@ public class OaFileLocalSubRef extends BaseEntity { private String refId; private String url; private String mainRefId; + private String fileName; public String getRefId() { return refId; @@ -35,4 +36,12 @@ public class OaFileLocalSubRef extends BaseEntity { public void setMainRefId(String mainRefId) { this.mainRefId = mainRefId; } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } } diff --git a/src/main/java/org/chenyon/location/IpLocationService.java b/src/main/java/org/chenyon/location/IpLocationService.java index 6d8d800..54b93ab 100644 --- a/src/main/java/org/chenyon/location/IpLocationService.java +++ b/src/main/java/org/chenyon/location/IpLocationService.java @@ -1,25 +1,20 @@ package org.chenyon.location; -import org.rcy.framework.utils.net.HttpRequestUtils; -import org.rcy.framework.utils.net.HttpResponse; +import com.maxmind.geoip2.DatabaseReader; +import com.maxmind.geoip2.model.CityResponse; import org.springframework.stereotype.Service; +import java.io.File; +import java.net.InetAddress; + @Service public class IpLocationService { - private static final String API = "https://apis.map.qq.com/ws/location/v1/ip"; - - public String getLocationByIP(String ip) { - String key = "CQPBZ-R543L-ZCZPH-E5CPI-KMUF6-VRBGE"; - String url = API + "?ip=" + ip + "&key=" + key; - try { - HttpResponse response = HttpRequestUtils.sendGet(url, null); - if(response.getCode() == 200) { - return response.getRespStr(); - } - }catch (Exception e) { - - } - return null; + public String getLocationByIP(String ip) throws Exception { + File database = new File("/usr/local/localfile/GeoLite2-City.mmdb"); + DatabaseReader reader = new DatabaseReader.Builder(database).build(); + InetAddress ipAddress = InetAddress.getByName(ip); + CityResponse response = reader.city(ipAddress); + return response.getCity().getName(); } } diff --git a/src/main/java/org/chenyon/location/LocateController.java b/src/main/java/org/chenyon/location/LocateController.java index 57fc2f7..48afa27 100644 --- a/src/main/java/org/chenyon/location/LocateController.java +++ b/src/main/java/org/chenyon/location/LocateController.java @@ -1,6 +1,8 @@ package org.chenyon.location; import org.rcy.framework.api.entity.ResultMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -12,17 +14,55 @@ import java.io.IOException; @RestController @RequestMapping("/location") public class LocateController { + + private static final Logger log = LoggerFactory.getLogger(LocateController.class); + @Autowired private IpLocationService ipLocationService; @GetMapping("/getRealCity") public ResultMessage getRealCity(HttpServletRequest request) throws IOException { -// String ip = ""; -// String locationJson = ipLocationService.getLocationByIP(ip); -// JsonNode root = JsonUtils.parseTree(locationJson); -// JsonNode adInfo = root.path("result").path("ad_info"); -// String city = adInfo.path("city").asText(); -// return ResultMessage.success(city != null ? city : "未知城市"); - return ResultMessage.success("宜昌"); + try { + String ip = getClientIp(request); + String city = ipLocationService.getLocationByIP(ip); + return ResultMessage.success(city != null ? city : "未知城市"); + }catch (Exception e){ + log.error(e.getMessage(),e); + } + return ResultMessage.success("宜昌市"); + } + + public String getClientIp(HttpServletRequest request) { + String ip; + // 1. X-Forwarded-For + ip = request.getHeader("X-Forwarded-For"); + if (isValid(ip)) { + // 多级代理:取第一个 + return ip.split(",")[0].trim(); + } + // 2. X-Real-IP + ip = request.getHeader("X-Real-IP"); + if (isValid(ip)) { + return ip; + } + // 3. 其他兼容头 + String[] headers = { + "Proxy-Client-IP", + "WL-Proxy-Client-IP", + "HTTP_CLIENT_IP", + "HTTP_X_FORWARDED_FOR" + }; + for (String header : headers) { + ip = request.getHeader(header); + if (isValid(ip)) { + return ip; + } + } + // 4. 最后兜底 + return request.getRemoteAddr(); + } + + private boolean isValid(String ip) { + return ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip); } } diff --git a/src/main/java/org/chenyon/message/Message.java b/src/main/java/org/chenyon/message/Message.java index aed7975..8b407c5 100644 --- a/src/main/java/org/chenyon/message/Message.java +++ b/src/main/java/org/chenyon/message/Message.java @@ -4,6 +4,7 @@ import org.rcy.framework.api.entity.BaseEntity; import javax.persistence.Entity; import javax.persistence.Table; +import java.util.Map; @Entity @Table(name = "MESSAGE") @@ -15,6 +16,9 @@ public class Message extends BaseEntity { private String messageReceiver; private String bizId; private Boolean hasRead = false; + private SubcribeMsgMode subscribeMsgMode; + private Map templateValue; + private String messageText; public MessageType getMessageType() { return messageType; @@ -71,4 +75,28 @@ public class Message extends BaseEntity { public void setHasRead(Boolean hasRead) { this.hasRead = hasRead; } + + public SubcribeMsgMode getSubscribeMsgMode() { + return subscribeMsgMode; + } + + public void setSubscribeMsgMode(SubcribeMsgMode subscribeMsgMode) { + this.subscribeMsgMode = subscribeMsgMode; + } + + public Map getTemplateValue() { + return templateValue; + } + + public void setTemplateValue(Map templateValue) { + this.templateValue = templateValue; + } + + public String getMessageText() { + return messageText; + } + + public void setMessageText(String messageText) { + this.messageText = messageText; + } } diff --git a/src/main/java/org/chenyon/message/MessageController.java b/src/main/java/org/chenyon/message/MessageController.java index a0697d0..5b7565d 100644 --- a/src/main/java/org/chenyon/message/MessageController.java +++ b/src/main/java/org/chenyon/message/MessageController.java @@ -2,13 +2,19 @@ package org.chenyon.message; import org.chenyon.user.LoginCheck; import org.chenyon.user.UserContext; +import org.chenyon.wx.AesException; import org.rcy.framework.api.entity.PageResult; import org.rcy.framework.api.entity.ResultMessage; +import org.rcy.framework.utils.aes.AESUtils; +import org.rcy.framework.utils.string.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import javax.xml.parsers.ParserConfigurationException; + @RestController @RequestMapping("/message") public class MessageController { @@ -74,7 +80,16 @@ public class MessageController { @PostMapping("/sendMessage") - public ResultMessage sendMessage(@RequestBody MessageVo vo){ + public ResultMessage sendMessage(@RequestBody MessageVo vo, HttpServletRequest request) throws Exception { + String internalToken = request.getHeader("internalToken"); + if(StringUtils.isBlank(internalToken)) { + return ResultMessage.error("无权限"); + } + String decrypt = AESUtils.decrypt(internalToken, "rent*123"); + if(!"oa".equals(decrypt)){ + return ResultMessage.error("无权限"); + } + messageService.send(vo); return ResultMessage.success(); } } diff --git a/src/main/java/org/chenyon/message/MessageDao.xml b/src/main/java/org/chenyon/message/MessageDao.xml index 5c67895..6f10619 100644 --- a/src/main/java/org/chenyon/message/MessageDao.xml +++ b/src/main/java/org/chenyon/message/MessageDao.xml @@ -25,7 +25,9 @@ AND messageReceiver = #{messageReceiver} - + + AND hasRead = #{hasRead} + \ No newline at end of file diff --git a/src/main/java/org/chenyon/message/MessageQueryCondition.java b/src/main/java/org/chenyon/message/MessageQueryCondition.java index 4e2098d..8cd2703 100644 --- a/src/main/java/org/chenyon/message/MessageQueryCondition.java +++ b/src/main/java/org/chenyon/message/MessageQueryCondition.java @@ -5,6 +5,8 @@ import org.rcy.framework.api.entity.PageQueryRequest; public class MessageQueryCondition extends PageQueryRequest { private String messageReceiver; + private Boolean hasRead; + private String bizId; public String getMessageReceiver() { return messageReceiver; @@ -13,4 +15,20 @@ public class MessageQueryCondition extends PageQueryRequest { public void setMessageReceiver(String messageReceiver) { this.messageReceiver = messageReceiver; } + + public Boolean getHasRead() { + return hasRead; + } + + public void setHasRead(Boolean hasRead) { + this.hasRead = hasRead; + } + + public String getBizId() { + return bizId; + } + + public void setBizId(String bizId) { + this.bizId = bizId; + } } diff --git a/src/main/java/org/chenyon/message/MessageService.java b/src/main/java/org/chenyon/message/MessageService.java index 4dd62bd..4e1573d 100644 --- a/src/main/java/org/chenyon/message/MessageService.java +++ b/src/main/java/org/chenyon/message/MessageService.java @@ -1,7 +1,6 @@ package org.chenyon.message; import org.chenyon.wx.AesException; -import org.chenyon.wx.WXBizMsgCrypt; import org.rcy.framework.api.entity.PageResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -16,6 +15,8 @@ public class MessageService { @Autowired private MessageDao messageDao; + @Autowired + private List subscribeMsgSenders; public MessageVo detail(Long id) { @@ -38,6 +39,7 @@ public class MessageService { public Integer countUnread(String cusNo){ MessageQueryCondition messageQueryCondition = new MessageQueryCondition(); messageQueryCondition.setMessageReceiver(cusNo); + messageQueryCondition.setHasRead(false); Long count = messageDao.countCondition(messageQueryCondition); return count.intValue(); } @@ -53,21 +55,23 @@ public class MessageService { public void send(MessageVo messageVo) throws AesException, ParserConfigurationException { // 消息入库 - // - String urlSend = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="; - - - // 需要加密的明文 - String encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"; - String token = "pamtest"; - String timestamp = "1409304348"; - String nonce = "xxxxxx"; - String appId = "wxb11529c136998cb6"; - String replyMsg = " 中文1407743423"; - - WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId); - String mingwen = pc.encryptMsg(replyMsg, timestamp, nonce); - System.out.println("加密后: " + mingwen); - + Message message = new Message(); + message.setMessageType(MessageType.valueOf(messageVo.getMessageType())); + message.setMessageContent(messageVo.getMessageContent()); + message.setMessageTime(messageVo.getMessageTime()); + message.setMessageReceiver(messageVo.getMessageReceiver()); + message.setBizId(messageVo.getBizId()); + message.setSubscribeMsgMode(SubcribeMsgMode.valueOf(messageVo.getSubscribeMsgMode())); + message.setTitle(messageVo.getTitle()); + message.setHasRead(false); + message.setTemplateValue(messageVo.getTemplateValue()); + message.setMessageText(messageVo.getMessageText()); + messageDao.save(message); + //发送订阅消息 + for (SubscribeMsgSender subscribeMsgSender : subscribeMsgSenders) { + if(subscribeMsgSender.support(messageVo) && Boolean.TRUE.equals(messageVo.getSendSubscribeMsg())){ + subscribeMsgSender.sendSubscribeMsg(messageVo); + } + } } } diff --git a/src/main/java/org/chenyon/message/MessageVo.java b/src/main/java/org/chenyon/message/MessageVo.java index 69e181e..72fccc8 100644 --- a/src/main/java/org/chenyon/message/MessageVo.java +++ b/src/main/java/org/chenyon/message/MessageVo.java @@ -1,14 +1,20 @@ package org.chenyon.message; +import java.util.Map; + public class MessageVo { private String id; private String title; private String messageType; private String messageContent; + private String messageText; private String messageTime; private String messageReceiver; private String bizId; private Boolean hasRead; + private Boolean sendSubscribeMsg; + private String subscribeMsgMode; + private Map templateValue; public String getMessageType() { return messageType; @@ -73,4 +79,36 @@ public class MessageVo { public void setHasRead(Boolean hasRead) { this.hasRead = hasRead; } + + public Boolean getSendSubscribeMsg() { + return sendSubscribeMsg; + } + + public void setSendSubscribeMsg(Boolean sendSubscribeMsg) { + this.sendSubscribeMsg = sendSubscribeMsg; + } + + public String getSubscribeMsgMode() { + return subscribeMsgMode; + } + + public void setSubscribeMsgMode(String subscribeMsgMode) { + this.subscribeMsgMode = subscribeMsgMode; + } + + public String getMessageText() { + return messageText; + } + + public void setMessageText(String messageText) { + this.messageText = messageText; + } + + public Map getTemplateValue() { + return templateValue; + } + + public void setTemplateValue(Map templateValue) { + this.templateValue = templateValue; + } } \ No newline at end of file diff --git a/src/main/java/org/chenyon/message/SubcribeMsgMode.java b/src/main/java/org/chenyon/message/SubcribeMsgMode.java new file mode 100644 index 0000000..3fc2eaa --- /dev/null +++ b/src/main/java/org/chenyon/message/SubcribeMsgMode.java @@ -0,0 +1,7 @@ +package org.chenyon.message; + +public enum SubcribeMsgMode { + WEAPPMINIPROGRAM, + SMS, + EMAIL,; +} diff --git a/src/main/java/org/chenyon/message/SubscribeMsgSender.java b/src/main/java/org/chenyon/message/SubscribeMsgSender.java new file mode 100644 index 0000000..7d34a06 --- /dev/null +++ b/src/main/java/org/chenyon/message/SubscribeMsgSender.java @@ -0,0 +1,6 @@ +package org.chenyon.message; + +public interface SubscribeMsgSender { + void sendSubscribeMsg(MessageVo messageVo); + Boolean support(MessageVo messageVo); +} diff --git a/src/main/java/org/chenyon/message/WeAppMiniProgramMsgSender.java b/src/main/java/org/chenyon/message/WeAppMiniProgramMsgSender.java new file mode 100644 index 0000000..40df76e --- /dev/null +++ b/src/main/java/org/chenyon/message/WeAppMiniProgramMsgSender.java @@ -0,0 +1,111 @@ +package org.chenyon.message; + +import org.chenyon.user.UserService; +import org.chenyon.user.UserVo; +import org.chenyon.wx.WXBizMsgCrypt; +import org.chenyon.wx.WeChatAccessTokenService; +import org.rcy.framework.utils.json.JsonUtils; +import org.rcy.framework.utils.net.HttpRequestUtils; +import org.rcy.framework.utils.net.HttpResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +@Component +public class WeAppMiniProgramMsgSender implements SubscribeMsgSender{ + + private static final Logger log = LoggerFactory.getLogger(WeAppMiniProgramMsgSender.class); + + @Autowired + private UserService userService; + @Autowired + private WeChatAccessTokenService weChatAccessTokenService; + + @Override + public void sendSubscribeMsg(MessageVo messageVo) { + try { + if(messageVo == null || messageVo.getMessageReceiver() == null){ + return; + } + UserVo userVo = userService.getByCusNo(messageVo.getMessageReceiver()); + //用户未开启推送则不发送 + if(userVo == null || !Boolean.TRUE.equals(userVo.getSubscribeMsg())){ + return; + } + String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + weChatAccessTokenService.getAccessToken(); + Map params = new HashMap<>(); + params.put("touser",userVo.getOpenId()); + params.put("template_id",getTemplateId(messageVo.getMessageType())); + params.put("page",getForwardPage(messageVo.getMessageType())); + params.put("miniprogram_state","formal"); + params.put("lang","zh_CN"); + params.put("data",getPushData(messageVo)); + HttpResponse response = HttpRequestUtils.sendPost(url, JsonUtils.convertJson(params), null); + Map respMap = JsonUtils.parseObject(response.getRespStr(), Map.class); + if (respMap.get("errcode") != null) { + log.error("推送消息到小程序失败"); + } + }catch (Exception e) { + log.error("推送消息到小程序失败: " + e.getMessage(),e); + } + } + + @Override + public Boolean support(MessageVo messageVo) { + return SubcribeMsgMode.WEAPPMINIPROGRAM.name().equals(messageVo.getSubscribeMsgMode()); + } + + private String getTemplateId(String msgType) { + switch (msgType) { + case "BILL": return "9QlNxNONJBICzw3Vcetqbf9yv4lI9q9cR_px8ujlOu8"; + } + return null; + } + + private Map getPushData(MessageVo messageVo) { + switch (messageVo.getMessageType()) { + case "BILL": return buildBillData(messageVo); + } + return null; + } + + public Map buildBillData(MessageVo messageVo) { + Map data = new HashMap<>(); + //设置账单金额 + Map amount2 = new HashMap<>(); + amount2.put("value",messageVo.getTemplateValue().get("billAmount")); + data.put("amount2",amount2); + //设置账单日期 + Map time3 = new HashMap<>(); + time3.put("value",messageVo.getTemplateValue().get("billDate")); + data.put("time3",time3); + //设置备注 + Map thing4 = new HashMap<>(); + thing4.put("value",messageVo.getTemplateValue().get("remark")); + data.put("thing4",thing4); + //设置资产店名 + + Map thing8 = new HashMap<>(); + thing8.put("value",messageVo.getTemplateValue().get("assetsName") + ""); + data.put("thing8",thing8); + + //设置房间号 + + Map thing1 = new HashMap<>(); + thing1.put("value",messageVo.getTemplateValue().get("roomNo") + ""); + data.put("thing1",thing1); + + return data; + } + + private String getForwardPage(String msgType) { + switch (msgType) { + case "BILL": return "unpaid"; + } + return null; + } +} diff --git a/src/main/java/org/chenyon/notice/NoticeVo.java b/src/main/java/org/chenyon/notice/NoticeVo.java index 5ff72de..1a9f24a 100644 --- a/src/main/java/org/chenyon/notice/NoticeVo.java +++ b/src/main/java/org/chenyon/notice/NoticeVo.java @@ -1,5 +1,7 @@ package org.chenyon.notice; +import org.chenyon.file.AttachmentVo; + import java.util.List; public class NoticeVo { @@ -14,7 +16,7 @@ public class NoticeVo { private String updateBy; private String updateTime; private String remark; - private List attachments; + private List attachments; private List imgs; public String getNoticeId() { @@ -97,11 +99,11 @@ public class NoticeVo { this.remark = remark; } - public List getAttachments() { + public List getAttachments() { return attachments; } - public void setAttachments(List attachments) { + public void setAttachments(List attachments) { this.attachments = attachments; } diff --git a/src/main/java/org/chenyon/oa/OaAssetService.java b/src/main/java/org/chenyon/oa/OaAssetService.java index a5474ac..556e9d7 100644 --- a/src/main/java/org/chenyon/oa/OaAssetService.java +++ b/src/main/java/org/chenyon/oa/OaAssetService.java @@ -9,6 +9,7 @@ import org.rcy.framework.utils.json.JsonUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,6 +43,11 @@ public class OaAssetService { return pageResult; } + public List getBizZones() throws Exception { + OaResp oaResp = seeyonHttpClient.sendGet("获取商圈信息",OaApiUrl.QUERY_ALL_BIZZONE); + return JsonUtils.parseObject(oaResp.getDataStr(), List.class); + } + public OaAssetsVo queryAssetsDetail(String assetsNo) throws Exception { Map params = new HashMap<>(); params.put("assetsNo",assetsNo); @@ -49,4 +55,8 @@ public class OaAssetService { return JsonUtils.parseObject(oaResp.getDataStr(),OaAssetsVo.class); } + public List getFeatures() throws Exception { + OaResp oaResp = seeyonHttpClient.sendGet("获取特点信息",OaApiUrl.QUERY_ALL_FEATURE); + return JsonUtils.parseObject(oaResp.getDataStr(), List.class); + } } diff --git a/src/main/java/org/chenyon/oa/OaBillService.java b/src/main/java/org/chenyon/oa/OaBillService.java index ec0e541..e139ed5 100644 --- a/src/main/java/org/chenyon/oa/OaBillService.java +++ b/src/main/java/org/chenyon/oa/OaBillService.java @@ -91,4 +91,9 @@ public class OaBillService { return (Integer) oaResp.getData(); } + public String getBillPayReceiver(Map params) throws Exception { + OaResp oaResp = seeyonHttpClient.sendPost("获取账单收款方", OaApiUrl.BILL_PAY_RECEIVER, JsonUtils.convertJson(params)); + return (String) oaResp.getData(); + } + } diff --git a/src/main/java/org/chenyon/oa/OaNoticeService.java b/src/main/java/org/chenyon/oa/OaNoticeService.java index 15652e7..0dfa8cc 100644 --- a/src/main/java/org/chenyon/oa/OaNoticeService.java +++ b/src/main/java/org/chenyon/oa/OaNoticeService.java @@ -1,10 +1,13 @@ package org.chenyon.oa; import org.chenyon.constants.OaApiUrl; +import org.chenyon.file.OaFileHandlerService; import org.chenyon.notice.NoticeQueryCondition; import org.chenyon.notice.NoticeVo; +import org.chenyon.oa.notice.OaNoticeVo; import org.rcy.framework.api.entity.PageResult; import org.rcy.framework.utils.json.JsonUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -17,6 +20,8 @@ public class OaNoticeService { @Autowired private SeeyonHttpClient seeyonHttpClient; + @Autowired + private OaFileHandlerService oaFileHandlerService; public PageResult pageQuery(NoticeQueryCondition condition) throws Exception { OaResp oaResp = seeyonHttpClient.sendPost("分页查询招商公告信息", OaApiUrl.PAGE_QUERY_NOTICE, JsonUtils.convertJson(condition)); @@ -42,6 +47,15 @@ public class OaNoticeService { Map params = new HashMap<>(); params.put("id",id); OaResp oaResp = seeyonHttpClient.sendPost("查询公告详情",OaApiUrl.QUERY_NOTICE_DETAIL, params); - return JsonUtils.parseObject(oaResp.getDataStr(),NoticeVo.class); + OaNoticeVo oaNoticeVo = JsonUtils.parseObject(oaResp.getDataStr(), OaNoticeVo.class); + NoticeVo vo = new NoticeVo(); + BeanUtils.copyProperties(oaNoticeVo,vo); + if(oaNoticeVo.getAttachments() != null) { + vo.setAttachments(oaFileHandlerService.getAttachmentUrls(true,null,oaNoticeVo.getNoticeId(),oaNoticeVo.getNoticeId(),"noticeAttachment",oaNoticeVo.getAttachments())); + } + if(oaNoticeVo.getImgs() != null) { + vo.setImgs(oaFileHandlerService.getUrls(true,oaNoticeVo.getNoticeId(),oaNoticeVo.getNoticeId(),"noticeImg",oaNoticeVo.getImgs())); + } + return vo; } } diff --git a/src/main/java/org/chenyon/oa/SeeyonHttpClient.java b/src/main/java/org/chenyon/oa/SeeyonHttpClient.java index 279b9ff..2e7102a 100644 --- a/src/main/java/org/chenyon/oa/SeeyonHttpClient.java +++ b/src/main/java/org/chenyon/oa/SeeyonHttpClient.java @@ -62,7 +62,7 @@ public class SeeyonHttpClient { return resovleResp(respStr); } - public String downloadFile(String bizType,String url,String refId,Boolean isPulic,String owner) throws Exception { + public Map downloadFile(String bizType,String url,String refId,Boolean isPulic,String owner) throws Exception { Map headers = new HashMap<>(); headers.put("token",getToken()); log.info("下载OA文件请求参数为:" + refId + "," + isPulic + "," + owner); @@ -81,10 +81,15 @@ public class SeeyonHttpClient { } savePath += File.separator + refId; String fileGetUrl = oaHost + "/seeyon/rest" + url + "?refId=" + refId; - File file = HttpRequestUtils.downloadFile(fileGetUrl, headers, savePath); + Map downloadResult = HttpRequestUtils.downloadFile(fileGetUrl, headers, savePath); + File file = (File) downloadResult.get("targetFile"); + String bizFileName = (String) downloadResult.get("oriFileName"); log.info("文件绝对路径为:" + file.getAbsolutePath()); returnUrl += "/" + file.getName(); - return returnUrl; + Map resMap = new HashMap<>(); + resMap.put("url",returnUrl); + resMap.put("fileName",bizFileName); + return resMap; } diff --git a/src/main/java/org/chenyon/oa/asset/OaAssetsVo.java b/src/main/java/org/chenyon/oa/asset/OaAssetsVo.java index decc1d7..c26d350 100644 --- a/src/main/java/org/chenyon/oa/asset/OaAssetsVo.java +++ b/src/main/java/org/chenyon/oa/asset/OaAssetsVo.java @@ -4,6 +4,7 @@ package org.chenyon.oa.asset; import org.chenyon.file.OaFileVo; import java.io.Serializable; +import java.util.List; public class OaAssetsVo implements Serializable { private String assetsNo; // 资产编号 @@ -15,6 +16,7 @@ public class OaAssetsVo implements Serializable { private String formId; //表单记录ID private OaFileVo detailImg; //详情图片 private OaFileVo vrImg; //vr图 + private OaFileVo coverImg; //封面图 private String assetsDesc; //资产描述 private String assetsAddress; //资产地址 private String latitude; //纬度 @@ -22,7 +24,7 @@ public class OaAssetsVo implements Serializable { private String unitNo; //单元号 private String floorNo; //楼层号 private String roomNo; //房间号 - private Boolean hasLift;//有无电梯 + private String hasLift;//有无电梯 private String managerName; //管理员 private String managerPhone; //管理员电话 private String layout; //户型 @@ -32,6 +34,9 @@ public class OaAssetsVo implements Serializable { private String waterFeeUnit; //水费单位 private String powerFee; //电费 private String powerFeeUnit; //电费单位 + private String bizZone; + private List features; + private String renovationStatus; //装修状态 public String getAssetsNo() { return assetsNo; @@ -161,11 +166,11 @@ public class OaAssetsVo implements Serializable { this.roomNo = roomNo; } - public Boolean getHasLift() { + public String getHasLift() { return hasLift; } - public void setHasLift(Boolean hasLift) { + public void setHasLift(String hasLift) { this.hasLift = hasLift; } @@ -240,4 +245,36 @@ public class OaAssetsVo implements Serializable { public void setManagerName(String managerName) { this.managerName = managerName; } + + public String getBizZone() { + return bizZone; + } + + public void setBizZone(String bizZone) { + this.bizZone = bizZone; + } + + public List getFeatures() { + return features; + } + + public void setFeatures(List features) { + this.features = features; + } + + public String getRenovationStatus() { + return renovationStatus; + } + + public void setRenovationStatus(String renovationStatus) { + this.renovationStatus = renovationStatus; + } + + public OaFileVo getCoverImg() { + return coverImg; + } + + public void setCoverImg(OaFileVo coverImg) { + this.coverImg = coverImg; + } } diff --git a/src/main/java/org/chenyon/oa/notice/OaNoticeVo.java b/src/main/java/org/chenyon/oa/notice/OaNoticeVo.java index 9190449..3af10f5 100644 --- a/src/main/java/org/chenyon/oa/notice/OaNoticeVo.java +++ b/src/main/java/org/chenyon/oa/notice/OaNoticeVo.java @@ -1,4 +1,115 @@ package org.chenyon.oa.notice; +import org.chenyon.file.OaFileVo; + public class OaNoticeVo { + + private String noticeId; + private String noticeTitle; + private String noticeType; + private String noticeContent; + private String status; + private String createBy; + private String createTime; + private String updateBy; + private String updateTime; + private String remark; + private OaFileVo attachments; //详情图片 + private OaFileVo imgs; //vr图 + + public String getNoticeId() { + return noticeId; + } + + public void setNoticeId(String noticeId) { + this.noticeId = noticeId; + } + + public String getNoticeTitle() { + return noticeTitle; + } + + public void setNoticeTitle(String noticeTitle) { + this.noticeTitle = noticeTitle; + } + + public String getNoticeType() { + return noticeType; + } + + public void setNoticeType(String noticeType) { + this.noticeType = noticeType; + } + + public String getNoticeContent() { + return noticeContent; + } + + public void setNoticeContent(String noticeContent) { + this.noticeContent = noticeContent; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public OaFileVo getAttachments() { + return attachments; + } + + public void setAttachments(OaFileVo attachments) { + this.attachments = attachments; + } + + public OaFileVo getImgs() { + return imgs; + } + + public void setImgs(OaFileVo imgs) { + this.imgs = imgs; + } } diff --git a/src/main/java/org/chenyon/pay/CreateOrderResp.java b/src/main/java/org/chenyon/pay/CreateOrderResp.java new file mode 100644 index 0000000..e664b1b --- /dev/null +++ b/src/main/java/org/chenyon/pay/CreateOrderResp.java @@ -0,0 +1,28 @@ +package org.chenyon.pay; + +public class CreateOrderResp { + private String errCode; + private String errMsg; + private String responseTimestamp; + private String mid; + private String tid; + private String msgId; + private String srcReserve; + private String merName; + private String merOrderId; + private String seqId; + +// "settleRefId":"35316566855N", +// "status":"NEW_ORDER", +// "totalAmount":"100", +// "targetOrderId":"734605162687061091810", +// "targetSys":"UAC", +// "targetStatus":"SUCCESS", +// "miniPayRequest": +// { +// +// }, +// "targetMid":"", +// "yxlmAmount":"100" + +} diff --git a/src/main/java/org/chenyon/pay/Goods.java b/src/main/java/org/chenyon/pay/Goods.java index 7ce9b0e..136c049 100644 --- a/src/main/java/org/chenyon/pay/Goods.java +++ b/src/main/java/org/chenyon/pay/Goods.java @@ -2,22 +2,46 @@ package org.chenyon.pay; public class Goods { + /** + * 商户自定义商品编码 + */ private String goodsId; + /** + * 商品名称 + */ private String goodsName; + /** + * 商品数量 + */ private String quantity; + /** + * 商品单价,单位为分 + */ private String price; private String unit; + /** + * 商品分类 + */ private String goodsCategory; + /** + * 商品说明 + */ private String body; private String discount; - /** 子商户号 */ + /** + * 子商户号 + * */ private String subMerchantId; - /** 子订单号 */ + /** + * 子订单号 + * */ private String merOrderId; - /** 子订单金额(分) */ + /** + * 子订单金额(分) + * */ private String subOrderAmount; public String getGoodsId() { diff --git a/src/main/java/org/chenyon/pay/LocalKvRedis.java b/src/main/java/org/chenyon/pay/LocalKvRedis.java new file mode 100644 index 0000000..632ccf5 --- /dev/null +++ b/src/main/java/org/chenyon/pay/LocalKvRedis.java @@ -0,0 +1,76 @@ +package org.chenyon.pay; + +import org.springframework.stereotype.Component; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Component +public class LocalKvRedis { + + // 存储 key -> value + private final ConcurrentHashMap store = new ConcurrentHashMap<>(); + + // 存储 key -> 过期时间(毫秒) + private final ConcurrentHashMap expireMap = new ConcurrentHashMap<>(); + + // 定时清理器 + private final ScheduledExecutorService cleaner = Executors.newSingleThreadScheduledExecutor(); + + public LocalKvRedis() { + // 每秒清理一次过期 key + cleaner.scheduleAtFixedRate(() -> { + long now = System.currentTimeMillis(); + for (String key : expireMap.keySet()) { + Long expireTime = expireMap.get(key); + if (expireTime != null && expireTime <= now) { + store.remove(key); + expireMap.remove(key); + } + } + }, 1, 1, TimeUnit.SECONDS); + } + + // ========== 操作 ========== + + // 设置永久 key + public void set(String key, String value) { + store.put(key, value); + expireMap.remove(key); + } + + // 设置带 TTL 的 key(秒) + public void set(String key, String value, long ttlSeconds) { + store.put(key, value); + expireMap.put(key, System.currentTimeMillis() + ttlSeconds * 1000); + } + + // 获取 key + public String get(String key) { + if (isExpired(key)) return null; + return store.get(key); + } + + // 删除 key + public void del(String key) { + store.remove(key); + expireMap.remove(key); + } + + // 判断 key 是否过期 + private boolean isExpired(String key) { + Long expireTime = expireMap.get(key); + if (expireTime == null) return false; + if (System.currentTimeMillis() > expireTime) { + store.remove(key); + expireMap.remove(key); + return true; + } + return false; + } + + // ========== 测试 ========== + +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/Order.java b/src/main/java/org/chenyon/pay/Order.java deleted file mode 100644 index b54b488..0000000 --- a/src/main/java/org/chenyon/pay/Order.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.chenyon.pay; - -import org.rcy.framework.api.entity.BaseEntity; - -public class Order extends BaseEntity { - - private String bizId; - private String payerId; - private String payDate; - private String amount; - private String status; - - public String getBizId() { - return bizId; - } - - public void setBizId(String bizId) { - this.bizId = bizId; - } - - public String getPayerId() { - return payerId; - } - - public void setPayerId(String payerId) { - this.payerId = payerId; - } - - public String getPayDate() { - return payDate; - } - - public void setPayDate(String payDate) { - this.payDate = payDate; - } - - public String getAmount() { - return amount; - } - - public void setAmount(String amount) { - this.amount = amount; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } -} diff --git a/src/main/java/org/chenyon/pay/OrderService.java b/src/main/java/org/chenyon/pay/OrderService.java new file mode 100644 index 0000000..30a7c0b --- /dev/null +++ b/src/main/java/org/chenyon/pay/OrderService.java @@ -0,0 +1,240 @@ +package org.chenyon.pay; + +import org.apache.commons.lang3.StringUtils; +import org.chenyon.bill.UnpaidBillVo; +import org.chenyon.oa.OaBillService; +import org.chenyon.pay.shopcar.SatInfo; +import org.chenyon.pay.shopcar.ShopCarOrderCreateRequest; +import org.chenyon.pay.shopcar.TmPayOrderRespVo; +import org.chenyon.pay.shopcar.VaFld; +import org.chenyon.user.UserService; +import org.rcy.framework.data.id.LongIdGenerator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +@Service +public class OrderService { + + @Autowired + private WeAppOrderDao weAppOrderDao; + @Autowired + private WeAppSubOrderDao weAppSubOrderDao; + + @Value("${chinaums.mid}") + private String mid; + @Value("${chinaums.tid}") + private String tid; + @Value("${chinaums.sourceNo}") + private String sourceNo; + @Value("${wx.appId}") + private String miniProgramAppId; + + @Autowired + private TmPayService tmPayService; + @Autowired + private UserService userService; + @Autowired + private OaBillService oaBillService; + + @Value("${chinaums.subMid.gy}") + private String gyMid; + @Value("${chinaums.submid.wjfw}") + private String fwglMid; + @Value("${wx.appId}") + private String wxAppId; + @Value("${chinaums.pay.notifyUrl}") + private String notifyUrl; + + /** + * 批量创建支付订单 + * 【核心】批量前 校验所有 billNo 是否已经存在子订单 + * 子订单唯一键:billNo + */ + @Transactional(rollbackFor = Exception.class) + public TmPayOrderRespVo createOrder(OrderVo orderVo) throws Exception { + // 1. 基础入参校验 + if (orderVo == null || orderVo.getBillVoList() == null || orderVo.getBillVoList().isEmpty()) { + throw new Exception("批量支付账单不能为空"); + } + if (StringUtils.isEmpty(orderVo.getPayerOpenId())) { + throw new Exception("支付人OPENID不能为空"); + } + + List billVoList = orderVo.getBillVoList(); + + // ====================================================================== + // 【批量支付 最强幂等校验】 + // 遍历所有子账单,根据 billNo 查询是否已存在支付记录 + // 只要有一个已存在 → 整批拒绝支付 + // ====================================================================== + for (UnpaidBillVo billVo : billVoList) { + String billNo = billVo.getBillNo(); + // 子订单唯一键:billNo + WeAppSubOrder existSubOrder = weAppSubOrderDao.selectByBillNo(billNo); + if (existSubOrder != null) { + throw new Exception("批量支付失败:账单号【" + billNo + "】已存在支付记录,禁止重复支付"); + } + } + + // 2. 生成主订单ID + Long mainOrderId = LongIdGenerator.generate(); + String bizId = mainOrderId.toString(); + orderVo.setBizId(bizId); + + // 3. 主订单幂等校验 + WeAppOrder existMainOrder = weAppOrderDao.findByBizId(bizId); + if (existMainOrder != null) { + TmPayOrderRespVo resp = new TmPayOrderRespVo(); +// resp.setOrderNo(existMainOrder.getTmOrderId()); +// resp.setAmount(existMainOrder.getAmount()); + return resp; + } + + // 4. 生成第三方支付订单号 + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + int random = 1000000 + new Random().nextInt(9000000); + String tmOrderNo = sourceNo + sdf.format(new Date()) + random; + + // 第三方单号唯一兜底 + WeAppOrder orderByTmNo = weAppOrderDao.selectByTmOrderId(tmOrderNo); + if (orderByTmNo != null) { + throw new Exception("支付单号重复,请重新提交"); + } + + // 5. 调用支付创建分账订单 + ShopCarOrderCreateRequest request = buildShopCarOrderCreateRequest(orderVo, tmOrderNo); + TmPayOrderRespVo payResp = tmPayService.weChatPayCreateSplitOrder(request); + + // 6. 批量插入子订单 + 修复 BigDecimal 金额BUG + BigDecimal totalAmount = BigDecimal.ZERO; + for (UnpaidBillVo billVo : billVoList) { + WeAppSubOrder subOrder = new WeAppSubOrder(); + subOrder.setMainOrderId(mainOrderId); + subOrder.setBillNo(billVo.getBillNo()); // 唯一键 + subOrder.setAmount(billVo.getAmount()); + subOrder.setPayStatus("0"); + weAppSubOrderDao.insert(subOrder); + + // 正确累加金额(修复原BUG) + totalAmount = totalAmount.add(new BigDecimal(billVo.getAmount())); + } + + // 7. 插入主订单 + WeAppOrder weAppOrder = new WeAppOrder(); + weAppOrder.setId(mainOrderId); + weAppOrder.setBizId(bizId); + weAppOrder.setPayerId(orderVo.getPayer()); + weAppOrder.setPayerName(orderVo.getPayerName()); + weAppOrder.setTmOrderId(tmOrderNo); + weAppOrder.setAmount(totalAmount.toString()); + weAppOrder.setPayStatus("0"); + weAppOrderDao.insert(weAppOrder); + + return payResp; + } + + /** + * 构建分账请求(完全按你的业务逻辑) + */ + private ShopCarOrderCreateRequest buildShopCarOrderCreateRequest(OrderVo orderVo, String orderNo) throws Exception { + ShopCarOrderCreateRequest request = new ShopCarOrderCreateRequest(); + request.setVaMchntNo(mid); + request.setVaTermNo(tid); + request.setSubAppId(wxAppId); + request.setMchntOrderId(orderNo); + request.setMsgType("wx.unifiedOrder"); + request.setNotifyUrl(notifyUrl); + request.setTradeType("MINI"); + request.setSubOpenId(orderVo.getPayerOpenId()); + request.setSysSource("OPT"); + + VaFld vaFld = new VaFld(); + vaFld.setNewShopFlag("GWCXS"); + vaFld.setSatType("01"); + List satInfoList = new ArrayList<>(); + vaFld.setSatInfo(satInfoList); + + BigDecimal gyAmount = BigDecimal.ZERO; + BigDecimal fwglAmount = BigDecimal.ZERO; + + for (UnpaidBillVo billVo : orderVo.getBillVoList()) { + Map param = new HashMap<>(); + param.put("billNo", billVo.getBillNo()); + param.put("bizType", billVo.getBizType()); + String receiver = oaBillService.getBillPayReceiver(param); + billVo.setPayee(receiver); + + int amountCent = (int) (Double.parseDouble(billVo.getAmount()) * 100); + BigDecimal cent = new BigDecimal(amountCent); + + if (StringUtils.isNotBlank(receiver) && receiver.contains("广源")) { + gyAmount = gyAmount.add(cent); + } else { + fwglAmount = fwglAmount.add(cent); + } + } + + if (gyAmount.compareTo(BigDecimal.ZERO) > 0) { + SatInfo info = new SatInfo(); + info.setMerId(gyMid); + info.setFeeBear("Y"); + info.setSatAmt(gyAmount.toString()); + satInfoList.add(info); + } + if (fwglAmount.compareTo(BigDecimal.ZERO) > 0) { + SatInfo info = new SatInfo(); + info.setMerId(fwglMid); + info.setFeeBear("Y"); + info.setSatAmt(fwglAmount.toString()); + satInfoList.add(info); + } + + request.setTotalAmount(gyAmount.add(fwglAmount).toString()); + request.setVaFld(vaFld); + return request; + } + + /** + * 支付回调(幂等 + 批量更新子订单) + */ + @Transactional(rollbackFor = Exception.class) + public void tmPayCallback(String tmOrderNo, String payResult) { + WeAppOrder order = weAppOrderDao.selectByTmOrderId(tmOrderNo); + if (order == null || "1".equals(order.getPayStatus())) { + return; + } + + if ("SUCCESS".equalsIgnoreCase(payResult)) { + order.setPayStatus("1"); + weAppOrderDao.updateByPrimaryKeySelective(order); + + // 批量更新该主订单下 所有子订单(billNo)状态 + List subList = weAppSubOrderDao.selectByMainOrderId(order.getId()); + for (WeAppSubOrder sub : subList) { + sub.setPayStatus("1"); + weAppSubOrderDao.updateById(sub); + } + } else { + order.setPayStatus("2"); + weAppOrderDao.updateByPrimaryKeySelective(order); + } + } + + public void callBack(String bizId) { + WeAppOrder order = weAppOrderDao.findByBizId(bizId); + if (order != null) { + tmPayCallback(order.getTmOrderId(), "SUCCESS"); + } + } + + private UnifiedOrderRequest buildUnifiedOrderRequest(OrderVo orderVo) { + return null; + } +} diff --git a/src/main/java/org/chenyon/pay/OrderVo.java b/src/main/java/org/chenyon/pay/OrderVo.java new file mode 100644 index 0000000..1505a65 --- /dev/null +++ b/src/main/java/org/chenyon/pay/OrderVo.java @@ -0,0 +1,80 @@ +package org.chenyon.pay; + +import org.chenyon.bill.UnpaidBillVo; + +import java.util.List; + +public class OrderVo { + private String bizId; //业务id + private String amount; //金额 + private String payer; //付款方 + private String payerName; //付款方名称 + private String payStatus; //支付状态 + private String payerOpenId; // + private List billVoList; + private String clientIp; + + public String getBizId() { + return bizId; + } + + public void setBizId(String bizId) { + this.bizId = bizId; + } + + public String getAmount() { + return amount; + } + + public void setAmount(String amount) { + this.amount = amount; + } + + public String getPayer() { + return payer; + } + + public void setPayer(String payer) { + this.payer = payer; + } + + public List getBillVoList() { + return billVoList; + } + + public void setBillVoList(List billVoList) { + this.billVoList = billVoList; + } + + public String getPayStatus() { + return payStatus; + } + + public void setPayStatus(String payStatus) { + this.payStatus = payStatus; + } + + public String getPayerName() { + return payerName; + } + + public void setPayerName(String payerName) { + this.payerName = payerName; + } + + public String getPayerOpenId() { + return payerOpenId; + } + + public void setPayerOpenId(String payerOpenId) { + this.payerOpenId = payerOpenId; + } + + public String getClientIp() { + return clientIp; + } + + public void setClientIp(String clientIp) { + this.clientIp = clientIp; + } +} diff --git a/src/main/java/org/chenyon/pay/SubOrder.java b/src/main/java/org/chenyon/pay/SubOrder.java index d6999e7..9d470a1 100644 --- a/src/main/java/org/chenyon/pay/SubOrder.java +++ b/src/main/java/org/chenyon/pay/SubOrder.java @@ -10,6 +10,10 @@ public class SubOrder { /** 金额(分) */ private String totalAmount; + /** 微信子商户appId*/ + private String subAppId; + /** 用户子标识*/ + private String subOpenId; public String getMid() { return mid; @@ -34,4 +38,20 @@ public class SubOrder { public void setTotalAmount(String totalAmount) { this.totalAmount = totalAmount; } + + public String getSubAppId() { + return subAppId; + } + + public void setSubAppId(String subAppId) { + this.subAppId = subAppId; + } + + public String getSubOpenId() { + return subOpenId; + } + + public void setSubOpenId(String subOpenId) { + this.subOpenId = subOpenId; + } } \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/TmHttpUtil.java b/src/main/java/org/chenyon/pay/TmHttpUtil.java new file mode 100644 index 0000000..b18a859 --- /dev/null +++ b/src/main/java/org/chenyon/pay/TmHttpUtil.java @@ -0,0 +1,190 @@ +package org.chenyon.pay; + +import org.rcy.framework.utils.net.HttpRequestUtils; +import org.rcy.framework.utils.net.HttpResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Component +public class TmHttpUtil { + + @Value("${chinaums.appId}") + private String APP_ID; + @Value("${chinaums.appSecret}") + private String APP_KEY; + @Value("${chinaums.api.host}") + private String host; + @Autowired + private TmTokenService tmTokenService; + + public enum AuthMode { + TOKEN, SIGNATURE + } + + // ============================= + // POST 请求 + // ============================= + public String post(String urlStr, String body, AuthMode mode) { + Map headers = new HashMap<>(); + try { + String timestamp = now(); + String nonce = uuid(); + + if (mode == AuthMode.TOKEN) { + String token = tmTokenService.getToken(); + String authString = "OPEN-ACCESS-TOKEN accessToken=\"" + token + "\"" + "," + "AppId=\"" + APP_ID + "\""; + headers.put("Authorization", authString); + } else { + // 🔥 SIGN模式 + String signature = buildBodySignature(body, timestamp, nonce); + String authString = + "OPEN-BODY-SIG " + + "AppId=\"" + APP_ID + "\"," + + "Timestamp=\"" + timestamp + "\"," + + "Nonce=\"" + nonce + "\"," + + "Signature=\"" + signature + "\""; + headers.put("Authorization", authString); + } + HttpResponse response = HttpRequestUtils.sendPost(host + urlStr, body, headers); + return response.getRespStr(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // ============================= + // GET 请求 + // ============================= + public String get(String url, String content, AuthMode mode) { + Map headers = new HashMap<>(); + String respStr = null; + try { + if (mode == AuthMode.TOKEN) { + String token = tmTokenService.getToken(); + String authString = "OPEN-ACCESS-TOKEN accessToken=\"" + token + "\"" + "," + "AppId=\"" + APP_ID + "\""; + headers.put("Authorization", authString); + HttpResponse response = HttpRequestUtils.sendGet(host + url, headers); + respStr = response.getRespStr(); + } else { + // 🔥 GET签名模式 + String timestamp = now(); + String nonce = uuid(); + + String signature = buildGetSignature(content, timestamp, nonce); + + String finalUrl = host + url + + "?authorization=OPEN-FORM-PARAM" + + "&appId=" + APP_ID + + "×tamp=" + timestamp + + "&nonce=" + nonce + + "&content=" + URLEncoder.encode(content, "UTF-8") + + "&signature=" + signature; + + HttpResponse response = HttpRequestUtils.sendGet(finalUrl, null); + respStr = response.getRespStr(); + } + return respStr; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // ============================= + // 🔐 POST签名 + // ============================= + private String buildBodySignature(String body, String timestamp, String nonce) { + + String bodySha = sha256(body); + String signStr = APP_ID + timestamp + nonce + bodySha; + + return base64(hmac(signStr, APP_KEY)); + } + + // ============================= + // 🔐 GET签名 + // ============================= + private String buildGetSignature(String content, String timestamp, String nonce) throws Exception { + + String contentSha = sha256(content); + String signStr = APP_ID + timestamp + nonce + contentSha; + + String base64 = base64(hmac(signStr, APP_KEY)); + + return URLEncoder.encode(base64, "UTF-8"); + } + + // ============================= + // 工具方法 + // ============================= + private String sha256(String str) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] hash = md.digest(str.getBytes(StandardCharsets.UTF_8)); + + StringBuilder hex = new StringBuilder(); + for (byte b : hash) { + String s = Integer.toHexString(0xff & b); + if (s.length() == 1) hex.append('0'); + hex.append(s); + } + return hex.toString(); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private byte[] hmac(String data, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + return mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private String base64(byte[] data) { + return Base64.getEncoder().encodeToString(data); + } + + private String now() { + return LocalDateTime.now() + .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); + } + + private String uuid() { + return UUID.randomUUID().toString().replace("-", ""); + } + + private String read(HttpURLConnection conn) throws Exception { + BufferedReader br = new BufferedReader( + new InputStreamReader(conn.getInputStream(), "UTF-8")); + + StringBuilder sb = new StringBuilder(); + String line; + + while ((line = br.readLine()) != null) { + sb.append(line); + } + + return sb.toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/TmPayService.java b/src/main/java/org/chenyon/pay/TmPayService.java index e952955..9bda417 100644 --- a/src/main/java/org/chenyon/pay/TmPayService.java +++ b/src/main/java/org/chenyon/pay/TmPayService.java @@ -1,28 +1,24 @@ package org.chenyon.pay; -import com.chinaums.open.api.OpenApiContext; -import com.chinaums.open.api.internal.util.http.HttpTransport; +import org.chenyon.pay.shopcar.MiniPayRequest; +import org.chenyon.pay.shopcar.ShopCarOrderCreateRequest; +import org.chenyon.pay.shopcar.TmPayOrderRespVo; import org.rcy.framework.utils.json.JsonUtils; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; +import java.util.Map; + @Service public class TmPayService { - @Value("${chinaums.api.dev.host}") - private String devHost; - @Value("chinaums.api.prod.host") - private String prodHost; + @Autowired + private TmHttpUtil tmHttpUtil; public void weChatPayCreateOrder(UnifiedOrderRequest request) { - String url = "/v1/netpay/wx/unified-order"; - String appId = "123456"; - String appKey = "123456"; - OpenApiContext context = TmPayApiContextBuilder.build(appId, appKey, url); + String url = "/v1/inip/upsp/shop/mini/pay"; Long totalAmount = null; // if(Boolean.TRUE.equals(divisionFlag)){ // request.setDivisionFlag(divisionFlag); @@ -35,10 +31,37 @@ public class TmPayService { request.setMid("");// 设置商户号 request.setTid(""); try { - HttpTransport.getInstance().doPost(context, JsonUtils.convertJson(request)); + } catch (Exception e) { throw new RuntimeException(e); } } + public TmPayOrderRespVo weChatPayCreateSplitOrder(ShopCarOrderCreateRequest request) { + String url = "/v1/inip/upsp/shop/mini/pay"; + try { + String respStr = tmHttpUtil.post(url, JsonUtils.convertJson(request), TmHttpUtil.AuthMode.SIGNATURE); + Map map = JsonUtils.parseObject(respStr, Map.class); + String code = (String)map.get("respCode"); + if(!"0000".equals(code)){ + throw new RuntimeException("创建订单失败"); + } + String forwardUrl = (String)map.get("url"); + Map miniRequestMap = (Map) map.get("miniPayRequest"); + MiniPayRequest miniPayRequest = new MiniPayRequest(); + miniPayRequest.setAppId(miniRequestMap.get("appId")); + miniPayRequest.setNonceStr(miniRequestMap.get("nonceStr")); + miniPayRequest.setPackageStr(miniRequestMap.get("package")); + miniPayRequest.setPaySign(miniRequestMap.get("paySign")); + miniPayRequest.setSignType(miniRequestMap.get("signType")); + miniPayRequest.setTimeStamp(miniRequestMap.get("timeStamp")); + TmPayOrderRespVo tmPayOrderRespVo = new TmPayOrderRespVo(); + tmPayOrderRespVo.setUrl(forwardUrl); + tmPayOrderRespVo.setMiniPayRequest(miniPayRequest); + return tmPayOrderRespVo; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } diff --git a/src/main/java/org/chenyon/pay/TmPaySignatureUtils.java b/src/main/java/org/chenyon/pay/TmPaySignatureUtils.java new file mode 100644 index 0000000..3f2a2ae --- /dev/null +++ b/src/main/java/org/chenyon/pay/TmPaySignatureUtils.java @@ -0,0 +1,69 @@ +package org.chenyon.pay; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.Base64; + +public class TmPaySignatureUtils { + + // SHA256(返回16进制小写) + public static String sha256Hex(String data) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8)); + StringBuilder hex = new StringBuilder(); + for (byte b : hash) { + String s = Integer.toHexString(0xff & b); + if (s.length() == 1) hex.append('0'); + hex.append(s); + } + return hex.toString(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // HmacSHA256 + Base64 + public static String hmacSha256Base64(String data, String key) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKey = + new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + mac.init(secretKey); + byte[] raw = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(raw); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + // ============================= + // 🔥 POST Body签名 + // ============================= + public static String buildBodySignature(String appId, String timestamp, String nonce, String body, String appKey) { + + String bodySha = sha256Hex(body); + String signStr = appId + timestamp + nonce + bodySha; + + return hmacSha256Base64(signStr, appKey); + } + + // ============================= + // 🔥 GET签名 + // ============================= + public static String buildGetSignature(String appId, String timestamp, String nonce, String content, String appKey) { + try { + String contentSha = sha256Hex(content); + String signStr = appId + timestamp + nonce + contentSha; + + String base64 = hmacSha256Base64(signStr, appKey); + + return URLEncoder.encode(base64, "UTF-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/TmTokenService.java b/src/main/java/org/chenyon/pay/TmTokenService.java new file mode 100644 index 0000000..cf8d110 --- /dev/null +++ b/src/main/java/org/chenyon/pay/TmTokenService.java @@ -0,0 +1,133 @@ +package org.chenyon.pay; + +import org.rcy.framework.utils.json.JsonUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.UUID; + +@Service +public class TmTokenService { + + @Value("${chinaums.appId}") + private String APP_ID; + @Value("${chinaums.appSecret}") + private String APP_KEY; + @Value("${chinaums.api.host}") + private String host; + private final String TOKEN_URL = "/v2/token/access"; + @Autowired + private LocalKvRedis localKvRedis; + + // 获取Token(自动缓存) + public synchronized String getToken() throws IOException { + String token = localKvRedis.get("TM-Token"); + if (token != null) { + return token; + } + + String timestamp = now(); + String nonce = UUID.randomUUID().toString().replace("-", ""); + String signature = TmPaySignatureUtils.sha256Hex(APP_ID + timestamp + nonce + APP_KEY); + String json = "{" + + "\"appId\":\"" + APP_ID + "\"," + + "\"timestamp\":\"" + timestamp + "\"," + + "\"nonce\":\"" + nonce + "\"," + + "\"signMethod\":\"SHA256\"," + + "\"signature\":\"" + signature + "\"" + + "}"; + + String resp = postJson(host + TOKEN_URL, json, null); + Map map = JsonUtils.parseObject(resp, Map.class); + String accessToken = (String)map.get("accessToken"); + Integer expiresIn = Integer.parseInt(map.get("expiresIn") + ""); + token = accessToken; + localKvRedis.set("TM-Token", token, expiresIn); + return token; + } + + private String now() { + return LocalDateTime.now() + .format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); + } + + private String postJson(String urlStr, String json, Map headers) { + + HttpURLConnection conn = null; + BufferedReader reader = null; + + try { + URL url = new URL(urlStr); + conn = (HttpURLConnection) url.openConnection(); + + // ============================= + // 基础配置 + // ============================= + conn.setRequestMethod("POST"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setConnectTimeout(15000); + conn.setReadTimeout(15000); + + conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + + // ============================= + // 🔥 可选Header(比如token接口这里传null) + // ============================= + if (headers != null) { + for (Map.Entry entry : headers.entrySet()) { + conn.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + + // ============================= + // 写入请求体 + // ============================= + try (OutputStream os = conn.getOutputStream()) { + os.write(json.getBytes("UTF-8")); + os.flush(); + } + + // ============================= + // 读取响应(成功 or 失败都能读) + // ============================= + int statusCode = conn.getResponseCode(); + + InputStream is; + if (statusCode >= 200 && statusCode < 300) { + is = conn.getInputStream(); + } else { + is = conn.getErrorStream(); // 🔥关键:错误流 + } + + reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); + + StringBuilder response = new StringBuilder(); + String line; + + while ((line = reader.readLine()) != null) { + response.append(line); + } + + return response.toString(); + + } catch (Exception e) { + throw new RuntimeException("POST请求异常: " + e.getMessage(), e); + } finally { + try { + if (reader != null) reader.close(); + } catch (IOException ignored) {} + + if (conn != null) conn.disconnect(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/UnifiedOrderRequest.java b/src/main/java/org/chenyon/pay/UnifiedOrderRequest.java index 8692535..71f4b24 100644 --- a/src/main/java/org/chenyon/pay/UnifiedOrderRequest.java +++ b/src/main/java/org/chenyon/pay/UnifiedOrderRequest.java @@ -17,11 +17,8 @@ public class UnifiedOrderRequest { private String tid; /** 订单总金额(分) */ - private Long totalAmount; - /** 微信子商户appId*/ - private String subAppId; - /** 用户子标识*/ - private String subOpenId; + private String totalAmount; + /** 微信:MINI / JSAPI */ private String tradeType; @@ -36,7 +33,7 @@ public class UnifiedOrderRequest { /** 同步分账标识*/ private Boolean divisionFlag; /** 分账金额*/ - private Long platformAmount; + private String platformAmount; /** 通知地址 */ private String notifyUrl; @@ -156,30 +153,6 @@ public class UnifiedOrderRequest { this.retCommParams = retCommParams; } - public Long getTotalAmount() { - return totalAmount; - } - - public void setTotalAmount(Long totalAmount) { - this.totalAmount = totalAmount; - } - - public String getSubAppId() { - return subAppId; - } - - public void setSubAppId(String subAppId) { - this.subAppId = subAppId; - } - - public String getSubOpenId() { - return subOpenId; - } - - public void setSubOpenId(String subOpenId) { - this.subOpenId = subOpenId; - } - public Boolean getDivisionFlag() { return divisionFlag; } @@ -188,11 +161,19 @@ public class UnifiedOrderRequest { this.divisionFlag = divisionFlag; } - public Long getPlatformAmount() { + public String getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(String totalAmount) { + this.totalAmount = totalAmount; + } + + public String getPlatformAmount() { return platformAmount; } - public void setPlatformAmount(Long platformAmount) { + public void setPlatformAmount(String platformAmount) { this.platformAmount = platformAmount; } } \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/WeAppOrder.java b/src/main/java/org/chenyon/pay/WeAppOrder.java new file mode 100644 index 0000000..f8efd77 --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppOrder.java @@ -0,0 +1,86 @@ +package org.chenyon.pay; + +import org.rcy.framework.api.entity.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.Date; + +@Entity +@Table(name = "ORDER") +public class WeAppOrder extends BaseEntity { + + private String bizId; + private String payerId; + private Date payDate; + private String amount; + private String payerName; //付款方名称 + private String payStatus; //支付状态 + private String payerOpenId; // + private String tmOrderId; //银联支付订单号 + + + public String getBizId() { + return bizId; + } + + public void setBizId(String bizId) { + this.bizId = bizId; + } + + public String getPayerId() { + return payerId; + } + + public void setPayerId(String payerId) { + this.payerId = payerId; + } + + public Date getPayDate() { + return payDate; + } + + public void setPayDate(Date payDate) { + this.payDate = payDate; + } + + public String getAmount() { + return amount; + } + + public void setAmount(String amount) { + this.amount = amount; + } + + public String getPayerName() { + return payerName; + } + + public void setPayerName(String payerName) { + this.payerName = payerName; + } + + public String getPayStatus() { + return payStatus; + } + + public void setPayStatus(String payStatus) { + this.payStatus = payStatus; + } + + public String getPayerOpenId() { + return payerOpenId; + } + + public void setPayerOpenId(String payerOpenId) { + this.payerOpenId = payerOpenId; + } + + public String getTmOrderId() { + return tmOrderId; + } + + public void setTmOrderId(String tmOrderId) { + this.tmOrderId = tmOrderId; + } +} diff --git a/src/main/java/org/chenyon/pay/WeAppOrderDao.java b/src/main/java/org/chenyon/pay/WeAppOrderDao.java new file mode 100644 index 0000000..ca41ebe --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppOrderDao.java @@ -0,0 +1,8 @@ +package org.chenyon.pay; + +import org.rcy.framework.data.dao.BaseDao; + +public interface WeAppOrderDao extends BaseDao { + WeAppOrder findByBizId(String bizId); + WeAppOrder selectByTmOrderId(String tmOrderNo); +} diff --git a/src/main/java/org/chenyon/pay/WeAppOrderDao.xml b/src/main/java/org/chenyon/pay/WeAppOrderDao.xml new file mode 100644 index 0000000..ebac760 --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppOrderDao.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/WeAppSubOrder.java b/src/main/java/org/chenyon/pay/WeAppSubOrder.java new file mode 100644 index 0000000..3c1aaf5 --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppSubOrder.java @@ -0,0 +1,56 @@ +package org.chenyon.pay; + +import org.rcy.framework.api.entity.BaseEntity; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "SUB_ORDER") +public class WeAppSubOrder extends BaseEntity { + private String billNo; + private String bizSubType; + private String amount; + private Long mainOrderId; + private String payStatus; + + public String getBillNo() { + return billNo; + } + + public void setBillNo(String billNo) { + this.billNo = billNo; + } + + public String getBizSubType() { + return bizSubType; + } + + public void setBizSubType(String bizSubType) { + this.bizSubType = bizSubType; + } + + public String getAmount() { + return amount; + } + + public void setAmount(String amount) { + this.amount = amount; + } + + public Long getMainOrderId() { + return mainOrderId; + } + + public void setMainOrderId(Long mainOrderId) { + this.mainOrderId = mainOrderId; + } + + public String getPayStatus() { + return payStatus; + } + + public void setPayStatus(String payStatus) { + this.payStatus = payStatus; + } +} diff --git a/src/main/java/org/chenyon/pay/WeAppSubOrderDao.java b/src/main/java/org/chenyon/pay/WeAppSubOrderDao.java new file mode 100644 index 0000000..cd94c58 --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppSubOrderDao.java @@ -0,0 +1,15 @@ +package org.chenyon.pay; + +import org.rcy.framework.data.dao.BaseDao; + +import java.util.List; + +public interface WeAppSubOrderDao extends BaseDao { + + WeAppSubOrder selectByBillNo(String billNo); + + List selectByMainOrderId(Long mainOrderId); + + Integer updateById(WeAppSubOrder subOrder); + +} diff --git a/src/main/java/org/chenyon/pay/WeAppSubOrderDao.xml b/src/main/java/org/chenyon/pay/WeAppSubOrderDao.xml new file mode 100644 index 0000000..4893a5f --- /dev/null +++ b/src/main/java/org/chenyon/pay/WeAppSubOrderDao.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/shopcar/GoodsInfo.java b/src/main/java/org/chenyon/pay/shopcar/GoodsInfo.java new file mode 100644 index 0000000..b274c96 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/GoodsInfo.java @@ -0,0 +1,32 @@ +package org.chenyon.pay.shopcar; + +public class GoodsInfo { + + private String goodsName; + private Integer goodsNum; + private Integer goodsPrice; + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public Integer getGoodsNum() { + return goodsNum; + } + + public void setGoodsNum(Integer goodsNum) { + this.goodsNum = goodsNum; + } + + public Integer getGoodsPrice() { + return goodsPrice; + } + + public void setGoodsPrice(Integer goodsPrice) { + this.goodsPrice = goodsPrice; + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/shopcar/MiniPayRequest.java b/src/main/java/org/chenyon/pay/shopcar/MiniPayRequest.java new file mode 100644 index 0000000..73d35a9 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/MiniPayRequest.java @@ -0,0 +1,58 @@ +package org.chenyon.pay.shopcar; + +public class MiniPayRequest { + private String timeStamp; + private String packageStr; + private String paySign; + private String appId; + private String signType; + private String nonceStr; + + public String getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getPackageStr() { + return packageStr; + } + + public void setPackageStr(String packageStr) { + this.packageStr = packageStr; + } + + public String getPaySign() { + return paySign; + } + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getSignType() { + return signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + + public String getNonceStr() { + return nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } +} diff --git a/src/main/java/org/chenyon/pay/shopcar/RetCommParams.java b/src/main/java/org/chenyon/pay/shopcar/RetCommParams.java new file mode 100644 index 0000000..4b44ed3 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/RetCommParams.java @@ -0,0 +1,16 @@ +package org.chenyon.pay.shopcar; + +import java.util.Map; + +public class RetCommParams { + + private Map map; + + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/shopcar/SatInfo.java b/src/main/java/org/chenyon/pay/shopcar/SatInfo.java new file mode 100644 index 0000000..d830c52 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/SatInfo.java @@ -0,0 +1,105 @@ +package org.chenyon.pay.shopcar; + +/** + * 分账信息 + */ +public class SatInfo { + + /** + * 子商户号 + */ + private String merId; + /** + * 手续费承担方 + */ + private String feeBear; + /** + * 子商户上送交易 + */ + private String payBear; + /** + * 商户子订单号 + */ + private String merOrderId; + /** + * 分账所得额 + */ + private String satAmt; + private String orderDesc; + private String remark; + private Integer subsidyAmt; + + private GoodsInfo goodsInfo; + + public String getMerId() { + return merId; + } + + public void setMerId(String merId) { + this.merId = merId; + } + + public String getFeeBear() { + return feeBear; + } + + public void setFeeBear(String feeBear) { + this.feeBear = feeBear; + } + + public String getPayBear() { + return payBear; + } + + public void setPayBear(String payBear) { + this.payBear = payBear; + } + + public String getMerOrderId() { + return merOrderId; + } + + public void setMerOrderId(String merOrderId) { + this.merOrderId = merOrderId; + } + + public String getSatAmt() { + return satAmt; + } + + public void setSatAmt(String satAmt) { + this.satAmt = satAmt; + } + + public String getOrderDesc() { + return orderDesc; + } + + public void setOrderDesc(String orderDesc) { + this.orderDesc = orderDesc; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public Integer getSubsidyAmt() { + return subsidyAmt; + } + + public void setSubsidyAmt(Integer subsidyAmt) { + this.subsidyAmt = subsidyAmt; + } + + public GoodsInfo getGoodsInfo() { + return goodsInfo; + } + + public void setGoodsInfo(GoodsInfo goodsInfo) { + this.goodsInfo = goodsInfo; + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderCreateRequest.java b/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderCreateRequest.java new file mode 100644 index 0000000..1329f9c --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderCreateRequest.java @@ -0,0 +1,493 @@ +package org.chenyon.pay.shopcar; + +import org.chenyon.pay.Goods; + +public class ShopCarOrderCreateRequest { + /** + * 商户订单号 + */ + private String mchntOrderId; + /** + * 商户号 + */ + private String vaMchntNo; + /** + * 终端号 + */ + private String vaTermNo; + /** + * 请求预留字段 + */ + private String srcReserve; + /** + * 业务模板,用来替代mid + * 作为大商户统一接入第三 + * 方,用于POS通等转商户 + * 交易场景 + * MINIDEFAULT + */ + private String instMid; + /** + * 消息类型 + * 微信: wx.unifiedOrder + * 支付宝: trade.create + * 云闪付: uac.miniOrder + */ + private String msgType; + /** + * 商品信息 + */ + private Goods goods; + /** + * 商户附加数据 + */ + private String attachedData; + /** + * 订单过期时间 + */ + private String expireTime; + /** + * 商品标记 + */ + private String goodsTag; + /** + * 商品交易单号 + * 跟goods字段二选一,商品信息通过goods.add接口 + * 提前上送 + */ + private String goodsTradeNo; + /** + * 订单描述 + */ + private String orderDesc; + /** + * 商品ID + */ + private String productId; + /** + * 订单原始金额,单位分, + * 用于记录前端系统打折前 + * 的金额 + */ + private String originalAmount; + /** + * 支付总金额,若divisionFlag为true,则: + * totalAmount=subOrders字段中的所有totalAmount + * 值之和 加上 platformAmount值=goods中的所有 + * subOrderAmount值之和 + */ + private String totalAmount; + /** + * 支付结果通知地址 + */ + private String notifyUrl; + /** + * 网页跳转地址 + */ + private String returnUrl; + /** + * 下单场景 + */ + private String placeOrderScene; + /** + * 订单展示页面 + */ + private String showUrl; + /** + * subAppId + */ + private String subAppId; + /** + * 用户子标识,商户自己公众号appid下的用户openid,可以通过微 + * 信oauth接口获取。 + */ + private String subOpenId; + /** + * 支付宝买家ID,支付宝必传 + * 需要商户自行调用支付宝接口获取,具体获取方式 请 + * 根据支付宝接口文档。 + */ + private String userId; + /** + * 交易类型,值为MINI,如果使用云闪付云微小程序支付时需要上 + * 送UP_WX_MINI + */ + private String tradeType; + /** + * 是否需要限制信用卡支付 + */ + private String limitCreditCard; + /** + * 花呗分期数 + */ + private String installmentNumber; + /** + * 实名认证姓名,Base64编码 + * 跨境交易时,该字段必须传 + */ + private String name; + /** + * 实名认证手机号,Base64编码 + * 跨境交易时,该字段可选 + */ + private String mobile; + /** + * 实名认证证件类型,证件类型,微信,银联支持身份证、支付宝支持身份 + * 证:IDENTITY_CARD、护照:PASSPORT、军官证: + * OFFICER_CARD、士兵证:SOLDIER_CARD、户口 + * 本:HOKOU + * 跨境交易时,该字段必须传 + */ + private String certType; + /** + * 实名认证证件号,Base64编码 + * 跨境交易时,该字段必须传 + */ + private String certNo; + /** + * 是否需要实名认证,需要实名认证时置为 T + * 跨境交易时,该字段必须传 + */ + private String fixBuyer; + + private RetCommParams retCommParams; + + private Boolean thirdPartyInstalSubsFlag; + private String bankCardNo; + private String invokeScene; + private String discountCode; + + private String ylyxId; + private String ylyxName; + private String ylyxMerAbbr; + /** + * 系统来源,商终密:SZM + * 开放平台: OPT + * 当需要接收交易结果通知时,需上送从UP系统申请的 + * 消息来源,同网付msgSrc,并且联系业务人员在新购 + * 物车录入对应的密钥 + */ + private String sysSource; + + private VaFld vaFld; + + public String getMchntOrderId() { + return mchntOrderId; + } + + public void setMchntOrderId(String mchntOrderId) { + this.mchntOrderId = mchntOrderId; + } + + public String getVaMchntNo() { + return vaMchntNo; + } + + public void setVaMchntNo(String vaMchntNo) { + this.vaMchntNo = vaMchntNo; + } + + public String getVaTermNo() { + return vaTermNo; + } + + public void setVaTermNo(String vaTermNo) { + this.vaTermNo = vaTermNo; + } + + public String getSrcReserve() { + return srcReserve; + } + + public void setSrcReserve(String srcReserve) { + this.srcReserve = srcReserve; + } + + public String getInstMid() { + return instMid; + } + + public void setInstMid(String instMid) { + this.instMid = instMid; + } + + public String getMsgType() { + return msgType; + } + + public void setMsgType(String msgType) { + this.msgType = msgType; + } + + public Goods getGoods() { + return goods; + } + + public void setGoods(Goods goods) { + this.goods = goods; + } + + public String getAttachedData() { + return attachedData; + } + + public void setAttachedData(String attachedData) { + this.attachedData = attachedData; + } + + public String getExpireTime() { + return expireTime; + } + + public void setExpireTime(String expireTime) { + this.expireTime = expireTime; + } + + public String getGoodsTag() { + return goodsTag; + } + + public void setGoodsTag(String goodsTag) { + this.goodsTag = goodsTag; + } + + public String getGoodsTradeNo() { + return goodsTradeNo; + } + + public void setGoodsTradeNo(String goodsTradeNo) { + this.goodsTradeNo = goodsTradeNo; + } + + public String getOrderDesc() { + return orderDesc; + } + + public void setOrderDesc(String orderDesc) { + this.orderDesc = orderDesc; + } + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public String getOriginalAmount() { + return originalAmount; + } + + public void setOriginalAmount(String originalAmount) { + this.originalAmount = originalAmount; + } + + public String getTotalAmount() { + return totalAmount; + } + + public void setTotalAmount(String totalAmount) { + this.totalAmount = totalAmount; + } + + public String getNotifyUrl() { + return notifyUrl; + } + + public void setNotifyUrl(String notifyUrl) { + this.notifyUrl = notifyUrl; + } + + public String getReturnUrl() { + return returnUrl; + } + + public void setReturnUrl(String returnUrl) { + this.returnUrl = returnUrl; + } + + public String getPlaceOrderScene() { + return placeOrderScene; + } + + public void setPlaceOrderScene(String placeOrderScene) { + this.placeOrderScene = placeOrderScene; + } + + public String getShowUrl() { + return showUrl; + } + + public void setShowUrl(String showUrl) { + this.showUrl = showUrl; + } + + public String getSubAppId() { + return subAppId; + } + + public void setSubAppId(String subAppId) { + this.subAppId = subAppId; + } + + public String getSubOpenId() { + return subOpenId; + } + + public void setSubOpenId(String subOpenId) { + this.subOpenId = subOpenId; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getTradeType() { + return tradeType; + } + + public void setTradeType(String tradeType) { + this.tradeType = tradeType; + } + + public String getLimitCreditCard() { + return limitCreditCard; + } + + public void setLimitCreditCard(String limitCreditCard) { + this.limitCreditCard = limitCreditCard; + } + + public String getInstallmentNumber() { + return installmentNumber; + } + + public void setInstallmentNumber(String installmentNumber) { + this.installmentNumber = installmentNumber; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getCertType() { + return certType; + } + + public void setCertType(String certType) { + this.certType = certType; + } + + public String getCertNo() { + return certNo; + } + + public void setCertNo(String certNo) { + this.certNo = certNo; + } + + public String getFixBuyer() { + return fixBuyer; + } + + public void setFixBuyer(String fixBuyer) { + this.fixBuyer = fixBuyer; + } + + public RetCommParams getRetCommParams() { + return retCommParams; + } + + public void setRetCommParams(RetCommParams retCommParams) { + this.retCommParams = retCommParams; + } + + public Boolean getThirdPartyInstalSubsFlag() { + return thirdPartyInstalSubsFlag; + } + + public void setThirdPartyInstalSubsFlag(Boolean thirdPartyInstalSubsFlag) { + this.thirdPartyInstalSubsFlag = thirdPartyInstalSubsFlag; + } + + public String getBankCardNo() { + return bankCardNo; + } + + public void setBankCardNo(String bankCardNo) { + this.bankCardNo = bankCardNo; + } + + public String getInvokeScene() { + return invokeScene; + } + + public void setInvokeScene(String invokeScene) { + this.invokeScene = invokeScene; + } + + public String getDiscountCode() { + return discountCode; + } + + public void setDiscountCode(String discountCode) { + this.discountCode = discountCode; + } + + public String getYlyxId() { + return ylyxId; + } + + public void setYlyxId(String ylyxId) { + this.ylyxId = ylyxId; + } + + public String getYlyxName() { + return ylyxName; + } + + public void setYlyxName(String ylyxName) { + this.ylyxName = ylyxName; + } + + public String getYlyxMerAbbr() { + return ylyxMerAbbr; + } + + public void setYlyxMerAbbr(String ylyxMerAbbr) { + this.ylyxMerAbbr = ylyxMerAbbr; + } + + public String getSysSource() { + return sysSource; + } + + public void setSysSource(String sysSource) { + this.sysSource = sysSource; + } + + public VaFld getVaFld() { + return vaFld; + } + + public void setVaFld(VaFld vaFld) { + this.vaFld = vaFld; + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderQueryRequest.java b/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderQueryRequest.java new file mode 100644 index 0000000..f8200ee --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/ShopCarOrderQueryRequest.java @@ -0,0 +1,79 @@ +package org.chenyon.pay.shopcar; + +public class ShopCarOrderQueryRequest { + /** + * 商户订单号,必传 + */ + private String mchntOrderId; + /** + * 商户号,必传 + */ + private String vaMchntNo; + /** + * 终端号,必传 + */ + private String vaTermNo; + private String srcReserve; + private String instMid; + private String sysSource; + /** + * 增值域,必传 + */ + private VaFld vaFld; + + public String getMchntOrderId() { + return mchntOrderId; + } + + public void setMchntOrderId(String mchntOrderId) { + this.mchntOrderId = mchntOrderId; + } + + public String getVaMchntNo() { + return vaMchntNo; + } + + public void setVaMchntNo(String vaMchntNo) { + this.vaMchntNo = vaMchntNo; + } + + public String getVaTermNo() { + return vaTermNo; + } + + public void setVaTermNo(String vaTermNo) { + this.vaTermNo = vaTermNo; + } + + public String getSrcReserve() { + return srcReserve; + } + + public void setSrcReserve(String srcReserve) { + this.srcReserve = srcReserve; + } + + public String getInstMid() { + return instMid; + } + + public void setInstMid(String instMid) { + this.instMid = instMid; + } + + public String getSysSource() { + return sysSource; + } + + public void setSysSource(String sysSource) { + this.sysSource = sysSource; + } + + public VaFld getVaFld() { + return vaFld; + } + + public void setVaFld(VaFld vaFld) { + this.vaFld = vaFld; + } +} diff --git a/src/main/java/org/chenyon/pay/shopcar/TmPayOrderRespVo.java b/src/main/java/org/chenyon/pay/shopcar/TmPayOrderRespVo.java new file mode 100644 index 0000000..90df7e3 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/TmPayOrderRespVo.java @@ -0,0 +1,23 @@ +package org.chenyon.pay.shopcar; + +public class TmPayOrderRespVo { + + private String url; + private MiniPayRequest miniPayRequest; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public MiniPayRequest getMiniPayRequest() { + return miniPayRequest; + } + + public void setMiniPayRequest(MiniPayRequest miniPayRequest) { + this.miniPayRequest = miniPayRequest; + } +} diff --git a/src/main/java/org/chenyon/pay/shopcar/TmPayResponse.java b/src/main/java/org/chenyon/pay/shopcar/TmPayResponse.java new file mode 100644 index 0000000..1dd1d2a --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/TmPayResponse.java @@ -0,0 +1,22 @@ +package org.chenyon.pay.shopcar; + +public class TmPayResponse { + private String respCode; + private String respDesc; + + public String getRespCode() { + return respCode; + } + + public void setRespCode(String respCode) { + this.respCode = respCode; + } + + public String getRespDesc() { + return respDesc; + } + + public void setRespDesc(String respDesc) { + this.respDesc = respDesc; + } +} diff --git a/src/main/java/org/chenyon/pay/shopcar/VaFld.java b/src/main/java/org/chenyon/pay/shopcar/VaFld.java new file mode 100644 index 0000000..34db062 --- /dev/null +++ b/src/main/java/org/chenyon/pay/shopcar/VaFld.java @@ -0,0 +1,81 @@ +package org.chenyon.pay.shopcar; + +import java.util.List; + +public class VaFld { + + /** + * 新购物车标识, + * 新购物车交易需上送 如果不上送则为标准支付交易 + * 线上-GWCXS + * 线下-BC-GWCBC + * 线下银行卡-GWCYH + */ + private String newShopFlag; + /** + * 交易上送方式,01:主商户上送 + * 02:子商户上送(目前仅支持公众号、小程序、H5、 + * App、聚分期) + */ + private String isSubMchntPay; + /** + * 平台分账金额 + */ + private String platAmt; + /** + * 分账类型,01-同步分账 + * 02-异步分账 + */ + private String satType; + + private GoodsInfo goodsInfo; + private List satInfo; + + public String getNewShopFlag() { + return newShopFlag; + } + + public void setNewShopFlag(String newShopFlag) { + this.newShopFlag = newShopFlag; + } + + public String getIsSubMchntPay() { + return isSubMchntPay; + } + + public void setIsSubMchntPay(String isSubMchntPay) { + this.isSubMchntPay = isSubMchntPay; + } + + public String getPlatAmt() { + return platAmt; + } + + public void setPlatAmt(String platAmt) { + this.platAmt = platAmt; + } + + public String getSatType() { + return satType; + } + + public void setSatType(String satType) { + this.satType = satType; + } + + public GoodsInfo getGoodsInfo() { + return goodsInfo; + } + + public void setGoodsInfo(GoodsInfo goodsInfo) { + this.goodsInfo = goodsInfo; + } + + public List getSatInfo() { + return satInfo; + } + + public void setSatInfo(List satInfo) { + this.satInfo = satInfo; + } +} \ No newline at end of file diff --git a/src/main/java/org/chenyon/potential/PotentialController.java b/src/main/java/org/chenyon/potential/PotentialController.java index c69ad69..946ded3 100644 --- a/src/main/java/org/chenyon/potential/PotentialController.java +++ b/src/main/java/org/chenyon/potential/PotentialController.java @@ -1,7 +1,7 @@ package org.chenyon.potential; -import org.chenyon.user.LoginCheck; -import org.chenyon.user.UserContext; + +import org.apache.commons.lang3.StringUtils; import org.chenyon.user.UserService; import org.chenyon.user.UserVo; import org.chenyon.wx.WxUserSession; @@ -33,14 +33,23 @@ public class PotentialController { public ResultMessage addViewRecord(HttpServletRequest request, @RequestParam("assetId") String assetId) { try { String token = request.getHeader("WT"); - String userType = request.getHeader("USERTYPE"); + String userType = request.getParameter("userType"); + if(StringUtils.isAnyBlank(token,userType)){ + return ResultMessage.success(); + } + String assetsNo = request.getParameter("assetId"); + String assetsName = request.getParameter("assetsName"); WxUserSession session = wxUserSessionService.getSessionInfoByThirdSession(token); UserVo userVo = userService.findByOpenIdAndUserType(session.getOpenId(), userType); ViewRecordVo viewRecordVo = new ViewRecordVo(); - viewRecordVo.setAssetsNo(assetId); + viewRecordVo.setAssetsNo(assetsNo); + viewRecordVo.setAssetsName(assetsName); viewRecordVo.setCusNo(userVo.getCusNo()); viewRecordVo.setPhone(userVo.getPhone()); viewRecordVo.setCusName(userVo.getUserName()); + if(StringUtils.isBlank(userVo.getPhone())) { + return ResultMessage.success(); + } potentialService.add(viewRecordVo); }catch (Exception e) { log.warn("记录租户浏览记录失败: " + e.getMessage(),e); diff --git a/src/main/java/org/chenyon/potential/ViewRecordVo.java b/src/main/java/org/chenyon/potential/ViewRecordVo.java index 1695117..57673c4 100644 --- a/src/main/java/org/chenyon/potential/ViewRecordVo.java +++ b/src/main/java/org/chenyon/potential/ViewRecordVo.java @@ -6,6 +6,7 @@ public class ViewRecordVo { private String cusName; private String phone; private String assetsNo; + private String assetsName; public String getCusNo() { return cusNo; @@ -38,4 +39,12 @@ public class ViewRecordVo { public void setAssetsNo(String assetsNo) { this.assetsNo = assetsNo; } + + public String getAssetsName() { + return assetsName; + } + + public void setAssetsName(String assetsName) { + this.assetsName = assetsName; + } } diff --git a/src/main/java/org/chenyon/reservation/ReservateController.java b/src/main/java/org/chenyon/reservation/ReservateController.java index 3d3300b..0c628ba 100644 --- a/src/main/java/org/chenyon/reservation/ReservateController.java +++ b/src/main/java/org/chenyon/reservation/ReservateController.java @@ -61,7 +61,7 @@ public class ReservateController { public ResultMessage countHandling() { try { UserContext userContext = UserContext.get(); - if(userContext == null || userContext.getCusNo() == null) { + if(userContext == null || userContext.getOpenId() == null) { return ResultMessage.success(0); } return ResultMessage.success(reservateService.countHandling(userContext.getOpenId())); diff --git a/src/main/java/org/chenyon/user/LoginController.java b/src/main/java/org/chenyon/user/LoginController.java index e4d10fc..29c587b 100644 --- a/src/main/java/org/chenyon/user/LoginController.java +++ b/src/main/java/org/chenyon/user/LoginController.java @@ -8,6 +8,7 @@ import org.rcy.framework.utils.net.HttpRequestUtils; import org.rcy.framework.utils.net.HttpResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -81,6 +82,22 @@ public class LoginController { return ResultMessage.success(userVo); } + @GetMapping("/subscribeMsg") + @LoginCheck + public ResultMessage subscribeMsg(@RequestParam("subscribe") Boolean subscribe) throws Exception { + UserContext userContext = UserContext.get(); + if(userContext == null) { + return ResultMessage.success(); + } + WxUserSession wxUserSession = wxUserSessionService.getSessionInfoByThirdSession(userContext.getToken()); + UserVo userVo = userService.findByOpenIdAndUserType(wxUserSession.getOpenId(), userContext.getUserType()); + User user = new User(); + BeanUtils.copyProperties(userVo,user); + user.setSubscribeMsg(subscribe); + userService.upsert(user); + return ResultMessage.success(); + } + @PostMapping("/updateVerifyCode") @LoginCheck public ResultMessage updateVerifyCode(HttpServletRequest request,@RequestBody AuthInfoVo authInfoVo) throws Exception { diff --git a/src/main/java/org/chenyon/user/UserDao.java b/src/main/java/org/chenyon/user/UserDao.java index 03a92e6..56e2d48 100644 --- a/src/main/java/org/chenyon/user/UserDao.java +++ b/src/main/java/org/chenyon/user/UserDao.java @@ -4,5 +4,6 @@ import org.rcy.framework.data.dao.BaseDao; import org.springframework.web.bind.annotation.RequestParam; public interface UserDao extends BaseDao { - User findByOpenIdAndUserType(@RequestParam("openId") String openId,@RequestParam("loginType") String loginType); + User findByOpenIdAndUserType(@RequestParam("openId") String openId,@RequestParam("userType") String userType); + User findByCusNo(@RequestParam("cusNo") String cusNo); } diff --git a/src/main/java/org/chenyon/user/UserDao.xml b/src/main/java/org/chenyon/user/UserDao.xml index d3000e3..1bdd67c 100644 --- a/src/main/java/org/chenyon/user/UserDao.xml +++ b/src/main/java/org/chenyon/user/UserDao.xml @@ -4,6 +4,9 @@ + \ No newline at end of file diff --git a/src/main/java/org/chenyon/user/UserService.java b/src/main/java/org/chenyon/user/UserService.java index 1b97f0c..4c98b39 100644 --- a/src/main/java/org/chenyon/user/UserService.java +++ b/src/main/java/org/chenyon/user/UserService.java @@ -25,6 +25,11 @@ public class UserService { if(oldDbData != null) { if(!oldDbData.getPhone().equals(user.getPhone())){ user.setId(oldDbData.getId()); + } + if(user.getSubscribeMsg() != null && !user.getSubscribeMsg().equals(oldDbData.getSubscribeMsg())){ + user.setId(oldDbData.getId()); + } + if(user.getId() != null) { userDao.updateByPrimaryKeySelective(user); } }else { @@ -36,7 +41,7 @@ public class UserService { User user = userDao.findByOpenIdAndUserType(openId, userType); OaCusVo cusInfo = null; try { - if(user.getCusNo() != null) { + if(user != null && user.getCusNo() != null) { cusInfo = oaCusService.getCusInfo(user.getCusNo()); } }catch (Exception e) { @@ -53,6 +58,16 @@ public class UserService { return userVo; } + public UserVo getByCusNo(String cusNo) { + User user = userDao.findByCusNo(cusNo); + if(user == null) { + return null; + } + UserVo userVo = new UserVo(); + BeanUtils.copyProperties(user,userVo); + return userVo; + } + public void updateAuthInfo(String openId,String userType,String verifyCode) throws Exception { //调用oa接口客商信息 User user = userDao.findByOpenIdAndUserType(openId, userType); diff --git a/src/main/java/org/chenyon/user/UserVo.java b/src/main/java/org/chenyon/user/UserVo.java index 27ad496..bce7805 100644 --- a/src/main/java/org/chenyon/user/UserVo.java +++ b/src/main/java/org/chenyon/user/UserVo.java @@ -10,6 +10,7 @@ public class UserVo implements Serializable { private Boolean oaAuth; private String userType = "0"; private String userName; + private Boolean subscribeMsg; public String getOpenId() { return openId; @@ -58,4 +59,12 @@ public class UserVo implements Serializable { public void setUserName(String userName) { this.userName = userName; } + + public Boolean getSubscribeMsg() { + return subscribeMsg; + } + + public void setSubscribeMsg(Boolean subscribeMsg) { + this.subscribeMsg = subscribeMsg; + } } diff --git a/src/main/java/org/chenyon/vr/VrDataController.java b/src/main/java/org/chenyon/vr/VrDataController.java new file mode 100644 index 0000000..fd56d83 --- /dev/null +++ b/src/main/java/org/chenyon/vr/VrDataController.java @@ -0,0 +1,29 @@ +package org.chenyon.vr; + +import org.rcy.framework.api.entity.ResultMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/vr") +public class VrDataController { + + private static final Logger log = LoggerFactory.getLogger(VrDataController.class); + + @Autowired + private VrDataService vrDataService; + + @GetMapping("/data") + public ResultMessage getVrData(String id) { + try { + return ResultMessage.success(vrDataService.getVrData(id)); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return ResultMessage.success(new VrDataVo()); + } +} diff --git a/src/main/java/org/chenyon/vr/VrDataService.java b/src/main/java/org/chenyon/vr/VrDataService.java new file mode 100644 index 0000000..8ae57e8 --- /dev/null +++ b/src/main/java/org/chenyon/vr/VrDataService.java @@ -0,0 +1,45 @@ +package org.chenyon.vr; + +import org.chenyon.assets.AssetsQueryService; +import org.chenyon.assets.vo.AssetsVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class VrDataService { + + @Value("${cdn.domain}") + private String cdnDomain; + @Autowired + private AssetsQueryService assetsQueryService; + + public VrDataVo getVrData(String id) throws Exception { + AssetsVo assets = assetsQueryService.getAssetsById(id); + if(assets == null || assets.getVrImgs() == null) { + return null; + } + List vrImgs = assets.getVrImgs(); + VrDataVo dataVo = new VrDataVo(); + dataVo.setName(assets.getAssetsName()); + dataVo.setStartInde(0); + dataVo.setSpaces(buildVrSpace(vrImgs)); + return dataVo; + } + + private List buildVrSpace(List vrImgs) { + List vrSpaces = new ArrayList<>(); + for (int i = 0; i < vrImgs.size(); i++) { + VrSpace vrSpace = new VrSpace(); + vrSpace.setId(String.valueOf(i)); + vrSpace.setName("资产全景"+i); + vrSpace.setType("image"); + vrSpace.setSrc(cdnDomain + vrImgs.get(i)); + vrSpaces.add(vrSpace); + } + return vrSpaces; + } +} diff --git a/src/main/java/org/chenyon/vr/VrDataVo.java b/src/main/java/org/chenyon/vr/VrDataVo.java new file mode 100644 index 0000000..7bb7bf8 --- /dev/null +++ b/src/main/java/org/chenyon/vr/VrDataVo.java @@ -0,0 +1,33 @@ +package org.chenyon.vr; + +import java.util.List; + +public class VrDataVo { + private String name; + private Integer startInde; // 初始显示空间索引 + private List spaces; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getStartInde() { + return startInde; + } + + public void setStartInde(Integer startInde) { + this.startInde = startInde; + } + + public List getSpaces() { + return spaces; + } + + public void setSpaces(List spaces) { + this.spaces = spaces; + } +} diff --git a/src/main/java/org/chenyon/vr/VrSpace.java b/src/main/java/org/chenyon/vr/VrSpace.java new file mode 100644 index 0000000..c036f1f --- /dev/null +++ b/src/main/java/org/chenyon/vr/VrSpace.java @@ -0,0 +1,61 @@ +package org.chenyon.vr; + +import java.util.List; + +public class VrSpace { + + private String id; + private String name; + private String type; // 类型:image | video | model | cubemap + private String src; + private Integer modelScale; //模型缩放 + private List hotspots; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getSrc() { + return src; + } + + public void setSrc(String src) { + this.src = src; + } + + public Integer getModelScale() { + return modelScale; + } + + public void setModelScale(Integer modelScale) { + this.modelScale = modelScale; + } + + public List getHotspots() { + return hotspots; + } + + public void setHotspots(List hotspots) { + this.hotspots = hotspots; + } +} diff --git a/src/main/java/org/chenyon/vr/Vrhotspot.java b/src/main/java/org/chenyon/vr/Vrhotspot.java new file mode 100644 index 0000000..e70fd2e --- /dev/null +++ b/src/main/java/org/chenyon/vr/Vrhotspot.java @@ -0,0 +1,40 @@ +package org.chenyon.vr; + +public class Vrhotspot { + private String lon; // 经度 + private String lat; // 纬度 + private String targetId; // 点击后跳转到的空间 id + private String label; + + public String getLon() { + return lon; + } + + public void setLon(String lon) { + this.lon = lon; + } + + public String getLat() { + return lat; + } + + public void setLat(String lat) { + this.lat = lat; + } + + public String getTargetId() { + return targetId; + } + + public void setTargetId(String targetId) { + this.targetId = targetId; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } +} diff --git a/src/test/java/org/chenyon/pay/TmPayTokenServiceTest.java b/src/test/java/org/chenyon/pay/TmPayTokenServiceTest.java new file mode 100644 index 0000000..090d6ee --- /dev/null +++ b/src/test/java/org/chenyon/pay/TmPayTokenServiceTest.java @@ -0,0 +1,27 @@ +package org.chenyon.pay; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.io.IOException; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +public class TmPayTokenServiceTest { + + @Autowired + private TmTokenService tmTokenService; + + @Test + public void testGetToken() throws IOException { + String token = tmTokenService.getToken(); + System.out.println(token); + } + + public void testCreateOrder() { + + } +}