From d4f159d60acf6f263bfa4508a113c0feacd2f5b9 Mon Sep 17 00:00:00 2001 From: mitao <2763622819@qq.com> Date: 星期三, 19 六月 2024 18:30:02 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/ToolUtil.java | 718 +++++++ ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml | 17 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/PaylogServiceImpl.java | 126 + ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/JwtProperties.java | 71 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/PageKit.java | 52 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HexKit.java | 259 ++ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafKit.java | 114 + ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/IMemberService.java | 2 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/StrKit.java | 1374 ++++++++++++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java | 21 ruoyi-modules/ruoyi-order/pom.xml | 18 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTimeKit.java | 709 +++++++ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/restTemplate/RestTemplateConfig.java | 15 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTime.java | 70 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/MD5AndKL.java | 116 + ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/ObjectKit.java | 21 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HttpKit.java | 196 ++ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/LogisticsServiceImpl.java | 55 ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/forepart/ForepartMemberController.java | 6 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/RestProperties.java | 57 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartOrderController.java | 7 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/GoodsGroupPurchaseInfoVO.java | 4 ruoyi-modules/ruoyi-order/src/main/resources/conf/param.properties | 8 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java | 5 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/BasicType.java | 38 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java | 125 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/PayProperties.java | 74 /dev/null | 287 --- ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/CollectionKit.java | 833 ++++++++ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartLogisticsController.java | 7 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/ILogisticsService.java | 2 ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/MemberServiceImpl.java | 14 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafRequestWrapper.java | 149 + ruoyi-api/ruoyi-api-system/pom.xml | 2 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/vo/KuaiDiCode.java | 14 35 files changed, 5,190 insertions(+), 396 deletions(-) diff --git a/ruoyi-api/ruoyi-api-system/pom.xml b/ruoyi-api/ruoyi-api-system/pom.xml index dba587c..0f6f7ba 100644 --- a/ruoyi-api/ruoyi-api-system/pom.xml +++ b/ruoyi-api/ruoyi-api-system/pom.xml @@ -39,6 +39,8 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> + + </dependencies> </project> \ No newline at end of file diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/GoodsGroupPurchaseInfoVO.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/GoodsGroupPurchaseInfoVO.java index b559987..e0ba88d 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/GoodsGroupPurchaseInfoVO.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/GoodsGroupPurchaseInfoVO.java @@ -91,4 +91,8 @@ @ApiModelProperty(value = "團購商品訂單") @JsonInclude(JsonInclude.Include.ALWAYS) private Order order; + + @ApiModelProperty(value = "是收藏 1未收藏,2收藏") + @JsonInclude(JsonInclude.Include.ALWAYS) + private Integer isCollection; } diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java index 38dc737..4f10ab6 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java @@ -21,9 +21,11 @@ import com.ruoyi.goods.controller.management.dto.GoodsGroupPurchaseDTO; import com.ruoyi.goods.controller.management.dto.GoodsGroupPurchaseQuery; import com.ruoyi.goods.controller.management.vo.GoodsGroupPurchaseVO; +import com.ruoyi.goods.domain.MemberGoodsCollection; import com.ruoyi.goods.mapper.GoodsGroupPurchaseMapper; import com.ruoyi.goods.service.IGoodsGroupPurchaseService; import com.ruoyi.goods.service.IGoodsSkuService; +import com.ruoyi.goods.service.IMemberGoodsCollectionService; import com.ruoyi.goods.service.async.AsyncMethodService; import com.ruoyi.system.api.constants.DelayTaskEnum; import com.ruoyi.system.api.constants.NotificationTypeConstant; @@ -68,6 +70,9 @@ private final IGoodsSkuService goodsSkuService; private final AsyncMethodService asyncMethodService; private final RedisService redisService; + + @Resource + private IMemberGoodsCollectionService iMemberGoodsCollectionService; // 创建一个静态共享的ObjectMapper实例以重用 private static final ObjectMapper objectMapper = new ObjectMapper(); /** @@ -319,7 +324,21 @@ goodsGroupPurchaseInfoVO.setListingStatus(one.getListingStatus()); goodsGroupPurchaseInfoVO.setGroupStatus(one.getGroupStatus()); - Order data = orderClient.getOrderByGroupPurchaseMemberId(homeGoodsSkuDTO, SecurityConstants.INNER).getData(); + LambdaQueryWrapper<MemberGoodsCollection> wrapper4= Wrappers.lambdaQuery(); + wrapper4.eq(MemberGoodsCollection::getDelFlag,0); + wrapper4.eq(MemberGoodsCollection::getMemberId,homeGoodsSkuDTO.getMemberId()); + wrapper4.eq(MemberGoodsCollection::getTargetId,one.getId()); + wrapper4.eq(MemberGoodsCollection::getType,1); + List<MemberGoodsCollection> list = iMemberGoodsCollectionService.list(wrapper4); + if (list.size()>0){ + goodsGroupPurchaseInfoVO.setIsCollection(2); + }else{ + goodsGroupPurchaseInfoVO.setIsCollection(1); + } + HomeGoodsSkuDTO homeGoodsSkuDTO1=new HomeGoodsSkuDTO(); + homeGoodsSkuDTO1.setGoodsSkuId(one.getId()); + homeGoodsSkuDTO1.setMemberId(homeGoodsSkuDTO.getMemberId()); + Order data = orderClient.getOrderByGroupPurchaseMemberId(homeGoodsSkuDTO1, SecurityConstants.INNER).getData(); if (data!=null){ goodsGroupPurchaseInfoVO.setIsGoodsGroupPurchase(2); goodsGroupPurchaseInfoVO.setOrder(data); diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java index 6f15c87..938eca7 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java @@ -33,6 +33,7 @@ import com.ruoyi.system.api.domain.dto.ListStatusDTO; import com.ruoyi.system.api.domain.vo.HomeGoodsSkuInfoVO; import com.ruoyi.system.api.domain.vo.HomeGoodsSkuListVO; +import com.ruoyi.system.api.domain.vo.OrderVO; import com.ruoyi.system.api.domain.vo.getHomeGoodsSkuXxiVO; import com.ruoyi.system.api.feignClient.GoodsSkuClient; @@ -426,8 +427,8 @@ HomeGoodsSkuDTO homeGoodsSkuDTO1 =new HomeGoodsSkuDTO(); homeGoodsSkuDTO1.setGoodsSkuId(goodsGroupPurchase.getId()); homeGoodsSkuDTO1.setMemberId(homeGoodsSkuDTO.getMemberId()); - Order data5 = orderClient.getOrderByGroupPurchaseMemberId(homeGoodsSkuDTO1, SecurityConstants.INNER).getData(); - if (data5!=null){ + List<OrderVO> data4 = orderClient.getOrderByGroupPurchaseMemberList(homeGoodsSkuDTO1, SecurityConstants.INNER).getData(); + if (data4!=null){ homeGoodsSkuInfoVO.setIsGoodsGroupPurchase(2); }else{ homeGoodsSkuInfoVO.setIsGoodsGroupPurchase(1); diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/forepart/ForepartMemberController.java b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/forepart/ForepartMemberController.java index 820a605..8801954 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/forepart/ForepartMemberController.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/controller/forepart/ForepartMemberController.java @@ -54,9 +54,9 @@ @PostMapping(value = "/mobile") @ApiOperation(value = "用户端-小程序获取电话号码") - public R mobile(@RequestBody MobileDTO mobileDTO) { - iMemberService.mobile(mobileDTO); - return R.ok(); + public R<String> mobile(@RequestBody MobileDTO mobileDTO) { + + return R.ok(iMemberService.mobile(mobileDTO)); } @PostMapping("/getMembeid") diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/IMemberService.java b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/IMemberService.java index 3536ffc..8b074fb 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/IMemberService.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/IMemberService.java @@ -37,7 +37,7 @@ List<Member> getMemberListByIds(Collection<Long> memberIdList); - void mobile(@RequestBody MobileDTO mobileDTO); + String mobile(@RequestBody MobileDTO mobileDTO); /** * 获取会员管理分页列表 diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/MemberServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/MemberServiceImpl.java index 69e1e96..55a5eb0 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/MemberServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/service/impl/MemberServiceImpl.java @@ -186,6 +186,7 @@ sysUser = new SysUser(); sysUser.setUserName(memberId); sysUser.setNickName("白金用户"); + sysUser.setUserType("03"); sysUser.setPhonenumber(response.getOpenId()); sysUser.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); String password = "123456"; @@ -243,6 +244,7 @@ sysUser = new SysUser(); sysUser.setUserName(memberId); sysUser.setNickName("白金用户"); + sysUser.setUserType("03"); sysUser.setAvatar("https://hongruitang.oss-cn-beijing.aliyuncs.com/default.png"); String password = "123456"; sysUser.setPassword(SecurityUtils.encryptPassword(password)); @@ -390,8 +392,9 @@ } @Override - public void mobile(MobileDTO mobileDTO) { + public String mobile(MobileDTO mobileDTO) { Member byId = this.getById(mobileDTO.getMemberid()); + String mobile=null; if (mobileDTO.getType()==1) { if (mobileDTO.getAuth_code() == null || mobileDTO.getAuth_code().length() == 0) { } else { @@ -442,8 +445,7 @@ new TypeReference<Map<String, String>>() { }, Feature.OrderedField); - byId.setPhone(openapiResult1.get("mobile")); - this.updateById(byId); + mobile=openapiResult1.get("mobile"); } }else{ String responseAccessToken = null; @@ -469,10 +471,10 @@ JSONObject jsonUserPhoneNumber = JSONObject.parseObject(responseUserPhoneNumber); String phoneInfo = jsonUserPhoneNumber.getString("phone_info"); JSONObject jsonUserPhoneInfo = JSONObject.parseObject(phoneInfo); - String mobile = jsonUserPhoneInfo.getString("purePhoneNumber"); - byId.setPhone(mobile); - this.updateById(byId); + mobile= jsonUserPhoneInfo.getString("purePhoneNumber"); + } + return mobile; } public static String getAccessTokenByWX() throws Exception { diff --git a/ruoyi-modules/ruoyi-order/pom.xml b/ruoyi-modules/ruoyi-order/pom.xml index 2e3b1ea..ced6648 100644 --- a/ruoyi-modules/ruoyi-order/pom.xml +++ b/ruoyi-modules/ruoyi-order/pom.xml @@ -129,7 +129,19 @@ <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> - <version>4.39.95.ALL</version> + <version>4.10.167.ALL</version> + </dependency> + + <dependency> + <groupId>com.github.wechatpay-apiv3</groupId> + <artifactId>wechatpay-java</artifactId> + <version>0.2.12</version> + </dependency> + + <dependency> + <groupId>com.github.javen205</groupId> + <artifactId>IJPay</artifactId> + <version>1.1.9</version> </dependency> <dependency> @@ -149,8 +161,12 @@ <groupId>com.ruoyi</groupId> <artifactId>ruoyi-common-seata</artifactId> </dependency> + + </dependencies> + + <build> <finalName>${project.artifactId}</finalName> <plugins> diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartLogisticsController.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartLogisticsController.java index 0f5afb0..78eafc5 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartLogisticsController.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartLogisticsController.java @@ -56,4 +56,11 @@ wrapper.eq(Logistics::getLogisticsNum,logisticsDTO.getCompany()); return R.ok( iLogisticsService.getOne(wrapper)); } + + @PostMapping("/isLogisticsOne") + @ApiOperation(value = "用户端-获取快递是否正确") + public R<Boolean> isLogisticsOne(@RequestBody LogisticsDTO logisticsDTO) { + + return R.ok( iLogisticsService.isLogisticsOne(logisticsDTO)); + } } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartOrderController.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartOrderController.java index 4533763..2eade8a 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartOrderController.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/forepart/ForepartOrderController.java @@ -66,6 +66,13 @@ return R.ok(); } + @PostMapping("/delOrderOne") + @ApiOperation(value = "用户端-删除订单") + public R delOrderOne(@RequestBody MemberOrderListDTO memberOrderListDTO) { + orderService.removeById(memberOrderListDTO.getId()); + return R.ok(); + } + @PostMapping("/AffirmOrderOne") @ApiOperation(value = "用户端-确认收货订单") public R AffirmOrderOne(@RequestBody MemberOrderListDTO memberOrderListDTO) { diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/restTemplate/RestTemplateConfig.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/restTemplate/RestTemplateConfig.java new file mode 100644 index 0000000..8b43a58 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/restTemplate/RestTemplateConfig.java @@ -0,0 +1,15 @@ +package com.ruoyi.order.restTemplate; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder){ + return builder.build(); + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/ILogisticsService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/ILogisticsService.java index 1c0f3b4..cb5f649 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/ILogisticsService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/ILogisticsService.java @@ -18,4 +18,6 @@ Express100VO getLogisticsList(@RequestBody LogisticsDTO logisticsDTO); + Boolean isLogisticsOne(@RequestBody LogisticsDTO logisticsDTO); + } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/LogisticsServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/LogisticsServiceImpl.java index a681596..c789080 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/LogisticsServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/LogisticsServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.order.service.impl; +import com.alibaba.fastjson.JSON; import com.alibaba.nacos.shaded.com.google.gson.Gson; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -13,12 +14,27 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.order.mapper.LogisticsMapper; import com.ruoyi.order.service.ILogisticsService; +import com.ruoyi.order.vo.KuaiDiCode; import com.ruoyi.system.api.domain.Logistics; import com.ruoyi.system.api.domain.dto.LogisticsDTO; import com.ruoyi.system.api.domain.vo.Express100VO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; /** * <p> @@ -35,7 +51,10 @@ private String key="BltjQodT7186"; private String customer="56DE8E9E3D58CE73C60755C8B7483043"; + private static final String AUTONUMBER_AUTO_URL = "http://www.kuaidi100.com/autonumber/auto?num=NUM&key=KEY"; + @Autowired + private RestTemplate restTemplate; @Override @@ -67,4 +86,40 @@ response.setLogisticsName(one.getLogisticsName()); return response; } + + @Override + public Boolean isLogisticsOne(LogisticsDTO logisticsDTO) { + List<KuaiDiCode> m=findKuaiDiCode(logisticsDTO.getPostid()); + Boolean b=false; + if (m.size()>0){ + for (KuaiDiCode k:m){ + if (k.getComCode().equals(logisticsDTO.getCompany())){ + b=true; + } + } + + } + + return b; + } + + public List<KuaiDiCode> findKuaiDiCode(String orderId) { + String url = AUTONUMBER_AUTO_URL.replace("NUM", orderId).replace("KEY", key); + // 发送快递参数处理 + MultiValueMap<String, Object> sendBody = new LinkedMultiValueMap<>(); + sendBody.add("num", orderId); + sendBody.add("key", key); + //设置请求头参数 + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded"); + HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(sendBody, headers); + ResponseEntity<String> result = restTemplate.postForEntity(url, formEntity, String.class); + List<KuaiDiCode> kuaiDiCode = new ArrayList<>(); + if (result.getBody() != null && result.getBody().length() > 0) { + ArrayList body = JSON.parseObject(result.getBody(), ArrayList.class); + body.forEach(i -> kuaiDiCode.add(JSON.parseObject(JSON.toJSONString(i), KuaiDiCode.class))); + } + return kuaiDiCode; + } + } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java index bd78592..5d0f6ee 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java @@ -349,6 +349,7 @@ order.setCoverPic(goodsSku.getCoverPic()); order.setSjPrice(goodsSku.getPrice()); } + order.setOrderRemark(memberOrderDTO.getOrderRemark()); order.setMemberId(memberOrderDTO.getMemberId()); order.setGoodsQuantity(memberOrderDTO.getGoodsQuantity()); order.setOrderTime(LocalDateTime.now()); @@ -406,6 +407,9 @@ @Override public MemberTiOrderVO updMemberOrder(MemberOrderDTO memberOrderDTO) { Order order = baseMapper.selectById(memberOrderDTO.getId()); + if(memberOrderDTO.getOrderRemark()!=null){ + order.setOrderRemark(memberOrderDTO.getOrderRemark()); + } MemberTiOrderVO memberOrderVO=new MemberTiOrderVO(); if (memberOrderDTO.getReceiverDetailAddress()!=null){ @@ -515,70 +519,73 @@ } } - BigDecimal pice=order.getPrice().multiply(new BigDecimal(memberOrderDTO.getGoodsQuantity())); - if (memberOrderDTO.getCouponId()!=null){ - CouponMemberDTO couponMemberDTO=new CouponMemberDTO(); - couponMemberDTO.setId(memberOrderDTO.getCouponId()); - CouponMember data = promotionClient.getCouponMember(couponMemberDTO, SecurityConstants.INNER).getData(); - if (order.getCouponId()!=0){ - CouponMemberDTO couponMemberDTO1=new CouponMemberDTO(); - couponMemberDTO1.setId(memberOrderDTO.getCouponId()); - couponMemberDTO1.setCouponStatus(0); - promotionClient.updCouponMember(couponMemberDTO1, SecurityConstants.INNER); - } - - order.setCouponId(data.getId()); - - if (data.getCouponType().getCode()==1){ - if (pice.doubleValue()>=data.getFullReductionAmount().doubleValue()){ - pice=pice.subtract(data.getReductionAmount()); - order.setDiscountMoney(data.getReductionAmount()); + if (memberOrderDTO.getGoodsQuantity()!=null){ + BigDecimal pice=order.getPrice().multiply(new BigDecimal(memberOrderDTO.getGoodsQuantity())); + if (memberOrderDTO.getCouponId()!=null){ + CouponMemberDTO couponMemberDTO=new CouponMemberDTO(); + couponMemberDTO.setId(memberOrderDTO.getCouponId()); + CouponMember data = promotionClient.getCouponMember(couponMemberDTO, SecurityConstants.INNER).getData(); + if (order.getCouponId()!=0){ + CouponMemberDTO couponMemberDTO1=new CouponMemberDTO(); + couponMemberDTO1.setId(memberOrderDTO.getCouponId()); + couponMemberDTO1.setCouponStatus(0); + promotionClient.updCouponMember(couponMemberDTO1, SecurityConstants.INNER); } - } - if (data.getCouponType().getCode()==2){ - pice= order.getTotalAmount(); - pice=pice.subtract(data.getVoucherAmount()); - order.setDiscountMoney(data.getVoucherAmount()); - } - if (data.getCouponType().getCode()==3){ - pice= order.getTotalAmount(); - BigDecimal pice1=new BigDecimal(data.getDiscountRate()); - BigDecimal pice2=new BigDecimal(0.1); - BigDecimal pice3=pice.multiply(pice1.multiply(pice2)); - BigDecimal pice4= pice.subtract(pice3); - if (pice4.doubleValue()>data.getMaxDiscount().doubleValue()){ - pice=pice.subtract(data.getMaxDiscount()); - order.setDiscountMoney(data.getMaxDiscount()); - }else{ - order.setDiscountMoney(pice4); - pice=pice3; - } + order.setCouponId(data.getId()); + + if (data.getCouponType().getCode()==1){ + if (pice.doubleValue()>=data.getFullReductionAmount().doubleValue()){ + pice=pice.subtract(data.getReductionAmount()); + order.setDiscountMoney(data.getReductionAmount()); + } + } + if (data.getCouponType().getCode()==2){ + pice= order.getTotalAmount(); + pice=pice.subtract(data.getVoucherAmount()); + order.setDiscountMoney(data.getVoucherAmount()); + } + if (data.getCouponType().getCode()==3){ + pice= order.getTotalAmount(); + BigDecimal pice1=new BigDecimal(data.getDiscountRate()); + BigDecimal pice2=new BigDecimal(0.1); + BigDecimal pice3=pice.multiply(pice1.multiply(pice2)); + BigDecimal pice4= pice.subtract(pice3); + if (pice4.doubleValue()>data.getMaxDiscount().doubleValue()){ + pice=pice.subtract(data.getMaxDiscount()); + order.setDiscountMoney(data.getMaxDiscount()); + }else{ + order.setDiscountMoney(pice4); + pice=pice3; + } + + } + order.setCouponId(memberOrderDTO.getCouponId()); + CouponMemberDTO couponMemberDTO2=new CouponMemberDTO(); + couponMemberDTO2.setId(memberOrderDTO.getCouponId()); + couponMemberDTO2.setCouponStatus(1); + promotionClient.updCouponMember(couponMemberDTO2, SecurityConstants.INNER); + }else{ + if (order.getCouponId()!=null&&order.getCouponId()!=0){ + CouponMemberDTO couponMemberDTO1=new CouponMemberDTO(); + couponMemberDTO1.setCouponStatus(0); + couponMemberDTO1.setId(order.getCouponId()); + promotionClient.updCouponMember(couponMemberDTO1, SecurityConstants.INNER); + } + order.setCouponId(0L); + order.setDiscountMoney(new BigDecimal(0)); } - order.setCouponId(memberOrderDTO.getCouponId()); - CouponMemberDTO couponMemberDTO2=new CouponMemberDTO(); - couponMemberDTO2.setId(memberOrderDTO.getCouponId()); - couponMemberDTO2.setCouponStatus(1); - promotionClient.updCouponMember(couponMemberDTO2, SecurityConstants.INNER); - }else{ - if (order.getCouponId()!=null&&order.getCouponId()!=0){ - CouponMemberDTO couponMemberDTO1=new CouponMemberDTO(); - couponMemberDTO1.setCouponStatus(0); - couponMemberDTO1.setId(order.getCouponId()); - promotionClient.updCouponMember(couponMemberDTO1, SecurityConstants.INNER); - } - order.setCouponId(0L); - order.setDiscountMoney(new BigDecimal(0)); + order.setTotalAmount(pice); + + CustomConfig memberPointsMoney = sysUserClient.getconfig("MEMBER_POINTS_MONEY").getData(); + CustomConfig memberPointsPoints = sysUserClient.getconfig("MEMBER_POINTS_POINTS").getData(); + + Double aDouble= Double.valueOf(memberPointsMoney.getConfigValue()) * Double.valueOf(memberPointsPoints.getConfigValue()); + BigDecimal pi=pice.multiply(new BigDecimal(aDouble)); + order.setPoints(pi.intValue()); + baseMapper.updateById(order); } - order.setTotalAmount(pice); - CustomConfig memberPointsMoney = sysUserClient.getconfig("MEMBER_POINTS_MONEY").getData(); - CustomConfig memberPointsPoints = sysUserClient.getconfig("MEMBER_POINTS_POINTS").getData(); - - Double aDouble= Double.valueOf(memberPointsMoney.getConfigValue()) * Double.valueOf(memberPointsPoints.getConfigValue()); - BigDecimal pi=pice.multiply(new BigDecimal(aDouble)); - order.setPoints(pi.intValue()); - baseMapper.updateById(order); memberOrderVO.setId(order.getId()); memberOrderVO.setOrderStatus(OrderStatusEnum.TO_PLAY); diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/PaylogServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/PaylogServiceImpl.java index 55000ae..e6be77b 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/PaylogServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/PaylogServiceImpl.java @@ -9,8 +9,9 @@ import com.alipay.api.response.AlipayTradeRefundResponse; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jpay.ext.kit.PaymentKit; +import com.jpay.weixin.api.WxPayApi; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.enums.OrderStatusEnum; @@ -19,8 +20,8 @@ import com.ruoyi.order.domain.Paylog; import com.ruoyi.order.mapper.OrderMapper; import com.ruoyi.order.mapper.PaylogMapper; -import com.ruoyi.order.service.IOrderService; import com.ruoyi.order.service.IPaylogService; +import com.ruoyi.order.util.MD5AndKL; import com.ruoyi.order.util.SinataUtil; import com.ruoyi.order.util.alipay.config.AlipayConfig; import com.ruoyi.order.util.alipay.util.PayDemoActivity; @@ -36,19 +37,12 @@ import com.ruoyi.system.api.domain.dto.updMembeOneDTO; import com.ruoyi.system.api.feignClient.AuctionClient; import com.ruoyi.system.api.feignClient.MemberClient; -import com.ruoyi.system.api.feignClient.OrderClient; + import java.io.IOException; import java.io.PrintWriter; import java.math.BigDecimal; -import java.security.SignatureException; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -57,6 +51,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Service; +import org.springframework.util.Assert; /** * <p> @@ -86,7 +81,11 @@ String body; try { if(judgeContainsStr(orderNO)){ - price= Double.valueOf(1); + LambdaQueryWrapper<Order> wrapper1= Wrappers.lambdaQuery(); + wrapper1.eq(Order::getOrderNo,orderNO); + wrapper1.eq(Order::getDelFlag,0); + Order page1 = OrderMapper.selectOne(wrapper1); + price=page1.getTotalAmount().doubleValue(); body = " 订单支付"; subject = " 订单支付"; Map<String, Object> map = new HashMap<String, Object>(); @@ -389,7 +388,7 @@ public static R<Map<String, Object>> wxpay(Integer apptype, String outTradeNo, String body,String openId, Double price, HttpServletRequest request) { // 获取预支付接口返回参数 - Map<String, Object> map = new HashMap<String, Object>(); + Map<String, Object> map1 = new HashMap<String, Object>(); Map<String, Object> appPayMap = new HashMap<String, Object>(); try { // 构建接口请求参数 @@ -400,26 +399,73 @@ System.out.println(result); System.out.println("WxpayController.createOrder__result:\n" + result); // 获取预支付接口返回参数 - map = XMLParser.getMapFromXML(result); + map1 = XMLParser.getMapFromXML(result); System.out.println("WxpayController.createOrder__result:\n" + result); // 捕获预支付接口错误提示 - if ("FAIL".equals(map.get("result_code")) || "FAIL".equals(map.get("return_code"))) { - return R.fail(String.valueOf(map.get("return_msg"))); + if ("FAIL".equals(map1.get("result_code")) || "FAIL".equals(map1.get("return_code"))) { + return R.fail(String.valueOf(map1.get("return_msg"))); } - // 对获取预支付返回接口参数进行封装(生成支付订单接口数据) + /* // 对获取预支付返回接口参数进行封装(生成支付订单接口数据) AppPayReqData appPay = new AppPayReqData(apptype, (String) map.get("appid"), (String) map.get("mch_id"), - (String) map.get("prepay_id"), unifiedorderReqData.getNonce_str()); + (String) map.get("prepay_id"), unifiedorderReqData.getNonce_str());*/ - HashMap<String, Object> map1 = new HashMap<>(); - map1.put("timeStamp", appPay.getTimestamp()); - map1.put("nonceStr", appPay.getNoncestr()); - map1.put("package", "prepay_id=" + appPay.getPrepayid()); - map1.put("signType", "RSA"); - map1.put("paySign", appPay.getSign()); + UUID uuid = UUID.randomUUID(); + String nonceStr = uuid.toString().replaceAll("-", ""); + //商品描述 String body = "XX商城-支付订单"; + // 创建hashmap(用户获得签名) + SortedMap<String, String> paraMap = new TreeMap<>(); + //设置请求参数(小程序ID) + paraMap.put("appid", unifiedorderReqData.getAppid()); + //设置请求参数(商户号) + paraMap.put("mch_id", unifiedorderReqData.getMch_id()); + //设置请求参数(随机字符串) + paraMap.put("nonce_str", nonceStr); + //设置请求参数(商品描述) + paraMap.put("body", unifiedorderReqData.getBody()); + //设置请求参数(商户订单号) + paraMap.put("out_trade_no", unifiedorderReqData.getOut_trade_no()); + //设置请求参数(总金额) + paraMap.put("total_fee", unifiedorderReqData.getTotal_fee().toString()); + //设置请求参数(通知地址) + paraMap.put("notify_url", unifiedorderReqData.getNotify_url()); + //设置请求参数(交易类型) + paraMap.put("trade_type", String.valueOf(WxPayApi.TradeType.JSAPI)); + paraMap.put("openid", unifiedorderReqData.getOpenid()); + + //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid) + //MD5运算生成签名,这里是第一次签名,用于调用统一下单接口 + String sign = PaymentKit.createSign(paraMap, "E10ADC3949BA59ABBE56E057F20F883E"); + paraMap.put("sign", sign); + //统一下单,向微信api发送数据 + //转成xml + String xmlResult = WxPayApi.pushOrder(false, paraMap); + Map<String, String> map = PaymentKit.xmlToMap(xmlResult); + //返回状态码 + String returnCode = map.get("return_code"); + /* Assert.isTrue("SUCCESS".equals(returnCode), getMsgByCode(returnCode));*/ + + //返回给小程序端需要的参数 + Map<String, Object> returnMap = new HashMap<>(20); + + String prepay_id = map.get("prepay_id"); + //重新进行签名后返回给前端 + returnMap.put("appId", map.get("appid")); + returnMap.put("nonceStr", map.get("nonce_str")); + returnMap.put("package", "prepay_id=" + prepay_id); + returnMap.put("timeStamp", new Date().getTime() + ""); + returnMap.put("signType", "MD5"); + String signature = weixinSignature(returnMap, "E10ADC3949BA59ABBE56E057F20F883E"); + + returnMap.put("prepay_id", prepay_id); + returnMap.put("mch_id", map.get("mch_id")); + returnMap.put("trade_type", map.get("trade_type")); + + returnMap.put("sign", signature); + returnMap.put("err_code_des", map.get("err_code_des")); // 对获取预支付返回接口参数进行封装(生成支付订单接口数据) - return R.ok(map1); + return R.ok(returnMap); } catch (Exception e) { System.out.println("统一下单_API_处理异常!"); e.printStackTrace(); @@ -427,6 +473,36 @@ return R.fail("统一下单失败"); } + private static String weixinSignature(Map<String, Object> map, String privateKey) { + try { + Set<Map.Entry<String, Object>> entries = map.entrySet(); + List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries); + // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) + Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() { + public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) { + return (o1.getKey()).toString().compareTo(o2.getKey()); + } + }); + // 构造签名键值对的格式 + StringBuilder sb = new StringBuilder(); + for (Map.Entry<String, Object> item : infoIds) { + if (item.getKey() != null || item.getKey() != "") { + String key = item.getKey(); + Object val = item.getValue(); + if (!(val == "" || val == null)) { + sb.append(key + "=" + val + "&"); + } + } + } + sb.append("key=" + privateKey); + String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 + return sign; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + /** diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/MD5AndKL.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/MD5AndKL.java new file mode 100644 index 0000000..72cdae6 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/MD5AndKL.java @@ -0,0 +1,116 @@ +package com.ruoyi.order.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.MessageDigest; + +public class MD5AndKL { + + private static Logger logger = LoggerFactory.getLogger(MD5AndKL.class); + + /** + * MD5加码。32位 + * + * @param inStr + * @return + */ + public static String MD5(String inStr) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + byte[] md5Bytes = md5.digest(inStr.getBytes()); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++) { + int val = ((int) md5Bytes[i]) & 0xff; + if (val < 16) { + hexValue.append("0"); + } + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } + + /** + * 可逆的加密算法 + * + * @param inStr + * @return + */ + public static String KL(String inStr) { + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++) { + a[i] = (char) (a[i] ^ 't'); + } + String s = new String(a); + return s; + } + + /** + * 加密后解密 + * + * @param inStr + * @return + */ + public static String JM(String inStr) { + char[] a = inStr.toCharArray(); + for (int i = 0; i < a.length; i++) { + a[i] = (char) (a[i] ^ 't'); + } + String k = new String(a); + return k; + } + + + private static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) + resultSb.append(byteToHexString(b[i])); + + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n += 256; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + } else { + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + return resultString; + } + + private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; + + public static void main(String args[]) { + + logger.debug("MD5后再加密:" + KL(MD5("123456"))); + logger.debug(MD5("123456")); + // logger.debug("加密:" + KL(MD5("123456"))); + // s = KL(s); + // logger.debug("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055")); + // logger.debug("解密:" + JM(KL(s))); + // logger.debug("解密为MD5后的:" + KL(KL(MD5(s)))); + // logger.debug(JM("5d62957bb57d3e49dcf48a0df064be4c")); + // logger.debug(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321"))); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/ToolUtil.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/ToolUtil.java new file mode 100644 index 0000000..c5ad01c --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/ToolUtil.java @@ -0,0 +1,718 @@ +/** + * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com). + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruoyi.order.util; + +import com.google.gson.Gson; +import com.ruoyi.common.core.utils.DateUtils; +import com.ruoyi.order.util.support.StrKit; + + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.net.URISyntaxException; +import java.util.*; +import java.util.Map.Entry; + +/** + * 高频方法集合类 + */ +public class ToolUtil { + + /** + * 获取随机位数的字符串 + * + * @author fengshuonan + * @Date 2017/8/24 14:09 + */ + public static String getRandomString(int length) { + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } + + public static <T> T objFromJson(Object src, Class<T> classOfT) { + Gson gson = new Gson(); + return gson.fromJson(gson.toJson(src), classOfT); + } + + /** + * 获取随机位数数字串 + */ + public static String getRandomNumber(int length) { + String base = "0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } + + /** + * 判断一个对象是否是时间类型 + * + * @author stylefeng + * @Date 2017/4/18 12:55 + */ + /* public static String dateType(Object o) { + if (o instanceof Date) { + return DateUtils.getDay((Date) o); + } else { + return o.toString(); + } + }*/ + + /** + * 获取异常的具体信息 + * + * @author fengshuonan + * @Date 2017/3/30 9:21 + * @version 2.0 + */ + public static String getExceptionMsg(Exception e) { + StringWriter sw = new StringWriter(); + try { + e.printStackTrace(new PrintWriter(sw)); + } finally { + try { + sw.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + return sw.getBuffer().toString().replaceAll("\\$", "T"); + } + + /** + * 比较两个对象是否相等。<br> + * 相同的条件有两个,满足其一即可:<br> + * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2) + * + * @param obj1 对象1 + * @param obj2 对象2 + * @return 是否相等 + */ + public static boolean equals(Object obj1, Object obj2) { + return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null); + } + + /** + * 计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度 + * + * @param obj 被计算长度的对象 + * @return 长度 + */ + public static int length(Object obj) { + if (obj == null) { + return 0; + } + if (obj instanceof CharSequence) { + return ((CharSequence) obj).length(); + } + if (obj instanceof Collection) { + return ((Collection<?>) obj).size(); + } + if (obj instanceof Map) { + return ((Map<?, ?>) obj).size(); + } + + int count; + if (obj instanceof Iterator) { + Iterator<?> iter = (Iterator<?>) obj; + count = 0; + while (iter.hasNext()) { + count++; + iter.next(); + } + return count; + } + if (obj instanceof Enumeration) { + Enumeration<?> enumeration = (Enumeration<?>) obj; + count = 0; + while (enumeration.hasMoreElements()) { + count++; + enumeration.nextElement(); + } + return count; + } + if (obj.getClass().isArray() == true) { + return Array.getLength(obj); + } + return -1; + } + + /** + * 对象中是否包含元素 + * + * @param obj 对象 + * @param element 元素 + * @return 是否包含 + */ + public static boolean contains(Object obj, Object element) { + if (obj == null) { + return false; + } + if (obj instanceof String) { + if (element == null) { + return false; + } + return ((String) obj).contains(element.toString()); + } + if (obj instanceof Collection) { + return ((Collection<?>) obj).contains(element); + } + if (obj instanceof Map) { + return ((Map<?, ?>) obj).values().contains(element); + } + + if (obj instanceof Iterator) { + Iterator<?> iter = (Iterator<?>) obj; + while (iter.hasNext()) { + Object o = iter.next(); + if (equals(o, element)) { + return true; + } + } + return false; + } + if (obj instanceof Enumeration) { + Enumeration<?> enumeration = (Enumeration<?>) obj; + while (enumeration.hasMoreElements()) { + Object o = enumeration.nextElement(); + if (equals(o, element)) { + return true; + } + } + return false; + } + if (obj.getClass().isArray() == true) { + int len = Array.getLength(obj); + for (int i = 0; i < len; i++) { + Object o = Array.get(obj, i); + if (equals(o, element)) { + return true; + } + } + } + return false; + } + + /** + * 对象是否不为空(新增) + */ + public static boolean isNotEmpty(Object o) { + return !isEmpty(o); + } + + /** + * 对象是否为空 + */ + @SuppressWarnings("rawtypes") + public static boolean isEmpty(Object o) { + if (o == null) { + return true; + } + if (o instanceof String) { + if (o.toString().trim().equals("")) { + return true; + } + } else if (o instanceof List) { + if (((List) o).size() == 0) { + return true; + } + } else if (o instanceof Map) { + if (((Map) o).size() == 0) { + return true; + } + } else if (o instanceof Set) { + if (((Set) o).size() == 0) { + return true; + } + } else if (o instanceof Object[]) { + if (((Object[]) o).length == 0) { + return true; + } + } else if (o instanceof int[]) { + if (((int[]) o).length == 0) { + return true; + } + } else if (o instanceof long[]) { + if (((long[]) o).length == 0) { + return true; + } + } + return false; + } + + /** + * 对象组中是否存在 Empty Object + * + * @param os 对象组 + * @return + */ + public static boolean isOneEmpty(Object... os) { + for (Object o : os) { + if (isEmpty(o)) { + return true; + } + } + return false; + } + + /** + * 对象组中是否全是 Empty Object + * + * @param os + * @return + */ + public static boolean isAllEmpty(Object... os) { + for (Object o : os) { + if (!isEmpty(o)) { + return false; + } + } + return true; + } + + /** + * 是否为数字 + * + * @param obj + * @return + */ + public static boolean isNum(Object obj) { + try { + Integer.parseInt(obj.toString()); + } catch (Exception e) { + return false; + } + return true; + } + + /** + * 如果为空, 则调用默认值 + * + * @param str + * @return + */ + public static Object getValue(Object str, Object defaultValue) { + if (isEmpty(str)) { + return defaultValue; + } + return str; + } + + /** + * 格式化文本 + * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param values 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... values) { + return StrKit.format(template, values); + } + + /** + * 格式化文本 + * + * @param template 文本模板,被替换的部分用 {key} 表示 + * @param map 参数值对 + * @return 格式化后的文本 + */ + public static String format(String template, Map<?, ?> map) { + return StrKit.format(template, map); + } + + /** + * 强转->string,并去掉多余空格 + * + * @param str + * @return + */ + public static String toStr(Object str) { + return toStr(str, ""); + } + + /** + * 强转->string,并去掉多余空格 + * + * @param str + * @param defaultValue + * @return + */ + public static String toStr(Object str, String defaultValue) { + if (null == str) { + return defaultValue; + } + return str.toString().trim(); + } + + /** + * 强转->int + * + * @param obj + * @return + */ +// public static int toInt(Object value) { +// return toInt(value, -1); +// } + + /** + * 强转->int + * + * @param obj + * @param defaultValue + * @return + */ +// public static int toInt(Object value, int defaultValue) { +// return Convert.toInt(value, defaultValue); +// } + + /** + * 强转->long + * + * @param obj + * @return + */ +// public static long toLong(Object value) { +// return toLong(value, -1); +// } + + /** + * 强转->long + * + * @param obj + * @param defaultValue + * @return + */ +// public static long toLong(Object value, long defaultValue) { +// return Convert.toLong(value, defaultValue); +// } +// +// public static String encodeUrl(String url) { +// return URLKit.encode(url, CharsetKit.UTF_8); +// } +// +// public static String decodeUrl(String url) { +// return URLKit.decode(url, CharsetKit.UTF_8); +// } + + /** + * map的key转为小写 + * + * @param map + * @return Map<String, Object> + */ + public static Map<String, Object> caseInsensitiveMap(Map<String, Object> map) { + Map<String, Object> tempMap = new HashMap<>(); + for (String key : map.keySet()) { + tempMap.put(key.toLowerCase(), map.get(key)); + } + return tempMap; + } + + /** + * 获取map中第一个数据值 + * + * @param <K> Key的类型 + * @param <V> Value的类型 + * @param map 数据源 + * @return 返回的值 + */ + public static <K, V> V getFirstOrNull(Map<K, V> map) { + V obj = null; + for (Entry<K, V> entry : map.entrySet()) { + obj = entry.getValue(); + if (obj != null) { + break; + } + } + return obj; + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 + */ + public static StringBuilder builder(String... strs) { + final StringBuilder sb = new StringBuilder(); + for (String str : strs) { + sb.append(str); + } + return sb; + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 + */ + public static void builder(StringBuilder sb, String... strs) { + for (String str : strs) { + sb.append(str); + } + } + + /** + * 去掉指定后缀 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串 + */ + public static String removeSuffix(String str, String suffix) { + if (isEmpty(str) || isEmpty(suffix)) { + return str; + } + + if (str.endsWith(suffix)) { + return str.substring(0, str.length() - suffix.length()); + } + return str; + } + + /** + * 当前时间 + * + * @author stylefeng + * @Date 2017/5/7 21:56 + */ + public static String currentTime() { + return DateUtils.getTime(); + } + + /** + * 首字母大写 + * + * @author stylefeng + * @Date 2017/5/7 22:01 + */ + public static String firstLetterToUpper(String val) { + return StrKit.firstCharToUpperCase(val); + } + + /** + * 首字母小写 + * + * @author stylefeng + * @Date 2017/5/7 22:02 + */ + public static String firstLetterToLower(String val) { + return StrKit.firstCharToLowerCase(val); + } + + /** + * 判断是否是windows操作系统 + * + * @author stylefeng + * @Date 2017/5/24 22:34 + */ + public static Boolean isWinOs() { + String os = System.getProperty("os.name"); + if (os.toLowerCase().startsWith("win")) { + return true; + } else { + return false; + } + } + + /** + * 获取临时目录 + * + * @author stylefeng + * @Date 2017/5/24 22:35 + */ + public static String getTempPath() { + return System.getProperty("java.io.tmpdir"); + } + + /** + * 把一个数转化为int + * + * @author fengshuonan + * @Date 2017/11/15 下午11:10 + */ + public static Integer toInt(Object val) { + if (val instanceof Double) { + BigDecimal bigDecimal = new BigDecimal((Double) val); + return bigDecimal.intValue(); + } else { + return Integer.valueOf(val.toString()); + } + + } + + /** + * 获取项目路径 + */ + public static String getWebRootPath(String filePath) { + try { + String path = ToolUtil.class.getClassLoader().getResource("").toURI().getPath(); + path = path.replace("/WEB-INF/classes/", ""); + path = path.replace("/target/classes/", ""); + path = path.replace("file:/", ""); + if (ToolUtil.isEmpty(filePath)) { + return path; + } else { + return path + "/" + filePath; + } + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** + * 获取文件后缀名 不包含点 + */ + public static String getFileSuffix(String fileWholeName) { + if (ToolUtil.isEmpty(fileWholeName)) { + return "none"; + } + int lastIndexOf = fileWholeName.lastIndexOf("."); + return fileWholeName.substring(lastIndexOf + 1); + } + + /** + * 逗号拼接字符串 + */ + public static String commaSpliceString(String first, String second, Object... param) { + StringBuffer sb = new StringBuffer(); + sb.append(first + "," + second); + if (param != null) { + for (int i = 0; i < param.length; i++) { + sb.append("," + param[i]); + } + } + return sb.toString(); + } + + /** + * List列表去重 + */ + public static List listRemoveDuplicate(List list) { + HashSet h = new HashSet(list); + list.clear(); + list.addAll(h); + return list; + } + + /** + * H5页面代码包装(判断加上自适应代码) + */ + public static String h5Warpper(String h5Code) { + String warpper = "<meta name=\"viewport\" content=\"width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no\"/>"; + // 代码不包含自适应代码,前部追加代码 + if (!h5Code.contains(warpper)) { + return warpper + h5Code; + } + return h5Code; + } + + /** + * 字符串Base64位加密 + */ + public static String Base64Encode(String src) { + return new String(Base64.getEncoder().encode(src.getBytes())); + } + + /** + * 字符串Base64位解密 + */ + public static String Base64Decode(String src) { + return new String(Base64.getDecoder().decode(src.getBytes())); + } + + /** + * 排序签名:通常需要签名和验签,而签名时,需要对url内容进行排序。 + */ + public static String putPairsSequenceAndTogether(Map<String, String> info) { + List<Entry<String, String>> infoIds = new ArrayList<Entry<String, String>>(info.entrySet()); + Collections.sort(infoIds, new Comparator<Entry<String, String>>() { + @Override + public int compare(Entry<String, String> arg0, Entry<String, String> arg1) { + // TODO Auto-generated method stub + return (arg0.getKey()).compareTo(arg1.getKey()); + } + }); + String ret = ""; + for (Entry<String, String> entry : infoIds) { + ret += entry.getKey(); + ret += "="; + ret += entry.getValue(); + ret += "&"; + } + ret = ret.substring(0, ret.length() - 1); + return ret; + } + + /** + * 将Map封装为Url参数串 + */ + public static String getUrlParmStr(Map<String, Object> map) { + StringBuffer sb = new StringBuffer(); + for (Entry<String, Object> entry : map.entrySet()) { + sb.append(entry.getKey()); + sb.append("="); + sb.append(entry.getValue()); + sb.append("&"); + } + return sb.toString(); + } + + /** + * 获取客户端真实IP地址 + */ + public static String getIpAddress(HttpServletRequest request) { + // 避免反向代理不能获取真实地址, 取X-Forwarded-For中第一个非unknown的有效IP字符串 + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } + + /** + * 字符串转对象 + * + * @param str 字符串 + * @param classOfT 转换后对象类 + * @param <T> 转换后对象 + * @return + */ + public static <T> T fromJson(String str, Class<T> classOfT) { + Gson gson = new Gson(); + return gson.fromJson(str, classOfT); + } + +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/WxPayUtils.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/WxPayUtils.java deleted file mode 100644 index 2583d2f..0000000 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/WxPayUtils.java +++ /dev/null @@ -1,287 +0,0 @@ -/* -package com.ruoyi.order.util; - -import cn.hutool.http.HttpRequest; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; - -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.JDOMException; -import org.jdom2.input.SAXBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.security.*; -import java.util.*; - - -public class WxPayUtils { - public static final String serial_no = "xxx"; - // 商户号 - public static final String mchId = "xxx"; - // appid - public static final String appId = "xxx"; - - // 证书私钥 - public static final String privateKey = "-----BEGIN PRIVATE KEY-----\n" + - "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBJn3bVt9BbLhs\n" + - "+ZjULV7Odh4rtBBd2wc7uZ8RlN/9E8sJfAefowiSTPwOkTYKDlyhpG131a4VKj+N\n" + - "zaTu0Y5zQGyl29ElHVVuPw4mVni7xyqVdJ5VUxyJMKHmQsGpngHS4sF28c5Aihfi\n" + - "Gkydt6BRF8xwFC9u+D0r4PY9dwHTn4jyaFd25CMUxVO+rfjOWFuGa/rEjtQw03KU\n" + - "UVR6np6FmNXdWalQbmbETyUqGjCac6J7hDZ1LIRU4YtqMqqsXhnk3FaoS23MOgaZ\n" + - "RE3nIgpYqGgfXfLOKDt5n4zLALJkV0xmk3VErbheWpzRVFae/JMtsf/8ySgtiOga\n" + - "n8fvShJNAgMBAAECggEAf+P+vbb9yJI2Y2G5QfRwrAAl5gYqOBsI5RD5NGkBDs+G\n" + - "RtdrLNaEnGqBExwvTeVIjHcVTJ2d0MHSpxAdP0xeKA3mYsPz7cFIieESe2wSMTOl\n" + - "DKTVGeYYJPagnJhjJu5KgtpGA34EdVN6kOmdBWlKq6c4ZJXY+n8/8cfZA8XC3d3B\n" + - "favo104podp8cC2IVNMs21OzbjD4V+6VV9X/5BA6x7bDcarlJXSyCehdXgjhjNmT\n" + - "/9gz7MFhOsUlAG7P03easIRcZCQL6z9MebD3xfVYcXnS4L3CcVw1FWEdLXxe/3IG\n" + - "Q8UPTPHhTLFRbURHI00x1jEvcD9qKXYgKeU/N7IY+QKBgQD93r2SotKM5EDxM3L2\n" + - "5UFrmEVnf4bwg5QDyZFpjAJ+/uMSsEX3f1m8Mst82Y4Mybz8XVMNsUJmoY8eJoM+\n" + - "sqRbI5HXySsFEbDqh7jrtBoN7R1rl3jQw4qxqWYR8GQJ6VqAXuEFbrxgE1YFgqw5\n" + - "40HAYbv417h0h5A1rcRKegoW9wKBgQDCxVaCmBzcYYFc2leRy6qH965OEedqbSCV\n" + - "QPprCDBoBM6jrq97ZfWyfmLNSjjFhTSz9h8z5dQcePZrrI3+evlE8V18hUmWN6rM\n" + - "CvPCb+4q8CwiHmLFqVp+m11MR8EOBcWCW/HlioqBKTLglijY53RUjW7No/T+32sf\n" + - "5R1qYq672wKBgQC3dztFN4o169bK+UWCDBgFK9wsecsJEe3r9sWxo09Ce+2aWe2W\n" + - "eWBeU88fARJZR4neT4tv/8Re6y7EuUxsCSoh+0iwy17doPVb6I3JOTUDD3MNiD/1\n" + - "jvsyfZuYJ0QErbGLyAWSqX5VaGPoQ5E3nHauE3OG2E8jV7zuLhAHSr7z7QKBgAF8\n" + - "Z/CPIIk95TLEJ67hEuf+p8HIuS9CreD1ofN3GIdyofD1wDj8yicWd8KBMnWvUnud\n" + - "ARfwRPICqj6gDmVGoug3vzLYAXu36QGtg7aUDAkf0/ZerPo9FIeqv8d5NKvat2sL\n" + - "MIlDyVK68bxs6NreyTBr89B108SuB68ynErXfeXJAoGBAMCoJyWdFAQKVvycHyv4\n" + - "914+v7niQahws23wxHlzvup8/doCS1XVQAoEyQ4iIPDHYmiOCcmzCQnb1CWgMbIl\n" + - "oBY3baP1GWOwEWw/HYKOwHW3fLkYC/xaRi+b5IxyEzR7hlCm/A6gCnCUYqIdU8gd\n" + - "jYE4kGB2O/5vdbITdSMai47o\n" + - "-----END PRIVATE KEY-----"; - - - */ -/** - * 获取微信预支付订单号 - * @return - *//* - - public JSONObject getPrepayId(Integer apptype, String outTradeNo, String body1,String openId, Double price){ - - JSONObject jsonObject = new JSONObject(); - JSONObject amountJsonObject = new JSONObject(); - JSONObject payerJsonObject = new JSONObject(); - amountJsonObject.put("total",price); - payerJsonObject.put("openid",openId); - // 应用ID - jsonObject.put("appid",appId); - // 商户号 - jsonObject.put("mchid",mchId); - // 商品描述 - jsonObject.put("description",body1); - // 商户订单号 - jsonObject.put("out_trade_no",outTradeNo); - // 通知地址 - jsonObject.put("notify_url","https://zc.xxx.com/wx/api/pay/notifyUrl"); - // 订单金额信息 - jsonObject.put("amount",amountJsonObject); - // 支付者信息 - jsonObject.put("payer",payerJsonObject); - String body = jsonObject.toString(); - System.out.println(body); - String authorization = signStr("POST", "/v3/pay/transactions/jsapi", body); - - String result = HttpRequest.post("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi") - .body(body) - .header("Content-Type","application/json") - .header("Accept","application/json") - .header("Authorization","WECHATPAY2-SHA256-RSA2048 " + authorization)//头信息,多个头信息多次调用此方法即可 - .timeout(10000)//超时,毫秒 - .execute().body(); - JSONObject jsonObject1 = JSONUtil.parseObj(result); - String prepay_id = jsonObject1 == null ? "":(String) jsonObject1.get("prepay_id"); - JSONObject resultJsonObject = new JSONObject(); - resultJsonObject.put("prepay_id",prepay_id); - resultJsonObject.put("chatPrice",wxOrder.getTotalPrice()); - return resultJsonObject; - } - - */ -/** - * 成功获取微信预支付订单号后, 返回给前端调起微信支付的必要参数 - * @param orderNo 商户订单号 - * @param prepay_id 预支付订单号 - * @return - *//* - - public Map<String, Object> returnToReceptionJson(String orderNo, String prepay_id){ - HashMap<String, Object> map = new HashMap<>(); - long timeStamp = System.currentTimeMillis() / 1000; - String uuid = UUID.randomUUID().toString().replace("-", ""); - String paySign = getPaySign(timeStamp, uuid, prepay_id); - map.put("orderId", orderNo); - map.put("timeStamp", timeStamp); - map.put("nonceStr", uuid); - map.put("package", "prepay_id=" + prepay_id); - map.put("signType", "RSA"); - map.put("paySign", paySign); - return map; - } - - public String getPaySign(long timestamp, String randString, String prepay_id){ - String data = appId + "\n" + - timestamp + "\n" + - randString + "\n" + - "prepay_id=" + prepay_id + "\n"; - String signature = null; - try { - signature = sign(data.getBytes("utf-8")); - } catch (SignatureException e) { - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return signature; - } - - public String signStr2(String method, String url){ - String nonceStr = UUID.randomUUID().toString(); - long timestamp = System.currentTimeMillis() / 1000; - String message = buildMessage2(method, url, timestamp, nonceStr); - String signature = null; - try { - signature = sign(message.getBytes("utf-8")); - } catch (Exception e) { - e.printStackTrace(); - } - System.out.println("签名后:[" + signature + "]"); - return "mchid=\"" + mchId + "\"," - + "serial_no=\"" + serial_no + "\"," - + "nonce_str=\"" + nonceStr + "\"," - + "timestamp=\"" + timestamp + "\"," - + "signature=\"" + signature + "\""; - } - - public String buildMessage2(String method, String url, long timestamp, String nonceStr) { - String str = method + "\n" - + url + "\n" - + timestamp + "\n" - + nonceStr + "\n\n"; - System.out.println("签名数据[" + str + "]"); - return str; - } - - public String signStr(String method, String url, String body){ - String nonceStr = UUID.randomUUID().toString(); - long timestamp = System.currentTimeMillis() / 1000; - String message = buildMessage(method, url, timestamp, nonceStr, body); - System.out.println("message:[" + message + "]"); - String signature = null; - try { - signature = sign(message.getBytes("utf-8")); - } catch (Exception e) { - e.printStackTrace(); - } - System.out.println("signature=[" + signature + "]"); - return "mchid=\"" + mchId + "\"," - + "nonce_str=\"" + nonceStr + "\"," - + "timestamp=\"" + timestamp + "\"," - + "serial_no=\"" + serial_no + "\"," - + "signature=\"" + signature + "\""; - } - - public String buildMessage(String method, String url, long timestamp, String nonceStr, String body) { - String str = method + "\n" - + url + "\n" - + timestamp + "\n" - + nonceStr + "\n" - + body + "\n"; - return str; - } - - public String sign(byte[] message) throws Exception { - Signature sign = null; - try { - sign = Signature.getInstance("SHA256withRSA"); - PrivateKey privateKey = getPrivateKey(); - sign.initSign(privateKey); - sign.update(message); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (SignatureException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return Base64.getEncoder().encodeToString(sign.sign()); - } - */ -/** - * 获取私钥。 - *//* - - public static PrivateKey getPrivateKey() throws IOException { - PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey( - new ByteArrayInputStream(privateKey.getBytes("utf-8"))); - return merchantPrivateKey; - } - - // xml解析 - public static Map doXMLParse(String strxml) throws JDOMException, IOException { - strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); - if(null == strxml || "".equals(strxml)) { - return null; - } - Map m = new HashMap(); - InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); - SAXBuilder builder = new SAXBuilder(); - Document doc = builder.build(in); - Element root = doc.getRootElement(); - List list = root.getChildren(); - Iterator it = list.iterator(); - while(it.hasNext()) { - Element e = (Element) it.next(); - String k = e.getName(); - String v = ""; - List children = e.getChildren(); - if(children.isEmpty()) { - v = e.getTextNormalize(); - } else { - v = getChildrenText(children); - } - m.put(k, v); - } - //关闭流 - in.close(); - return m; - } - - */ -/** - * 获取子结点的xml - * - * @param children - * @return String - *//* - - public static String getChildrenText(List children) { - StringBuffer sb = new StringBuffer(); - if(!children.isEmpty()) { - Iterator it = children.iterator(); - while(it.hasNext()) { - Element e = (Element) it.next(); - String name = e.getName(); - String value = e.getTextNormalize(); - List list = e.getChildren(); - sb.append("<" + name + ">"); - if(!list.isEmpty()) { - sb.append(getChildrenText(list)); - } - sb.append(value); - sb.append("</" + name + ">"); - } - } - return sb.toString(); - } -} -*/ diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/JwtProperties.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/JwtProperties.java new file mode 100644 index 0000000..918844e --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/JwtProperties.java @@ -0,0 +1,71 @@ +package com.ruoyi.order.util.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * jwt相关配置 + * + * @author fengshuonan + * @date 2017-08-23 9:23 + */ +@Configuration +@ConfigurationProperties(prefix = JwtProperties.JWT_PREFIX) +public class JwtProperties { + + public static final String JWT_PREFIX = "jwt"; + + private String header = "Authorization"; + + private String secret = "defaultSecret"; + + private Long expiration = 604800L; + + private String authPath = "auth"; + + private String md5Key = "randomKey"; + + public static String getJwtPrefix() { + return JWT_PREFIX; + } + + public String getHeader() { + return header; + } + + public void setHeader(String header) { + this.header = header; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public Long getExpiration() { + return expiration; + } + + public void setExpiration(Long expiration) { + this.expiration = expiration; + } + + public String getAuthPath() { + return authPath; + } + + public void setAuthPath(String authPath) { + this.authPath = authPath; + } + + public String getMd5Key() { + return md5Key; + } + + public void setMd5Key(String md5Key) { + this.md5Key = md5Key; + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/PayProperties.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/PayProperties.java new file mode 100644 index 0000000..a92b104 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/PayProperties.java @@ -0,0 +1,74 @@ +package com.ruoyi.order.util.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +/** + * 配置参数 + * + * @author: KingKong + * @create: 2018-12-17 14:36 + **/ +@Data +@Component +@Configuration +@ConfigurationProperties(prefix = "pay") +public class PayProperties { + + /** + * 应用私钥 + */ + private String aliPrivateKey; + /** + * 支付宝公钥(不是应用公钥) + */ + private String aliPublicKey; + private String aliAppId; + private String aliNotifyUrl; + private String aliReturnUrl; + /** + * 支付宝账号 + */ + private String aliSellerId; + + + /** + * 微信appId + */ + private String wxAppId; + /** + * 微信服务号ID + */ + private String wxServiceAppId; + /** + * 商户号 + */ + private String wxMchId; + /** + * 微信key + */ + private String wxPayKey; + /** + * 支付回调地址 + */ + private String wxNotifyUrl; + /** + * 支付回显地址 + */ + private String wxReturnUrl; + /** + * 微信secret + */ + private String wxAppSecret; + /** + * 微信公众号secret + */ + private String wxPublicSecretKey; + /** + * 微信证书位置 + */ + private String wxCertPath; + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/RestProperties.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/RestProperties.java new file mode 100644 index 0000000..0d74a95 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/properties/RestProperties.java @@ -0,0 +1,57 @@ +package com.ruoyi.order.util.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 项目相关配置 + * + * @author fengshuonan + * @date 2017年10月23日16:44:15 + */ +@Configuration +@ConfigurationProperties(prefix = RestProperties.REST_PREFIX) +public class RestProperties { + + public static final String REST_PREFIX = "rest"; + + private boolean authOpen = true; + + private boolean signOpen = true; + + private boolean swaggerOpen = true; + + private String fileUploadPath; + + public boolean isAuthOpen() { + return authOpen; + } + + public void setAuthOpen(boolean authOpen) { + this.authOpen = authOpen; + } + + public boolean isSignOpen() { + return signOpen; + } + + public void setSignOpen(boolean signOpen) { + this.signOpen = signOpen; + } + + public boolean isSwaggerOpen() { + return swaggerOpen; + } + + public void setSwaggerOpen(boolean swaggerOpen) { + this.swaggerOpen = swaggerOpen; + } + + public String getFileUploadPath() { + return fileUploadPath; + } + + public void setFileUploadPath(String fileUploadPath) { + this.fileUploadPath = fileUploadPath; + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/BasicType.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/BasicType.java new file mode 100644 index 0000000..4c07e1f --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/BasicType.java @@ -0,0 +1,38 @@ +package com.ruoyi.order.util.support; + +import java.util.HashMap; +import java.util.Map; + +/** + * 基本变量类型的枚举 + * + * @author xiaoleilu + */ +public enum BasicType { + BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING; + + /** + * 原始类型为Key,包装类型为Value,例如: int.class -> Integer.class. + */ + public static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<Class<?>, Class<?>>(8); + + /** + * 包装类型为Key,原始类型为Value,例如: Integer.class -> int.class. + */ + public static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<Class<?>, Class<?>>(8); + + static { + wrapperPrimitiveMap.put(Boolean.class, boolean.class); + wrapperPrimitiveMap.put(Byte.class, byte.class); + wrapperPrimitiveMap.put(Character.class, char.class); + wrapperPrimitiveMap.put(Double.class, double.class); + wrapperPrimitiveMap.put(Float.class, float.class); + wrapperPrimitiveMap.put(Integer.class, int.class); + wrapperPrimitiveMap.put(Long.class, long.class); + wrapperPrimitiveMap.put(Short.class, short.class); + + for (Map.Entry<Class<?>, Class<?>> entry : wrapperPrimitiveMap.entrySet()) { + primitiveWrapperMap.put(entry.getValue(), entry.getKey()); + } + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/CollectionKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/CollectionKit.java new file mode 100644 index 0000000..9238e7e --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/CollectionKit.java @@ -0,0 +1,833 @@ +package com.ruoyi.order.util.support; + + + +import com.ruoyi.common.core.exception.ServiceException; + +import java.lang.reflect.Array; +import java.util.*; +import java.util.Map.Entry; + +/** + * 集合相关工具类,包括数组 + * + * @author xiaoleilu + */ +public class CollectionKit { + + private CollectionKit() { + // 静态类不可实例化 + } + + /** + * 以 conjunction 为分隔符将集合转换为字符串 + * + * @param <T> 被处理的集合 + * @param collection 集合 + * @param conjunction 分隔符 + * @return 连接后的字符串 + */ + public static <T> String join(Iterable<T> collection, String conjunction) { + StringBuilder sb = new StringBuilder(); + boolean isFirst = true; + for (T item : collection) { + if (isFirst) { + isFirst = false; + } else { + sb.append(conjunction); + } + sb.append(item); + } + return sb.toString(); + } + + /** + * 以 conjunction 为分隔符将数组转换为字符串 + * + * @param <T> 被处理的集合 + * @param array 数组 + * @param conjunction 分隔符 + * @return 连接后的字符串 + */ + public static <T> String join(T[] array, String conjunction) { + StringBuilder sb = new StringBuilder(); + boolean isFirst = true; + for (T item : array) { + if (isFirst) { + isFirst = false; + } else { + sb.append(conjunction); + } + sb.append(item); + } + return sb.toString(); + } + + /** + * 将多个集合排序并显示不同的段落(分页) + * + * @param pageNo 页码 + * @param numPerPage 每页的条目数 + * @param comparator 比较器 + * @param colls 集合数组 + * @return 分页后的段落内容 + */ + @SafeVarargs + public static <T> List<T> sortPageAll(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) { + final List<T> result = new ArrayList<T>(); + for (Collection<T> coll : colls) { + result.addAll(coll); + } + + Collections.sort(result, comparator); + + //第一页且数目少于第一页显示的数目 + if (pageNo <= 1 && result.size() <= numPerPage) { + return result; + } + + final int[] startEnd = PageKit.transToStartEnd(pageNo, numPerPage); + return result.subList(startEnd[0], startEnd[1]); + } + + /** + * 将多个集合排序并显示不同的段落(分页) + * @param pageNo 页码 + * @param numPerPage 每页的条目数 + * @param comparator 比较器 + * @param colls 集合数组 + * @return 分业后的段落内容 + */ +// @SafeVarargs +// public static <T> List<T> sortPageAll2(int pageNo, int numPerPage, Comparator<T> comparator, Collection<T>... colls) { +// BoundedPriorityQueue<T> queue = new BoundedPriorityQueue<T>(pageNo * numPerPage); +// for (Collection<T> coll : colls) { +// queue.addAll(coll); +// } +// +// //第一页且数目少于第一页显示的数目 +// if(pageNo <=1 && queue.size() <= numPerPage) { +// return queue.toList(); +// } +// +// final int[] startEnd = PageKit.transToStartEnd(pageNo, numPerPage); +// return queue.toList().subList(startEnd[0], startEnd[1]); +// } + + /** + * 将Set排序(根据Entry的值) + * + * @param set 被排序的Set + * @return 排序后的Set + */ + public static List<Entry<Long, Long>> sortEntrySetToList(Set<Entry<Long, Long>> set) { + List<Entry<Long, Long>> list = new LinkedList<Entry<Long, Long>>(set); + Collections.sort(list, new Comparator<Entry<Long, Long>>() { + + @Override + public int compare(Entry<Long, Long> o1, Entry<Long, Long> o2) { + if (o1.getValue() > o2.getValue()) { + return 1; + } + if (o1.getValue() < o2.getValue()) { + return -1; + } + return 0; + } + }); + return list; + } + + /** + * 切取部分数据 + * + * @param <T> 集合元素类型 + * @param surplusAlaDatas 原数据 + * @param partSize 每部分数据的长度 + * @return 切取出的数据或null + */ + public static <T> List<T> popPart(Stack<T> surplusAlaDatas, int partSize) { + if (surplusAlaDatas == null || surplusAlaDatas.size() <= 0) { + return null; + } + + final List<T> currentAlaDatas = new ArrayList<T>(); + int size = surplusAlaDatas.size(); + // 切割 + if (size > partSize) { + for (int i = 0; i < partSize; i++) { + currentAlaDatas.add(surplusAlaDatas.pop()); + } + } else { + for (int i = 0; i < size; i++) { + currentAlaDatas.add(surplusAlaDatas.pop()); + } + } + return currentAlaDatas; + } + + /** + * 切取部分数据 + * + * @param <T> 集合元素类型 + * @param surplusAlaDatas 原数据 + * @param partSize 每部分数据的长度 + * @return 切取出的数据或null + */ + public static <T> List<T> popPart(Deque<T> surplusAlaDatas, int partSize) { + if (surplusAlaDatas == null || surplusAlaDatas.size() <= 0) { + return null; + } + + final List<T> currentAlaDatas = new ArrayList<T>(); + int size = surplusAlaDatas.size(); + // 切割 + if (size > partSize) { + for (int i = 0; i < partSize; i++) { + currentAlaDatas.add(surplusAlaDatas.pop()); + } + } else { + for (int i = 0; i < size; i++) { + currentAlaDatas.add(surplusAlaDatas.pop()); + } + } + return currentAlaDatas; + } + + /** + * 新建一个HashMap + * + * @return HashMap对象 + */ + public static <T, K> HashMap<T, K> newHashMap() { + return new HashMap<T, K>(); + } + + /** + * 新建一个HashMap + * + * @param size 初始大小,由于默认负载因子0.75,传入的size会实际初始大小为size / 0.75 + * @return HashMap对象 + */ + public static <T, K> HashMap<T, K> newHashMap(int size) { + return new HashMap<T, K>((int) (size / 0.75)); + } + + /** + * 新建一个HashSet + * + * @return HashSet对象 + */ + public static <T> HashSet<T> newHashSet() { + return new HashSet<T>(); + } + + /** + * 新建一个HashSet + * + * @return HashSet对象 + */ + @SafeVarargs + public static <T> HashSet<T> newHashSet(T... ts) { + HashSet<T> set = new HashSet<T>(); + for (T t : ts) { + set.add(t); + } + return set; + } + + /** + * 新建一个ArrayList + * + * @return ArrayList对象 + */ + public static <T> ArrayList<T> newArrayList() { + return new ArrayList<T>(); + } + + /** + * 新建一个ArrayList + * + * @return ArrayList对象 + */ + @SafeVarargs + public static <T> ArrayList<T> newArrayList(T... values) { + return new ArrayList<T>(Arrays.asList(values)); + } + + /** + * 将新元素添加到已有数组中<br/> + * 添加新元素会生成一个新的数组,不影响原数组 + * + * @param buffer 已有数组 + * @param newElement 新元素 + * @return 新数组 + */ + public static <T> T[] append(T[] buffer, T newElement) { + T[] t = resize(buffer, buffer.length + 1, newElement.getClass()); + t[buffer.length] = newElement; + return t; + } + + /** + * 生成一个新的重新设置大小的数组 + * + * @param buffer 原数组 + * @param newSize 新的数组大小 + * @param componentType 数组元素类型 + * @return 调整后的新数组 + */ + public static <T> T[] resize(T[] buffer, int newSize, Class<?> componentType) { + T[] newArray = newArray(componentType, newSize); + System.arraycopy(buffer, 0, newArray, 0, buffer.length >= newSize ? newSize : buffer.length); + return newArray; + } + + /** + * 新建一个空数组 + * + * @param componentType 元素类型 + * @param newSize 大小 + * @return 空数组 + */ + @SuppressWarnings("unchecked") + public static <T> T[] newArray(Class<?> componentType, int newSize) { + return (T[]) Array.newInstance(componentType, newSize); + } + + /** + * 生成一个新的重新设置大小的数组<br/> + * 新数组的类型为原数组的类型 + * + * @param buffer 原数组 + * @param newSize 新的数组大小 + * @return 调整后的新数组 + */ + public static <T> T[] resize(T[] buffer, int newSize) { + return resize(buffer, newSize, buffer.getClass().getComponentType()); + } + + /** + * 将多个数组合并在一起<br> + * 忽略null的数组 + * + * @param arrays 数组集合 + * @return 合并后的数组 + */ + @SafeVarargs + public static <T> T[] addAll(T[]... arrays) { + if (arrays.length == 1) { + return arrays[0]; + } + + int length = 0; + for (T[] array : arrays) { + if (array == null) { + continue; + } + length += array.length; + } + T[] result = newArray(arrays.getClass().getComponentType().getComponentType(), length); + + length = 0; + for (T[] array : arrays) { + if (array == null) { + continue; + } + System.arraycopy(array, 0, result, length, array.length); + length += array.length; + } + return result; + } + + /** + * 克隆数组 + * + * @param array 被克隆的数组 + * @return 新数组 + */ + public static <T> T[] clone(T[] array) { + if (array == null) { + return null; + } + return array.clone(); + } + + /** + * 生成一个数字列表<br> + * 自动判定正序反序 + * + * @param excludedEnd 结束的数字(不包含) + * @return 数字列表 + */ + public static int[] range(int excludedEnd) { + return range(0, excludedEnd, 1); + } + + /** + * 生成一个数字列表<br> + * 自动判定正序反序 + * + * @param includedStart 开始的数字(包含) + * @param excludedEnd 结束的数字(不包含) + * @return 数字列表 + */ + public static int[] range(int includedStart, int excludedEnd) { + return range(includedStart, excludedEnd, 1); + } + + /** + * 生成一个数字列表<br> + * 自动判定正序反序 + * + * @param includedStart 开始的数字(包含) + * @param excludedEnd 结束的数字(不包含) + * @param step 步进 + * @return 数字列表 + */ + public static int[] range(int includedStart, int excludedEnd, int step) { + if (includedStart > excludedEnd) { + int tmp = includedStart; + includedStart = excludedEnd; + excludedEnd = tmp; + } + + if (step <= 0) { + step = 1; + } + + int deviation = excludedEnd - includedStart; + int length = deviation / step; + if (deviation % step != 0) { + length += 1; + } + int[] range = new int[length]; + for (int i = 0; i < length; i++) { + range[i] = includedStart; + includedStart += step; + } + return range; + } + + /** + * 截取数组的部分 + * + * @param list 被截取的数组 + * @param start 开始位置(包含) + * @param end 结束位置(不包含) + * @return 截取后的数组,当开始位置超过最大时,返回null + */ + public static <T> List<T> sub(List<T> list, int start, int end) { + if (list == null || list.isEmpty()) { + return null; + } + + if (start < 0) { + start = 0; + } + if (end < 0) { + end = 0; + } + + if (start > end) { + int tmp = start; + start = end; + end = tmp; + } + + final int size = list.size(); + if (end > size) { + if (start >= size) { + return null; + } + end = size; + } + + return list.subList(start, end); + } + + /** + * 截取集合的部分 + * + * @param list 被截取的数组 + * @param start 开始位置(包含) + * @param end 结束位置(不包含) + * @return 截取后的数组,当开始位置超过最大时,返回null + */ + public static <T> List<T> sub(Collection<T> list, int start, int end) { + if (list == null || list.isEmpty()) { + return null; + } + + return sub(new ArrayList<T>(list), start, end); + } + + /** + * 数组是否为空 + * + * @param array 数组 + * @return 是否为空 + */ + public static <T> boolean isEmpty(T[] array) { + return array == null || array.length == 0; + } + + /** + * 数组是否为非空 + * + * @param array 数组 + * @return 是否为非空 + */ + public static <T> boolean isNotEmpty(T[] array) { + return false == isEmpty(array); + } + + /** + * 集合是否为空 + * + * @param collection 集合 + * @return 是否为空 + */ + public static boolean isEmpty(Collection<?> collection) { + return collection == null || collection.isEmpty(); + } + + /** + * 集合是否为非空 + * + * @param collection 集合 + * @return 是否为非空 + */ + public static boolean isNotEmpty(Collection<?> collection) { + return false == isEmpty(collection); + } + + /** + * Map是否为空 + * + * @param map 集合 + * @return 是否为空 + */ + public static boolean isEmpty(Map<?, ?> map) { + return map == null || map.isEmpty(); + } + + /** + * Map是否为非空 + * + * @param map 集合 + * @return 是否为非空 + */ + public static <T> boolean isNotEmpty(Map<?, ?> map) { + return false == isEmpty(map); + } + + /** + * 映射键值(参考Python的zip()函数)<br> + * 例如:<br> + * keys = [a,b,c,d]<br> + * values = [1,2,3,4]<br> + * 则得到的Map是 {a=1, b=2, c=3, d=4}<br> + * 如果两个数组长度不同,则只对应最短部分 + * + * @param keys 键列表 + * @param values 值列表 + * @return Map + */ + public static <T, K> Map<T, K> zip(T[] keys, K[] values) { + if (isEmpty(keys) || isEmpty(values)) { + return null; + } + + final int size = Math.min(keys.length, values.length); + final Map<T, K> map = new HashMap<T, K>((int) (size / 0.75)); + for (int i = 0; i < size; i++) { + map.put(keys[i], values[i]); + } + + return map; + } + + /** + * 映射键值(参考Python的zip()函数)<br> + * 例如:<br> + * keys = a,b,c,d<br> + * values = 1,2,3,4<br> + * delimiter = , + * 则得到的Map是 {a=1, b=2, c=3, d=4}<br> + * 如果两个数组长度不同,则只对应最短部分 + * + * @param keys 键列表 + * @param values 值列表 + * @return Map + */ + public static Map<String, String> zip(String keys, String values, String delimiter) { + return zip(StrKit.split(keys, delimiter), StrKit.split(values, delimiter)); + } + + /** + * 映射键值(参考Python的zip()函数)<br> + * 例如:<br> + * keys = [a,b,c,d]<br> + * values = [1,2,3,4]<br> + * 则得到的Map是 {a=1, b=2, c=3, d=4}<br> + * 如果两个数组长度不同,则只对应最短部分 + * + * @param keys 键列表 + * @param values 值列表 + * @return Map + */ + public static <T, K> Map<T, K> zip(Collection<T> keys, Collection<K> values) { + if (isEmpty(keys) || isEmpty(values)) { + return null; + } + + final List<T> keyList = new ArrayList<T>(keys); + final List<K> valueList = new ArrayList<K>(values); + + final int size = Math.min(keys.size(), values.size()); + final Map<T, K> map = new HashMap<T, K>((int) (size / 0.75)); + for (int i = 0; i < size; i++) { + map.put(keyList.get(i), valueList.get(i)); + } + + return map; + } + + /** + * 数组中是否包含元素 + * + * @param array 数组 + * @param value 被检查的元素 + * @return 是否包含 + */ + public static <T> boolean contains(T[] array, T value) { + final Class<?> componetType = array.getClass().getComponentType(); + boolean isPrimitive = false; + if (null != componetType) { + isPrimitive = componetType.isPrimitive(); + } + for (T t : array) { + if (t == value) { + return true; + } else if (false == isPrimitive && null != value && value.equals(t)) { + return true; + } + } + return false; + } + + /** + * 将Entry集合转换为HashMap + * + * @param entryCollection entry集合 + * @return Map + */ + public static <T, K> HashMap<T, K> toMap(Collection<Entry<T, K>> entryCollection) { + HashMap<T, K> map = new HashMap<T, K>(); + for (Entry<T, K> entry : entryCollection) { + map.put(entry.getKey(), entry.getValue()); + } + return map; + } + + /** + * 将集合转换为排序后的TreeSet + * + * @param collection 集合 + * @param comparator 比较器 + * @return treeSet + */ + public static <T> TreeSet<T> toTreeSet(Collection<T> collection, Comparator<T> comparator) { + final TreeSet<T> treeSet = new TreeSet<T>(comparator); + for (T t : collection) { + treeSet.add(t); + } + return treeSet; + } + + /** + * 排序集合 + * + * @param collection 集合 + * @param comparator 比较器 + * @return treeSet + */ + public static <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) { + List<T> list = new ArrayList<T>(collection); + Collections.sort(list, comparator); + return list; + } + + //------------------------------------------------------------------- 基本类型的数组转换为包装类型数组 + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Integer[] wrap(int... values) { + final int length = values.length; + Integer[] array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Long[] wrap(long... values) { + final int length = values.length; + Long[] array = new Long[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Character[] wrap(char... values) { + final int length = values.length; + Character[] array = new Character[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Byte[] wrap(byte... values) { + final int length = values.length; + Byte[] array = new Byte[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Short[] wrap(short... values) { + final int length = values.length; + Short[] array = new Short[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Float[] wrap(float... values) { + final int length = values.length; + Float[] array = new Float[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Double[] wrap(double... values) { + final int length = values.length; + Double[] array = new Double[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 将基本类型数组包装为包装类型 + * + * @param values 基本类型数组 + * @return 包装类型数组 + */ + public static Boolean[] wrap(boolean... values) { + final int length = values.length; + Boolean[] array = new Boolean[length]; + for (int i = 0; i < length; i++) { + array[i] = values[i]; + } + return array; + } + + /** + * 判定给定对象是否为数组类型 + * + * @param obj 对象 + * @return 是否为数组类型 + */ + public static boolean isArray(Object obj) { + return obj.getClass().isArray(); + } + + /** + * 数组或集合转String + * + * @param obj 集合或数组对象 + * @return 数组字符串,与集合转字符串格式相同 + */ + public static String toString(Object obj) { + if (null == obj) { + return null; + } + if (isArray(obj)) { + try { + return Arrays.deepToString((Object[]) obj); + } catch (Exception e) { + final String className = obj.getClass().getComponentType().getName(); + switch (className) { + case "long": + return Arrays.toString((long[]) obj); + case "int": + return Arrays.toString((int[]) obj); + case "short": + return Arrays.toString((short[]) obj); + case "char": + return Arrays.toString((char[]) obj); + case "byte": + return Arrays.toString((byte[]) obj); + case "boolean": + return Arrays.toString((boolean[]) obj); + case "float": + return Arrays.toString((float[]) obj); + case "double": + return Arrays.toString((double[]) obj); + default: + throw new ServiceException(e.getMessage()); + } + } + } + return obj.toString(); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTime.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTime.java new file mode 100644 index 0000000..5a569e8 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTime.java @@ -0,0 +1,70 @@ +package com.ruoyi.order.util.support; + +import java.util.Date; + +/** + * 封装java.util.Date + * + * @author xiaoleilu + */ +public class DateTime extends Date { + private static final long serialVersionUID = -5395712593979185936L; + + /** + * 转换JDK date为 DateTime + * + * @param date JDK Date + * @return DateTime + */ + public static DateTime parse(Date date) { + return new DateTime(date); + } + + /** + * 当前时间 + */ + public DateTime() { + super(); + } + + /** + * 给定日期的构造 + * + * @param date 日期 + */ + public DateTime(Date date) { + this(date.getTime()); + } + + /** + * 给定日期毫秒数的构造 + * + * @param timeMillis 日期毫秒数 + */ + public DateTime(long timeMillis) { + super(timeMillis); + } + + @Override + public String toString() { + return DateTimeKit.formatDateTime(this); + } + + public String toString(String format) { + return DateTimeKit.format(this, format); + } + + /** + * @return 输出精确到毫秒的标准日期形式 + */ + public String toMsStr() { + return DateTimeKit.format(this, DateTimeKit.NORM_DATETIME_MS_PATTERN); + } + + /** + * @return java.util.Date + */ + public Date toDate() { + return new Date(this.getTime()); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTimeKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTimeKit.java new file mode 100644 index 0000000..90faf65 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/DateTimeKit.java @@ -0,0 +1,709 @@ +package com.ruoyi.order.util.support; + +import com.ruoyi.common.core.exception.ServiceException; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Locale; + +/** + * 时间工具类 + * + * @author xiaoleilu + */ +public class DateTimeKit { + /** + * 毫秒 + */ + public final static long MS = 1; + /** + * 每秒钟的毫秒数 + */ + public final static long SECOND_MS = MS * 1000; + /** + * 每分钟的毫秒数 + */ + public final static long MINUTE_MS = SECOND_MS * 60; + /** + * 每小时的毫秒数 + */ + public final static long HOUR_MS = MINUTE_MS * 60; + /** + * 每天的毫秒数 + */ + public final static long DAY_MS = HOUR_MS * 24; + + /** + * 标准日期格式 + */ + public final static String NORM_DATE_PATTERN = "yyyy-MM-dd"; + /** + * 标准时间格式 + */ + public final static String NORM_TIME_PATTERN = "HH:mm:ss"; + /** + * 标准日期时间格式,精确到分 + */ + public final static String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm"; + /** + * 标准日期时间格式,精确到秒 + */ + public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + /** + * 标准日期时间格式,精确到毫秒 + */ + public final static String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; + /** + * HTTP头中日期时间格式 + */ + public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; + + /** + * 标准日期(不含时间)格式化器 + */ + // private final static SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat(NORM_DATE_PATTERN); + private static ThreadLocal<SimpleDateFormat> NORM_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() { + synchronized protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(NORM_DATE_PATTERN); + } + + ; + }; + /** + * 标准时间格式化器 + */ + // private final static SimpleDateFormat NORM_TIME_FORMAT = new SimpleDateFormat(NORM_TIME_PATTERN); + private static ThreadLocal<SimpleDateFormat> NORM_TIME_FORMAT = new ThreadLocal<SimpleDateFormat>() { + synchronized protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(NORM_TIME_PATTERN); + } + + ; + }; + /** + * 标准日期时间格式化器 + */ + // private final static SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat(NORM_DATETIME_PATTERN); + private static ThreadLocal<SimpleDateFormat> NORM_DATETIME_FORMAT = new ThreadLocal<SimpleDateFormat>() { + synchronized protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(NORM_DATETIME_PATTERN); + } + + ; + }; + /** + * HTTP日期时间格式化器 + */ + // private final static SimpleDateFormat HTTP_DATETIME_FORMAT = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US); + private static ThreadLocal<SimpleDateFormat> HTTP_DATETIME_FORMAT = new ThreadLocal<SimpleDateFormat>() { + synchronized protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US); + } + + ; + }; + + /** + * 当前时间,格式 yyyy-MM-dd HH:mm:ss + * + * @return 当前时间的标准形式字符串 + */ + public static String now() { + return formatDateTime(new DateTime()); + } + + /** + * 当前时间long + * + * @param isNano 是否为高精度时间 + * @return 时间 + */ + public static long current(boolean isNano) { + return isNano ? System.nanoTime() : System.currentTimeMillis(); + } + + /** + * 当前日期,格式 yyyy-MM-dd + * + * @return 当前日期的标准形式字符串 + */ + public static String today() { + return formatDate(new DateTime()); + } + + /** + * @return 当前月份 + */ + public static int thisMonth() { + return month(date()); + } + + /** + * @return 今年 + */ + public static int thisYear() { + return year(date()); + } + + /** + * @return 当前时间 + */ + public static DateTime date() { + return new DateTime(); + } + + /** + * Long类型时间转为Date + * + * @param date Long类型Date(Unix时间戳) + * @return 时间对象 + */ + public static DateTime date(long date) { + return new DateTime(date); + } + + /** + * 转换为Calendar对象 + * + * @param date 日期对象 + * @return Calendar对象 + */ + public static Calendar toCalendar(Date date) { + final Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return cal; + } + + /** + * 获得月份,从1月开始计数 + * + * @param date 日期 + * @return 月份 + */ + public static int month(Date date) { + return toCalendar(date).get(Calendar.MONTH) + 1; + } + + /** + * 获得年 + * + * @param date 日期 + * @return 年 + */ + public static int year(Date date) { + return toCalendar(date).get(Calendar.YEAR); + } + + /** + * 获得季节 + * + * @param date 日期 + * @return 第几个季节 + */ + public static int season(Date date) { + return toCalendar(date).get(Calendar.MONTH) / 3 + 1; + } + + /** + * 获得指定日期年份和季节<br> + * 格式:[20131]表示2013年第一季度 + * + * @param date 日期 + * @return Season ,类似于 20132 + */ + public static String yearAndSeason(Date date) { + return yearAndSeason(toCalendar(date)); + } + + /** + * 获得指定日期区间内的年份和季节<br> + * + * @param startDate 其实日期(包含) + * @param endDate 结束日期(包含) + * @return Season列表 ,元素类似于 20132 + */ + public static LinkedHashSet<String> yearAndSeasons(Date startDate, Date endDate) { + final LinkedHashSet<String> seasons = new LinkedHashSet<String>(); + if (startDate == null || endDate == null) { + return seasons; + } + + final Calendar cal = Calendar.getInstance(); + cal.setTime(startDate); + while (true) { + // 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环 + if (startDate.after(endDate)) { + startDate = endDate; + } + + seasons.add(yearAndSeason(cal)); + + if (startDate.equals(endDate)) { + break; + } + + cal.add(Calendar.MONTH, 3); + startDate = cal.getTime(); + } + + return seasons; + } + + // ------------------------------------ Format start ---------------------------------------------- + + /** + * 根据特定格式格式化日期 + * + * @param date 被格式化的日期 + * @param format 格式 + * @return 格式化后的字符串 + */ + public static String format(Date date, String format) { + return new SimpleDateFormat(format).format(date); + } + + /** + * 格式 yyyy-MM-dd HH:mm:ss + * + * @param date 被格式化的日期 + * @return 格式化后的日期 + */ + public static String formatDateTime(Date date) { + if (null == date) { + return null; + } + return NORM_DATETIME_FORMAT.get().format(date); + } + + /** + * 格式 yyyy-MM-dd + * + * @param date 被格式化的日期 + * @return 格式化后的字符串 + */ + public static String formatDate(Date date) { + if (null == date) { + return null; + } + return NORM_DATE_FORMAT.get().format(date); + } + + /** + * 格式化为Http的标准日期格式 + * + * @param date 被格式化的日期 + * @return HTTP标准形式日期字符串 + */ + public static String formatHttpDate(Date date) { + if (null == date) { + return null; + } + return HTTP_DATETIME_FORMAT.get().format(date); + } + // ------------------------------------ Format end ---------------------------------------------- + + // ------------------------------------ Parse start ---------------------------------------------- + + /** + * 构建DateTime对象 + * + * @param dateStr Date字符串 + * @param simpleDateFormat 格式化器 + * @return DateTime对象 + */ + public static DateTime parse(String dateStr, SimpleDateFormat simpleDateFormat) { + try { + return new DateTime(simpleDateFormat.parse(dateStr)); + } catch (Exception e) { + throw new ServiceException(StrKit.format("Parse [{}] with format [{}] error!", dateStr, simpleDateFormat.toPattern())); + } + } + + /** + * 将特定格式的日期转换为Date对象 + * + * @param dateString 特定格式的日期 + * @param format 格式,例如yyyy-MM-dd + * @return 日期对象 + */ + public static DateTime parse(String dateString, String format) { + return parse(dateString, new SimpleDateFormat(format)); + } + + /** + * 格式yyyy-MM-dd HH:mm:ss + * + * @param dateString 标准形式的时间字符串 + * @return 日期对象 + */ + public static DateTime parseDateTime(String dateString) { + return parse(dateString, NORM_DATETIME_FORMAT.get()); + } + + /** + * 格式yyyy-MM-dd + * + * @param dateString 标准形式的日期字符串 + * @return 日期对象 + */ + public static DateTime parseDate(String dateString) { + return parse(dateString, NORM_DATE_FORMAT.get()); + } + + /** + * 格式HH:mm:ss + * + * @param timeString 标准形式的日期字符串 + * @return 日期对象 + */ + public static DateTime parseTime(String timeString) { + return parse(timeString, NORM_TIME_FORMAT.get()); + } + + /** + * 格式:<br> + * 1、yyyy-MM-dd HH:mm:ss<br> + * 2、yyyy-MM-dd<br> + * 3、HH:mm:ss<br> + * 4、yyyy-MM-dd HH:mm 5、yyyy-MM-dd HH:mm:ss.SSS + * + * @param dateStr 日期字符串 + * @return 日期 + */ + public static DateTime parse(String dateStr) { + if (null == dateStr) { + return null; + } + dateStr = dateStr.trim(); + int length = dateStr.length(); + try { + if (length == NORM_DATETIME_PATTERN.length()) { + return parseDateTime(dateStr); + } else if (length == NORM_DATE_PATTERN.length()) { + return parseDate(dateStr); + } else if (length == NORM_TIME_PATTERN.length()) { + return parseTime(dateStr); + } else if (length == NORM_DATETIME_MINUTE_PATTERN.length()) { + return parse(dateStr, NORM_DATETIME_MINUTE_PATTERN); + } else if (length >= NORM_DATETIME_MS_PATTERN.length() - 2) { + return parse(dateStr, NORM_DATETIME_MS_PATTERN); + } + } catch (Exception e) { + + } + + // 没有更多匹配的时间格式 + throw new ServiceException(StrKit.format(" [{}] format is not fit for date pattern!", dateStr)); + } + // ------------------------------------ Parse end ---------------------------------------------- + + // ------------------------------------ Offset start ---------------------------------------------- + + /** + * 获取某天的开始时间 + * + * @param date 日期 + * @return 某天的开始时间 + */ + public static DateTime getBeginTimeOfDay(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + return new DateTime(calendar.getTime()); + } + + /** + * 获取某天的结束时间 + * + * @param date 日期 + * @return 某天的结束时间 + */ + public static DateTime getEndTimeOfDay(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.set(Calendar.HOUR_OF_DAY, 23); + calendar.set(Calendar.MINUTE, 59); + calendar.set(Calendar.SECOND, 59); + calendar.set(Calendar.MILLISECOND, 999); + return new DateTime(calendar.getTime()); + } + + /** + * 昨天 + * + * @return 昨天 + */ + public static DateTime yesterday() { + return offsiteDay(new DateTime(), -1); + } + + /** + * 上周 + * + * @return 上周 + */ + public static DateTime lastWeek() { + return offsiteWeek(new DateTime(), -1); + } + + /** + * 上个月 + * + * @return 上个月 + */ + public static DateTime lastMouth() { + return offsiteMonth(new DateTime(), -1); + } + + /** + * 偏移天 + * + * @param date 日期 + * @param offsite 偏移天数,正数向未来偏移,负数向历史偏移 + * @return 偏移后的日期 + */ + public static DateTime offsiteDay(Date date, int offsite) { + return offsiteDate(date, Calendar.DAY_OF_YEAR, offsite); + } + + /** + * 偏移周 + * + * @param date 日期 + * @param offsite 偏移周数,正数向未来偏移,负数向历史偏移 + * @return 偏移后的日期 + */ + public static DateTime offsiteWeek(Date date, int offsite) { + return offsiteDate(date, Calendar.WEEK_OF_YEAR, offsite); + } + + /** + * 偏移月 + * + * @param date 日期 + * @param offsite 偏移月数,正数向未来偏移,负数向历史偏移 + * @return 偏移后的日期 + */ + public static DateTime offsiteMonth(Date date, int offsite) { + return offsiteDate(date, Calendar.MONTH, offsite); + } + + /** + * 获取指定日期偏移指定时间后的时间 + * + * @param date 基准日期 + * @param calendarField 偏移的粒度大小(小时、天、月等)使用Calendar中的常数 + * @param offsite 偏移量,正数为向后偏移,负数为向前偏移 + * @return 偏移后的日期 + */ + public static DateTime offsiteDate(Date date, int calendarField, int offsite) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.add(calendarField, offsite); + return new DateTime(cal.getTime()); + } + // ------------------------------------ Offset end ---------------------------------------------- + + /** + * 判断两个日期相差的时长<br/> + * 返回 minuend - subtrahend 的差 + * + * @param subtrahend 减数日期 + * @param minuend 被减数日期 + * @param diffField 相差的选项:相差的天、小时 + * @return 日期差 + */ + public static long diff(Date subtrahend, Date minuend, long diffField) { + long diff = minuend.getTime() - subtrahend.getTime(); + return diff / diffField; + } + + /** + * 计时,常用于记录某段代码的执行时间,单位:纳秒 + * + * @param preTime 之前记录的时间 + * @return 时间差,纳秒 + */ + public static long spendNt(long preTime) { + return System.nanoTime() - preTime; + } + + /** + * 计时,常用于记录某段代码的执行时间,单位:毫秒 + * + * @param preTime 之前记录的时间 + * @return 时间差,毫秒 + */ + public static long spendMs(long preTime) { + return System.currentTimeMillis() - preTime; + } + + /** + * 格式化成yyMMddHHmm后转换为int型 + * + * @param date 日期 + * @return int + */ + public static int toIntSecond(Date date) { + return Integer.parseInt(format(date, "yyMMddHHmm")); + } + + /** + * 计算指定指定时间区间内的周数 + * + * @param start 开始时间 + * @param end 结束时间 + * @return 周数 + */ + public static int weekCount(Date start, Date end) { + final Calendar startCalendar = Calendar.getInstance(); + startCalendar.setTime(start); + final Calendar endCalendar = Calendar.getInstance(); + endCalendar.setTime(end); + + final int startWeekofYear = startCalendar.get(Calendar.WEEK_OF_YEAR); + final int endWeekofYear = endCalendar.get(Calendar.WEEK_OF_YEAR); + + int count = endWeekofYear - startWeekofYear + 1; + + if (Calendar.SUNDAY != startCalendar.get(Calendar.DAY_OF_WEEK)) { + count--; + } + + return count; + } + + /** + * 计时器<br> + * 计算某个过程话费的时间,精确到毫秒 + * + * @return Timer + */ + public static Timer timer() { + return new Timer(); + + } + + /** + * 生日转为年龄,计算法定年龄 + * + * @param birthDay 生日,标准日期字符串 + * @return 年龄 + * @throws Exception + */ + public static int ageOfNow(String birthDay) { + return ageOfNow(parse(birthDay)); + } + + /** + * 生日转为年龄,计算法定年龄 + * + * @param birthDay 生日 + * @return 年龄 + * @throws Exception + */ + public static int ageOfNow(Date birthDay) { + return age(birthDay, date()); + } + + /** + * 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄 + * + * @param birthDay 生日 + * @param dateToCompare 需要对比的日期 + * @return 年龄 + * @throws Exception + */ + public static int age(Date birthDay, Date dateToCompare) { + Calendar cal = Calendar.getInstance(); + cal.setTime(dateToCompare); + + if (cal.before(birthDay)) { + throw new IllegalArgumentException(StrKit.format("Birthday is after date {}!", formatDate(dateToCompare))); + } + + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH); + int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); + + cal.setTime(birthDay); + int age = year - cal.get(Calendar.YEAR); + + int monthBirth = cal.get(Calendar.MONTH); + if (month == monthBirth) { + int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); + if (dayOfMonth < dayOfMonthBirth) { + //如果生日在当月,但是未达到生日当天的日期,年龄减一 + age--; + } + } else if (month < monthBirth) { + //如果当前月份未达到生日的月份,年龄计算减一 + age--; + } + + return age; + } + + /** + * 计时器<br> + * 计算某个过程话费的时间,精确到毫秒 + * + * @author Looly + */ + public static class Timer { + private long time; + private boolean isNano; + + public Timer() { + this(false); + } + + public Timer(boolean isNano) { + this.isNano = isNano; + start(); + } + + /** + * @return 开始计时并返回当前时间 + */ + public long start() { + time = current(isNano); + return time; + } + + /** + * @return 重新计时并返回从开始到当前的持续时间 + */ + public long durationRestart() { + long now = current(isNano); + long d = now - time; + time = now; + return d; + } + + /** + * @return 从开始到当前的持续时间 + */ + public long duration() { + return current(isNano) - time; + } + } + + // ------------------------------------------------------------------------ Private method start + + /** + * 获得指定日期年份和季节<br> + * 格式:[20131]表示2013年第一季度 + * + * @param cal 日期 + */ + private static String yearAndSeason(Calendar cal) { + return new StringBuilder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString(); + } + // ------------------------------------------------------------------------ Private method end +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HexKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HexKit.java new file mode 100644 index 0000000..419714c --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HexKit.java @@ -0,0 +1,259 @@ +package com.ruoyi.order.util.support; + +import java.nio.charset.Charset; + +/** + * 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br> + * 例如十进制数57,在二进制写作111001,在16进制写作39。<br> + * 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br> + * <p> + * 参考:https://my.oschina.net/xinxingegeya/blog/287476 + * + * @author Looly + */ +public class HexKit { + + /** + * 用于建立十六进制字符的输出的小写字符数组 + */ + private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + /** + * 用于建立十六进制字符的输出的大写字符数组 + */ + private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + //---------------------------------------------------------------------------------------------------- encode + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @return 十六进制char[] + */ + public static char[] encodeHex(byte[] data) { + return encodeHex(data, true); + } + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param str 字符串 + * @param charset 编码 + * @return 十六进制char[] + */ + public static char[] encodeHex(String str, Charset charset) { + return encodeHex(StrKit.getBytes(str, charset), true); + } + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 + * @return 十六进制char[] + */ + public static char[] encodeHex(byte[] data, boolean toLowerCase) { + return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @return 十六进制String + */ + public static String encodeHexStr(byte[] data) { + return encodeHexStr(data, true); + } + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式 + * @return 十六进制String + */ + public static String encodeHexStr(byte[] data, boolean toLowerCase) { + return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); + } + + //---------------------------------------------------------------------------------------------------- decode + + /** + * 将十六进制字符数组转换为字符串 + * + * @param hexStr 十六进制String + * @param charset 编码 + * @return 字符串 + */ + public static String decodeHexStr(String hexStr, Charset charset) { + if (StrKit.isEmpty(hexStr)) { + return hexStr; + } + return decodeHexStr(hexStr.toCharArray(), charset); + } + + /** + * 将十六进制字符数组转换为字符串 + * + * @param hexData 十六进制char[] + * @param charset 编码 + * @return 字符串 + */ + public static String decodeHexStr(char[] hexData, Charset charset) { + return StrKit.str(decodeHex(hexData), charset); + } + + /** + * 将十六进制字符数组转换为字节数组 + * + * @param hexData 十六进制char[] + * @return byte[] + * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常 + */ + public static byte[] decodeHex(char[] hexData) { + + int len = hexData.length; + + if ((len & 0x01) != 0) { + throw new RuntimeException("Odd number of characters."); + } + + byte[] out = new byte[len >> 1]; + + // two characters form the hex value. + for (int i = 0, j = 0; j < len; i++) { + int f = toDigit(hexData[j], j) << 4; + j++; + f = f | toDigit(hexData[j], j); + j++; + out[i] = (byte) (f & 0xFF); + } + + return out; + } + + //---------------------------------------------------------------------------------------- Private method start + + /** + * 将字节数组转换为十六进制字符串 + * + * @param data byte[] + * @param toDigits 用于控制输出的char[] + * @return 十六进制String + */ + private static String encodeHexStr(byte[] data, char[] toDigits) { + return new String(encodeHex(data, toDigits)); + } + + /** + * 将字节数组转换为十六进制字符数组 + * + * @param data byte[] + * @param toDigits 用于控制输出的char[] + * @return 十六进制char[] + */ + private static char[] encodeHex(byte[] data, char[] toDigits) { + int l = data.length; + char[] out = new char[l << 1]; + // two characters form the hex value. + for (int i = 0, j = 0; i < l; i++) { + out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; + out[j++] = toDigits[0x0F & data[i]]; + } + return out; + } + + /** + * 将十六进制字符转换成一个整数 + * + * @param ch 十六进制char + * @param index 十六进制字符在字符数组中的位置 + * @return 一个整数 + * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常 + */ + private static int toDigit(char ch, int index) { + int digit = Character.digit(ch, 16); + if (digit == -1) { + throw new RuntimeException("Illegal hexadecimal character " + ch + " at index " + index); + } + return digit; + } + //---------------------------------------------------------------------------------------- Private method end + + + /** + * 2进制转16进制 + * + * @param bString 2进制字符串 + * @return + */ + public static String binary2Hex(String bString) { + if (bString == null || bString.equals("") || bString.length() % 8 != 0) + return null; + StringBuffer tmp = new StringBuffer(); + int iTmp = 0; + for (int i = 0; i < bString.length(); i += 4) { + iTmp = 0; + for (int j = 0; j < 4; j++) { + iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1); + } + tmp.append(Integer.toHexString(iTmp)); + } + return tmp.toString(); + } + + /** + * 16进制转2进制 + * + * @param hexString + * @return + */ + public static String hex2Binary(String hexString) { + if (hexString == null || hexString.length() % 2 != 0) + return null; + String bString = "", tmp; + for (int i = 0; i < hexString.length(); i++) { + tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16)); + bString += tmp.substring(tmp.length() - 4); + } + return bString; + } + + /** + * 将二进制转换成16进制 + * + * @param buf + * @return + */ + public static String binary2Hex(byte buf[]) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < buf.length; i++) { + String hex = Integer.toHexString(buf[i] & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + sb.append(hex.toUpperCase()); + } + return sb.toString(); + } + + /** + * 将16进制转换为二进制 + * + * @param hexStr + * @return + */ + public static byte[] hex2Byte(String hexStr) { + if (hexStr.length() < 1) + return null; + byte[] result = new byte[hexStr.length() / 2]; + for (int i = 0; i < hexStr.length() / 2; i++) { + int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); + int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); + result[i] = (byte) (high * 16 + low); + } + return result; + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HttpKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HttpKit.java new file mode 100644 index 0000000..a774559 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/HttpKit.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com). + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruoyi.order.util.support; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HttpKit { + + public static String getIp() { + return HttpKit.getRequest().getRemoteHost(); + } + + /** + * 获取所有请求的值 + */ + public static Map<String, String> getRequestParameters() { + HashMap<String, String> values = new HashMap<>(); + HttpServletRequest request = HttpKit.getRequest(); + Enumeration enums = request.getParameterNames(); + while (enums.hasMoreElements()) { + String paramName = (String) enums.nextElement(); + String paramValue = request.getParameter(paramName); + values.put(paramName, paramValue); + } + return values; + } + + /** + * 获取 HttpServletRequest + */ + public static HttpServletResponse getResponse() { + HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); + return response; + } + + /** + * 获取 包装防Xss Sql注入的 HttpServletRequest + * + * @return request + */ + public static HttpServletRequest getRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + return new WafRequestWrapper(request); + } + + /** + * 向指定URL发送GET方法的请求 + * + * @param url 发送请求的URL + * @param param 请求参数 + * @return URL 所代表远程资源的响应结果 + */ + public static String sendGet(String url, Map<String, String> param) { + String result = ""; + BufferedReader in = null; + try { + StringBuffer query = new StringBuffer(); + + for (Map.Entry<String, String> kv : param.entrySet()) { + query.append(URLEncoder.encode(kv.getKey(), "UTF-8") + "="); + query.append(URLEncoder.encode(kv.getValue(), "UTF-8") + "&"); + } + if (query.lastIndexOf("&") > 0) { + query.deleteCharAt(query.length() - 1); + } + + String urlNameString = url + "?" + query.toString(); + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + URLConnection connection = realUrl.openConnection(); + // 设置通用的请求属性 + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 建立实际的连接 + connection.connect(); + // 获取所有响应头字段 + Map<String, List<String>> map = connection.getHeaderFields(); + // 遍历所有的响应头字段 + for (String key : map.keySet()) { + System.out.println(key + "--->" + map.get(key)); + } + // 定义 BufferedReader输入流来读取URL的响应 + in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + } catch (Exception e) { + System.out.println("发送GET请求出现异常!" + e); + e.printStackTrace(); + } + // 使用finally块来关闭输入流 + finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception e2) { + e2.printStackTrace(); + } + } + return result; + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, Map<String, String> param) { + PrintWriter out = null; + BufferedReader in = null; + String result = ""; + try { + String para = ""; + for (String key : param.keySet()) { + para += (key + "=" + param.get(key) + "&"); + } + if (para.lastIndexOf("&") > 0) { + para = para.substring(0, para.length() - 1); + } + String urlNameString = url + "?" + para; + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + URLConnection conn = realUrl.openConnection(); + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + // 发送请求参数 + out.print(param); + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + } catch (Exception e) { + System.out.println("发送 POST 请求出现异常!" + e); + e.printStackTrace(); + } + // 使用finally块来关闭输出流、输入流 + finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return result; + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/ObjectKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/ObjectKit.java new file mode 100644 index 0000000..bef23de --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/ObjectKit.java @@ -0,0 +1,21 @@ +package com.ruoyi.order.util.support; + +/** + * 一些通用的函数 + * + * @author Looly + */ +public class ObjectKit { + /** + * 比较两个对象是否相等。<br> + * 相同的条件有两个,满足其一即可:<br> + * 1. obj1 == null && obj2 == null; 2. obj1.equals(obj2) + * + * @param obj1 对象1 + * @param obj2 对象2 + * @return 是否相等 + */ + public static boolean equals(Object obj1, Object obj2) { + return (obj1 != null) ? (obj1.equals(obj2)) : (obj2 == null); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/PageKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/PageKit.java new file mode 100644 index 0000000..74ca344 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/PageKit.java @@ -0,0 +1,52 @@ +package com.ruoyi.order.util.support; + +/** + * 分页工具类 + * + * @author xiaoleilu + */ +public class PageKit { + + /** + * 将页数和每页条目数转换为开始位置和结束位置<br> + * 此方法用于不包括结束位置的分页方法<br> + * 例如:<br> + * 页码:1,每页10 -> [0, 10]<br> + * 页码:2,每页10 -> [10, 20]<br> + * 。。。<br> + * + * @param pageNo 页码(从1计数) + * @param countPerPage 每页条目数 + * @return 第一个数为开始位置,第二个数为结束位置 + */ + public static int[] transToStartEnd(int pageNo, int countPerPage) { + if (pageNo < 1) { + pageNo = 1; + } + + if (countPerPage < 1) { + countPerPage = 0; +// LogKit.warn("Count per page [" + countPerPage + "] is not valid!"); + } + + int start = (pageNo - 1) * countPerPage; + int end = start + countPerPage; + + return new int[]{start, end}; + } + + /** + * 根据总数计算总页数 + * + * @param totalCount 总数 + * @param numPerPage 每页数 + * @return 总页数 + */ + public static int totalPage(int totalCount, int numPerPage) { + if (numPerPage == 0) { + return 0; + } + return totalCount % numPerPage == 0 ? (totalCount / numPerPage) + : (totalCount / numPerPage + 1); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/StrKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/StrKit.java new file mode 100644 index 0000000..2a7e95e --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/StrKit.java @@ -0,0 +1,1374 @@ +package com.ruoyi.order.util.support; + +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * 字符串工具类 + * + * @author xiaoleilu + */ +public class StrKit { + + public static final String SPACE = " "; + public static final String DOT = "."; + public static final String SLASH = "/"; + public static final String BACKSLASH = "\\"; + public static final String EMPTY = ""; + public static final String CRLF = "\r\n"; + public static final String NEWLINE = "\n"; + public static final String UNDERLINE = "_"; + public static final String COMMA = ","; + + public static final String HTML_NBSP = " "; + public static final String HTML_AMP = "&"; + public static final String HTML_QUOTE = """; + public static final String HTML_LT = "<"; + public static final String HTML_GT = ">"; + + public static final String EMPTY_JSON = "{}"; + + + /** + * 首字母变小写 + */ + public static String firstCharToLowerCase(String str) { + char firstChar = str.charAt(0); + if (firstChar >= 'A' && firstChar <= 'Z') { + char[] arr = str.toCharArray(); + arr[0] += ('a' - 'A'); + return new String(arr); + } + return str; + } + + /** + * 首字母变大写 + */ + public static String firstCharToUpperCase(String str) { + char firstChar = str.charAt(0); + if (firstChar >= 'a' && firstChar <= 'z') { + char[] arr = str.toCharArray(); + arr[0] -= ('a' - 'A'); + return new String(arr); + } + return str; + } + + // ------------------------------------------------------------------------ Blank + + /** + * 字符串是否为空白 空白的定义如下: <br> + * 1、为null <br> + * 2、为不可见字符(如空格)<br> + * 3、""<br> + * + * @param str 被检测的字符串 + * @return 是否为空 + */ + public static boolean isBlank(String str) { + int length; + if ((str == null) || ((length = str.length()) == 0)) { + return true; + } + for (int i = 0; i < length; i++) { + // 只要有一个非空字符即为非空字符串 + if (false == Character.isWhitespace(str.charAt(i))) { + return false; + } + } + return true; + } + + /** + * 字符串是否为非空白 空白的定义如下: <br> + * 1、不为null <br> + * 2、不为不可见字符(如空格)<br> + * 3、不为""<br> + * + * @param str 被检测的字符串 + * @return 是否为非空 + */ + public static boolean notBlank(String str) { + return false == isBlank(str); + } + + /** + * 是否包含空字符串 + * + * @param strs 字符串列表 + * @return 是否包含空字符串 + */ + public static boolean hasBlank(String... strs) { + if (CollectionKit.isEmpty(strs)) { + return true; + } + for (String str : strs) { + if (isBlank(str)) { + return true; + } + } + return false; + } + + /** + * 给定所有字符串是否为空白 + * + * @param strs 字符串 + * @return 所有字符串是否为空白 + */ + public static boolean isAllBlank(String... strs) { + if (CollectionKit.isEmpty(strs)) { + return true; + } + for (String str : strs) { + if (notBlank(str)) { + return false; + } + } + return true; + } + + // ------------------------------------------------------------------------ Empty + + /** + * 字符串是否为空,空的定义如下 1、为null <br> + * 2、为""<br> + * + * @param str 被检测的字符串 + * @return 是否为空 + */ + public static boolean isEmpty(String str) { + return str == null || str.length() == 0; + } + + /** + * 字符串是否为非空白 空白的定义如下: <br> + * 1、不为null <br> + * 2、不为""<br> + * + * @param str 被检测的字符串 + * @return 是否为非空 + */ + public static boolean isNotEmpty(String str) { + return false == isEmpty(str); + } + + /** + * 当给定字符串为null时,转换为Empty + * + * @param str 被转换的字符串 + * @return 转换后的字符串 + */ + public static String nullToEmpty(String str) { + return nullToDefault(str, EMPTY); + } + + /** + * 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。 + * + * <pre> + * nullToDefault(null, "default") = "default" + * nullToDefault("", "default") = "" + * nullToDefault(" ", "default") = " " + * nullToDefault("bat", "default") = "bat" + * </pre> + * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * @return 字符串本身或指定的默认字符串 + */ + public static String nullToDefault(String str, String defaultStr) { + return (str == null) ? defaultStr : str; + } + + /** + * 当给定字符串为空字符串时,转换为<code>null</code> + * + * @param str 被转换的字符串 + * @return 转换后的字符串 + */ + public static String emptyToNull(String str) { + return isEmpty(str) ? null : str; + } + + /** + * 是否包含空字符串 + * + * @param strs 字符串列表 + * @return 是否包含空字符串 + */ + public static boolean hasEmpty(String... strs) { + if (CollectionKit.isEmpty(strs)) { + return true; + } + + for (String str : strs) { + if (isEmpty(str)) { + return true; + } + } + return false; + } + + /** + * 是否全部为空字符串 + * + * @param strs 字符串列表 + * @return 是否全部为空字符串 + */ + public static boolean isAllEmpty(String... strs) { + if (CollectionKit.isEmpty(strs)) { + return true; + } + + for (String str : strs) { + if (isNotEmpty(str)) { + return false; + } + } + return true; + } + + // ------------------------------------------------------------------------ Trim + + /** + * 除去字符串头尾部的空白,如果字符串是<code>null</code>,依然返回<code>null</code>。 + * + * <p> + * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + * <pre> + * trim(null) = null + * trim("") = "" + * trim(" ") = "" + * trim("abc") = "abc" + * trim(" abc ") = "abc" + * </pre> + * + * </p> + * + * @param str 要处理的字符串 + * @return 除去空白的字符串,如果原字串为<code>null</code>,则返回<code>null</code> + */ + public static String trim(String str) { + return (null == str) ? null : trim(str, 0); + } + + /** + * 给定字符串数组全部做去首尾空格 + * + * @param strs 字符串数组 + */ + public static void trim(String[] strs) { + if (null == strs) { + return; + } + String str; + for (int i = 0; i < strs.length; i++) { + str = strs[i]; + if (null != str) { + strs[i] = str.trim(); + } + } + } + + /** + * 除去字符串头部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。 + * + * <p> + * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + * <pre> + * trimStart(null) = null + * trimStart("") = "" + * trimStart("abc") = "abc" + * trimStart(" abc") = "abc" + * trimStart("abc ") = "abc " + * trimStart(" abc ") = "abc " + * </pre> + * + * </p> + * + * @param str 要处理的字符串 + * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回 <code>null</code> + */ + public static String trimStart(String str) { + return trim(str, -1); + } + + /** + * 除去字符串尾部的空白,如果字符串是<code>null</code>,则返回<code>null</code>。 + * + * <p> + * 注意,和<code>String.trim</code>不同,此方法使用<code>Character.isWhitespace</code> 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + * <pre> + * trimEnd(null) = null + * trimEnd("") = "" + * trimEnd("abc") = "abc" + * trimEnd(" abc") = " abc" + * trimEnd("abc ") = "abc" + * trimEnd(" abc ") = " abc" + * </pre> + * + * </p> + * + * @param str 要处理的字符串 + * @return 除去空白的字符串,如果原字串为<code>null</code>或结果字符串为<code>""</code>,则返回 <code>null</code> + */ + public static String trimEnd(String str) { + return trim(str, 1); + } + + /** + * 除去字符串头尾部的空白符,如果字符串是<code>null</code>,依然返回<code>null</code>。 + * + * @param str 要处理的字符串 + * @param mode <code>-1</code>表示trimStart,<code>0</code>表示trim全部, <code>1</code>表示trimEnd + * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> + */ + public static String trim(String str, int mode) { + if (str == null) { + return null; + } + + int length = str.length(); + int start = 0; + int end = length; + + // 扫描字符串头部 + if (mode <= 0) { + while ((start < end) && (Character.isWhitespace(str.charAt(start)))) { + start++; + } + } + + // 扫描字符串尾部 + if (mode >= 0) { + while ((start < end) && (Character.isWhitespace(str.charAt(end - 1)))) { + end--; + } + } + + if ((start > 0) || (end < length)) { + return str.substring(start, end); + } + + return str; + } + + /** + * 是否以指定字符串开头 + * + * @param str 被监测字符串 + * @param prefix 开头字符串 + * @param isIgnoreCase 是否忽略大小写 + * @return 是否以指定字符串开头 + */ + public static boolean startWith(String str, String prefix, boolean isIgnoreCase) { + if (isIgnoreCase) { + return str.toLowerCase().startsWith(prefix.toLowerCase()); + } else { + return str.startsWith(prefix); + } + } + + /** + * 是否以指定字符串结尾 + * + * @param str 被监测字符串 + * @param suffix 结尾字符串 + * @param isIgnoreCase 是否忽略大小写 + * @return 是否以指定字符串结尾 + */ + public static boolean endWith(String str, String suffix, boolean isIgnoreCase) { + if (isIgnoreCase) { + return str.toLowerCase().endsWith(suffix.toLowerCase()); + } else { + return str.endsWith(suffix); + } + } + + /** + * 是否包含特定字符,忽略大小写,如果给定两个参数都为<code>null</code>,返回true + * + * @param str 被检测字符串 + * @param testStr 被测试是否包含的字符串 + * @return 是否包含 + */ + public static boolean containsIgnoreCase(String str, String testStr) { + if (null == str) { + //如果被监测字符串和 + return null == testStr; + } + return str.toLowerCase().contains(testStr.toLowerCase()); + } + + /** + * 获得set或get方法对应的标准属性名<br/> + * 例如:setName 返回 name + * + * @param getOrSetMethodName + * @return 如果是set或get方法名,返回field, 否则null + */ + public static String getGeneralField(String getOrSetMethodName) { + if (getOrSetMethodName.startsWith("get") || getOrSetMethodName.startsWith("set")) { + return cutPreAndLowerFirst(getOrSetMethodName, 3); + } + return null; + } + + /** + * 生成set方法名<br/> + * 例如:name 返回 setName + * + * @param fieldName 属性名 + * @return setXxx + */ + public static String genSetter(String fieldName) { + return upperFirstAndAddPre(fieldName, "set"); + } + + /** + * 生成get方法名 + * + * @param fieldName 属性名 + * @return getXxx + */ + public static String genGetter(String fieldName) { + return upperFirstAndAddPre(fieldName, "get"); + } + + /** + * 去掉首部指定长度的字符串并将剩余字符串首字母小写<br/> + * 例如:str=setName, preLength=3 -> return name + * + * @param str 被处理的字符串 + * @param preLength 去掉的长度 + * @return 处理后的字符串,不符合规范返回null + */ + public static String cutPreAndLowerFirst(String str, int preLength) { + if (str == null) { + return null; + } + if (str.length() > preLength) { + char first = Character.toLowerCase(str.charAt(preLength)); + if (str.length() > preLength + 1) { + return first + str.substring(preLength + 1); + } + return String.valueOf(first); + } + return null; + } + + /** + * 原字符串首字母大写并在其首部添加指定字符串 例如:str=name, preString=get -> return getName + * + * @param str 被处理的字符串 + * @param preString 添加的首部 + * @return 处理后的字符串 + */ + public static String upperFirstAndAddPre(String str, String preString) { + if (str == null || preString == null) { + return null; + } + return preString + upperFirst(str); + } + + /** + * 大写首字母<br> + * 例如:str = name, return Name + * + * @param str 字符串 + * @return 字符串 + */ + public static String upperFirst(String str) { + return Character.toUpperCase(str.charAt(0)) + str.substring(1); + } + + /** + * 小写首字母<br> + * 例如:str = Name, return name + * + * @param str 字符串 + * @return 字符串 + */ + public static String lowerFirst(String str) { + if (isBlank(str)) { + return str; + } + return Character.toLowerCase(str.charAt(0)) + str.substring(1); + } + + /** + * 去掉指定前缀 + * + * @param str 字符串 + * @param prefix 前缀 + * @return 切掉后的字符串,若前缀不是 preffix, 返回原字符串 + */ + public static String removePrefix(String str, String prefix) { + if (isEmpty(str) || isEmpty(prefix)) { + return str; + } + + if (str.startsWith(prefix)) { + return str.substring(prefix.length()); + } + return str; + } + + /** + * 忽略大小写去掉指定前缀 + * + * @param str 字符串 + * @param prefix 前缀 + * @return 切掉后的字符串,若前缀不是 prefix, 返回原字符串 + */ + public static String removePrefixIgnoreCase(String str, String prefix) { + if (isEmpty(str) || isEmpty(prefix)) { + return str; + } + + if (str.toLowerCase().startsWith(prefix.toLowerCase())) { + return str.substring(prefix.length()); + } + return str; + } + + /** + * 去掉指定后缀 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串 + */ + public static String removeSuffix(String str, String suffix) { + if (isEmpty(str) || isEmpty(suffix)) { + return str; + } + + if (str.endsWith(suffix)) { + return str.substring(0, str.length() - suffix.length()); + } + return str; + } + + /** + * 获得字符串对应byte数组 + * + * @param str 字符串 + * @param charset 编码,如果为<code>null</code>使用系统默认编码 + * @return bytes + */ + public static byte[] getBytes(String str, Charset charset) { + if (null == str) { + return null; + } + return null == charset ? str.getBytes() : str.getBytes(charset); + } + + /** + * 忽略大小写去掉指定后缀 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串 + */ + public static String removeSuffixIgnoreCase(String str, String suffix) { + if (isEmpty(str) || isEmpty(suffix)) { + return str; + } + + if (str.toLowerCase().endsWith(suffix.toLowerCase())) { + return str.substring(0, str.length() - suffix.length()); + } + return str; + } + + /** + * 如果给定字符串不是以prefix开头的,在开头补充 prefix + * + * @param str 字符串 + * @param prefix 前缀 + * @return 补充后的字符串 + */ + public static String addPrefixIfNot(String str, String prefix) { + if (isEmpty(str) || isEmpty(prefix)) { + return str; + } + if (false == str.startsWith(prefix)) { + str = prefix + str; + } + return str; + } + + /** + * 如果给定字符串不是以suffix结尾的,在尾部补充 suffix + * + * @param str 字符串 + * @param suffix 后缀 + * @return 补充后的字符串 + */ + public static String addSuffixIfNot(String str, String suffix) { + if (isEmpty(str) || isEmpty(suffix)) { + return str; + } + if (false == str.endsWith(suffix)) { + str += suffix; + } + return str; + } + + /** + * 清理空白字符 + * + * @param str 被清理的字符串 + * @return 清理后的字符串 + */ + public static String cleanBlank(String str) { + if (str == null) { + return null; + } + + return str.replaceAll("\\s*", EMPTY); + } + + /** + * 切分字符串<br> + * a#b#c -> [a,b,c] <br> + * a##b#c -> [a,"",b,c] + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @return 切分后的集合 + */ + public static List<String> split(String str, char separator) { + return split(str, separator, 0); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数 + * @return 切分后的集合 + */ + public static List<String> split(String str, char separator, int limit) { + if (str == null) { + return null; + } + List<String> list = new ArrayList<String>(limit == 0 ? 16 : limit); + if (limit == 1) { + list.add(str); + return list; + } + + boolean isNotEnd = true; // 未结束切分的标志 + int strLen = str.length(); + StringBuilder sb = new StringBuilder(strLen); + for (int i = 0; i < strLen; i++) { + char c = str.charAt(i); + if (isNotEnd && c == separator) { + list.add(sb.toString()); + // 清空StringBuilder + sb.delete(0, sb.length()); + + // 当达到切分上限-1的量时,将所剩字符全部作为最后一个串 + if (limit != 0 && list.size() == limit - 1) { + isNotEnd = false; + } + } else { + sb.append(c); + } + } + list.add(sb.toString());// 加入尾串 + return list; + } + + /** + * 切分字符串<br> + * from jodd + * + * @param str 被切分的字符串 + * @param delimiter 分隔符 + * @return 字符串 + */ + public static String[] split(String str, String delimiter) { + if (str == null) { + return null; + } + if (str.trim().length() == 0) { + return new String[]{str}; + } + + int dellen = delimiter.length(); // del length + int maxparts = (str.length() / dellen) + 2; // one more for the last + int[] positions = new int[maxparts]; + + int i, j = 0; + int count = 0; + positions[0] = -dellen; + while ((i = str.indexOf(delimiter, j)) != -1) { + count++; + positions[count] = i; + j = i + dellen; + } + count++; + positions[count] = str.length(); + + String[] result = new String[count]; + + for (i = 0; i < count; i++) { + result[i] = str.substring(positions[i] + dellen, positions[i + 1]); + } + return result; + } + + /** + * 改进JDK subString<br> + * index从0开始计算,最后一个字符为-1<br> + * 如果from和to位置一样,返回 "" <br> + * 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br> + * 如果经过修正的index中from大于to,则互换from和to + * example: <br> + * abcdefgh 2 3 -> c <br> + * abcdefgh 2 -3 -> cde <br> + * + * @param string String + * @param fromIndex 开始的index(包括) + * @param toIndex 结束的index(不包括) + * @return 字串 + */ + public static String sub(String string, int fromIndex, int toIndex) { + int len = string.length(); + if (fromIndex < 0) { + fromIndex = len + fromIndex; + if (fromIndex < 0) { + fromIndex = 0; + } + } else if (fromIndex >= len) { + fromIndex = len - 1; + } + if (toIndex < 0) { + toIndex = len + toIndex; + if (toIndex < 0) { + toIndex = len; + } + } else if (toIndex > len) { + toIndex = len; + } + if (toIndex < fromIndex) { + int tmp = fromIndex; + fromIndex = toIndex; + toIndex = tmp; + } + if (fromIndex == toIndex) { + return EMPTY; + } + char[] strArray = string.toCharArray(); + char[] newStrArray = Arrays.copyOfRange(strArray, fromIndex, toIndex); + return new String(newStrArray); + } + + /** + * 切割前部分 + * + * @param string 字符串 + * @param toIndex 切割到的位置(不包括) + * @return 切割后的字符串 + */ + public static String subPre(String string, int toIndex) { + return sub(string, 0, toIndex); + } + + /** + * 切割后部分 + * + * @param string 字符串 + * @param fromIndex 切割开始的位置(包括) + * @return 切割后的字符串 + */ + public static String subSuf(String string, int fromIndex) { + if (isEmpty(string)) { + return null; + } + return sub(string, fromIndex, string.length()); + } + + /** + * 给定字符串是否被字符包围 + * + * @param str 字符串 + * @param prefix 前缀 + * @param suffix 后缀 + * @return 是否包围,空串不包围 + */ + public static boolean isSurround(String str, String prefix, String suffix) { + if (StrKit.isBlank(str)) { + return false; + } + if (str.length() < (prefix.length() + suffix.length())) { + return false; + } + + return str.startsWith(prefix) && str.endsWith(suffix); + } + + /** + * 给定字符串是否被字符包围 + * + * @param str 字符串 + * @param prefix 前缀 + * @param suffix 后缀 + * @return 是否包围,空串不包围 + */ + public static boolean isSurround(String str, char prefix, char suffix) { + if (StrKit.isBlank(str)) { + return false; + } + if (str.length() < 2) { + return false; + } + + return str.charAt(0) == prefix && str.charAt(str.length() - 1) == suffix; + } + + /** + * 重复某个字符 + * + * @param c 被重复的字符 + * @param count 重复的数目 + * @return 重复字符字符串 + */ + public static String repeat(char c, int count) { + char[] result = new char[count]; + for (int i = 0; i < count; i++) { + result[i] = c; + } + return new String(result); + } + + /** + * 重复某个字符串 + * + * @param str 被重复的字符 + * @param count 重复的数目 + * @return 重复字符字符串 + */ + public static String repeat(String str, int count) { + + // 检查 + final int len = str.length(); + final long longSize = (long) len * (long) count; + final int size = (int) longSize; + if (size != longSize) { + throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize); + } + + final char[] array = new char[size]; + str.getChars(0, len, array, 0); + int n; + for (n = len; n < size - n; n <<= 1) {// n <<= 1相当于n *2 + System.arraycopy(array, 0, array, n, n); + } + System.arraycopy(array, 0, array, n, size - n); + return new String(array); + } + + /** + * 比较两个字符串(大小写敏感)。 + * + * <pre> + * equals(null, null) = true + * equals(null, "abc") = false + * equals("abc", null) = false + * equals("abc", "abc") = true + * equals("abc", "ABC") = false + * </pre> + * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> + */ + public static boolean equals(String str1, String str2) { + if (str1 == null) { + return str2 == null; + } + + return str1.equals(str2); + } + + /** + * 比较两个字符串(大小写不敏感)。 + * + * <pre> + * equalsIgnoreCase(null, null) = true + * equalsIgnoreCase(null, "abc") = false + * equalsIgnoreCase("abc", null) = false + * equalsIgnoreCase("abc", "abc") = true + * equalsIgnoreCase("abc", "ABC") = true + * </pre> + * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同,或者都是<code>null</code>,则返回<code>true</code> + */ + public static boolean equalsIgnoreCase(String str1, String str2) { + if (str1 == null) { + return str2 == null; + } + + return str1.equalsIgnoreCase(str2); + } + + /** + * 格式化文本, {} 表示占位符<br> + * 例如:format("aaa {} ccc", "bbb") ----> aaa bbb ccc + * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param values 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... values) { + if (CollectionKit.isEmpty(values) || isBlank(template)) { + return template; + } + + final StringBuilder sb = new StringBuilder(); + final int length = template.length(); + + int valueIndex = 0; + char currentChar; + for (int i = 0; i < length; i++) { + if (valueIndex >= values.length) { + sb.append(sub(template, i, length)); + break; + } + + currentChar = template.charAt(i); + if (currentChar == '{') { + final char nextChar = template.charAt(++i); + if (nextChar == '}') { + sb.append(values[valueIndex++]); + } else { + sb.append('{').append(nextChar); + } + } else { + sb.append(currentChar); + } + + } + + return sb.toString(); + } + + /** + * 格式化文本,使用 {varName} 占位<br> + * map = {a: "aValue", b: "bValue"} + * format("{a} and {b}", map) ----> aValue and bValue + * + * @param template 文本模板,被替换的部分用 {key} 表示 + * @param map 参数值对 + * @return 格式化后的文本 + */ + public static String format(String template, Map<?, ?> map) { + if (null == map || map.isEmpty()) { + return template; + } + + for (Entry<?, ?> entry : map.entrySet()) { + template = template.replace("{" + entry.getKey() + "}", entry.getValue().toString()); + } + return template; + } + + /** + * 编码字符串 + * + * @param str 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 编码后的字节码 + */ + public static byte[] bytes(String str, String charset) { + return bytes(str, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 编码字符串 + * + * @param str 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 编码后的字节码 + */ + public static byte[] bytes(String str, Charset charset) { + if (str == null) { + return null; + } + + if (null == charset) { + return str.getBytes(); + } + return str.getBytes(charset); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) { + return str(bytes, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) { + if (data == null) { + return null; + } + + if (null == charset) { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) { + if (data == null) { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) { + if (null == charset) { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + /** + * 字符串转换为byteBuffer + * + * @param str 字符串 + * @param charset 编码 + * @return byteBuffer + */ + public static ByteBuffer byteBuffer(String str, String charset) { + return ByteBuffer.wrap(StrKit.bytes(str, charset)); + } + + /** + * 以 conjunction 为分隔符将多个对象转换为字符串 + * + * @param conjunction 分隔符 + * @param objs 数组 + * @return 连接后的字符串 + */ + public static String join(String conjunction, Object... objs) { + StringBuilder sb = new StringBuilder(); + boolean isFirst = true; + for (Object item : objs) { + if (isFirst) { + isFirst = false; + } else { + sb.append(conjunction); + } + sb.append(item); + } + return sb.toString(); + } + + /** + * 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br> + * 例如:HelloWorld->hello_world + * + * @param camelCaseStr 转换前的驼峰式命名的字符串 + * @return 转换后下划线大写方式命名的字符串 + */ + public static String toUnderlineCase(String camelCaseStr) { + if (camelCaseStr == null) { + return null; + } + + final int length = camelCaseStr.length(); + StringBuilder sb = new StringBuilder(); + char c; + boolean isPreUpperCase = false; + for (int i = 0; i < length; i++) { + c = camelCaseStr.charAt(i); + boolean isNextUpperCase = true; + if (i < (length - 1)) { + isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1)); + } + if (Character.isUpperCase(c)) { + if (!isPreUpperCase || !isNextUpperCase) { + if (i > 0) sb.append(UNDERLINE); + } + isPreUpperCase = true; + } else { + isPreUpperCase = false; + } + sb.append(Character.toLowerCase(c)); + } + return sb.toString(); + } + + /** + * 将下划线方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br> + * 例如:hello_world->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String toCamelCase(String name) { + if (name == null) { + return null; + } + if (name.contains(UNDERLINE)) { + name = name.toLowerCase(); + + StringBuilder sb = new StringBuilder(name.length()); + boolean upperCase = false; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + + if (c == '_') { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + return sb.toString(); + } else + return name; + } + + /** + * 包装指定字符串 + * + * @param str 被包装的字符串 + * @param prefix 前缀 + * @param suffix 后缀 + * @return 包装后的字符串 + */ + public static String wrap(String str, String prefix, String suffix) { + return format("{}{}{}", prefix, str, suffix); + } + + /** + * 指定字符串是否被包装 + * + * @param str 字符串 + * @param prefix 前缀 + * @param suffix 后缀 + * @return 是否被包装 + */ + public static boolean isWrap(String str, String prefix, String suffix) { + return str.startsWith(prefix) && str.endsWith(suffix); + } + + /** + * 指定字符串是否被同一字符包装(前后都有这些字符串) + * + * @param str 字符串 + * @param wrapper 包装字符串 + * @return 是否被包装 + */ + public static boolean isWrap(String str, String wrapper) { + return isWrap(str, wrapper, wrapper); + } + + /** + * 指定字符串是否被同一字符包装(前后都有这些字符串) + * + * @param str 字符串 + * @param wrapper 包装字符 + * @return 是否被包装 + */ + public static boolean isWrap(String str, char wrapper) { + return isWrap(str, wrapper, wrapper); + } + + /** + * 指定字符串是否被包装 + * + * @param str 字符串 + * @param prefixChar 前缀 + * @param suffixChar 后缀 + * @return 是否被包装 + */ + public static boolean isWrap(String str, char prefixChar, char suffixChar) { + return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar; + } + + /** + * 补充字符串以满足最小长度 StrUtil.padPre("1", 3, '0');//"001" + * + * @param str 字符串 + * @param minLength 最小长度 + * @param padChar 补充的字符 + * @return 补充后的字符串 + */ + public static String padPre(String str, int minLength, char padChar) { + if (str.length() >= minLength) { + return str; + } + StringBuilder sb = new StringBuilder(minLength); + for (int i = str.length(); i < minLength; i++) { + sb.append(padChar); + } + sb.append(str); + return sb.toString(); + } + + /** + * 补充字符串以满足最小长度 StrUtil.padEnd("1", 3, '0');//"100" + * + * @param str 字符串 + * @param minLength 最小长度 + * @param padChar 补充的字符 + * @return 补充后的字符串 + */ + public static String padEnd(String str, int minLength, char padChar) { + if (str.length() >= minLength) { + return str; + } + StringBuilder sb = new StringBuilder(minLength); + sb.append(str); + for (int i = str.length(); i < minLength; i++) { + sb.append(padChar); + } + return sb.toString(); + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 + */ + public static StringBuilder builder() { + return new StringBuilder(); + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 + */ + public static StringBuilder builder(int capacity) { + return new StringBuilder(capacity); + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 + */ + public static StringBuilder builder(String... strs) { + final StringBuilder sb = new StringBuilder(); + for (String str : strs) { + sb.append(str); + } + return sb; + } + + /** + * 获得StringReader + * + * @param str 字符串 + * @return StringReader + */ + public static StringReader getReader(String str) { + return new StringReader(str); + } + + /** + * 获得StringWriter + * + * @return StringWriter + */ + public static StringWriter getWriter() { + return new StringWriter(); + } + + /** + * 编码字符串 + * + * @param str 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 编码后的字节码 + */ + public static byte[] encode(String str, String charset) { + if (str == null) { + return null; + } + + if (isBlank(charset)) { + return str.getBytes(); + } + try { + return str.getBytes(charset); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(format("Charset [{}] unsupported!", charset)); + } + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String decode(byte[] data, String charset) { + if (data == null) { + return null; + } + + if (isBlank(charset)) { + return new String(data); + } + try { + return new String(data, charset); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(format("Charset [{}] unsupported!", charset)); + } + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafKit.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafKit.java new file mode 100644 index 0000000..7c184b1 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafKit.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2011-2014, hubin (jobob@qq.com). + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruoyi.order.util.support; + +import java.util.regex.Pattern; + +/** + * Web防火墙工具类 + * <p> + * @author hubin + * @Date 2014-5-8 + */ +public class WafKit { + + /** + * @Description 过滤XSS脚本内容 + * @param value + * 待处理内容 + * @return + */ + public static String stripXSS(String value) { + String rlt = null; + + if (null != value) { + // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to + // avoid encoded attacks. + // value = ESAPI.encoder().canonicalize(value); + + // Avoid null characters + rlt = value.replaceAll("", ""); + + // Avoid anything between script tags + Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid anything in a src='...' type of expression + /*scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll("");*/ + + // Remove any lonesome </script> tag + scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Remove any lonesome <script ...> tag + scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid eval(...) expressions + scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid expression(...) expressions + scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid javascript:... expressions + scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid vbscript:... expressions + scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + + // Avoid onload= expressions + scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE + | Pattern.MULTILINE | Pattern.DOTALL); + rlt = scriptPattern.matcher(rlt).replaceAll(""); + } + + return rlt; + } + + /** + * @Description 过滤SQL注入内容 + * @param value + * 待处理内容 + * @return + */ + public static String stripSqlInjection(String value) { + return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)", ""); //value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", ""); + } + + /** + * @Description 过滤SQL/XSS注入内容 + * @param value + * 待处理内容 + * @return + */ + public static String stripSqlXSS(String value) { + return stripXSS(stripSqlInjection(value)); + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafRequestWrapper.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafRequestWrapper.java new file mode 100644 index 0000000..65c877d --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/util/support/WafRequestWrapper.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2011-2014, hubin (jobob@qq.com). + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.ruoyi.order.util.support; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.Map; + +/** + * Request请求过滤包装 + * <p> + * @author hubin + * @Date 2014-5-8 + */ +public class WafRequestWrapper extends HttpServletRequestWrapper { + + private boolean filterXSS = true; + + private boolean filterSQL = true; + + + public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) { + super(request); + this.filterXSS = filterXSS; + this.filterSQL = filterSQL; + } + + + public WafRequestWrapper(HttpServletRequest request) { + this(request, true, true); + } + + + /** + * @Description 数组参数过滤 + * @param parameter + * 过滤参数 + * @return + */ + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = filterParamString(values[i]); + } + + return encodedValues; + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public Map getParameterMap() { + Map<String, String[]> primary = super.getParameterMap(); + Map<String, String[]> result = new HashMap<String, String[]>(primary.size()); + for (Map.Entry<String, String[]> entry : primary.entrySet()) { + result.put(entry.getKey(), filterEntryString(entry.getValue())); + } + return result; + + } + + protected String[] filterEntryString(String[] rawValue) { + for (int i = 0; i < rawValue.length; i++) { + rawValue[i] = filterParamString(rawValue[i]); + } + return rawValue; + } + + /** + * @Description 参数过滤 + * @param parameter + * 过滤参数 + * @return + */ + @Override + public String getParameter(String parameter) { + return filterParamString(super.getParameter(parameter)); + } + + + /** + * @Description 请求头过滤 + * @param name + * 过滤内容 + * @return + */ + @Override + public String getHeader(String name) { + return filterParamString(super.getHeader(name)); + } + + + /** + * @Description Cookie内容过滤 + * @return + */ + @Override + public Cookie[] getCookies() { + Cookie[] existingCookies = super.getCookies(); + if (existingCookies != null) { + for (int i = 0; i < existingCookies.length; ++i) { + Cookie cookie = existingCookies[i]; + cookie.setValue(filterParamString(cookie.getValue())); + } + } + return existingCookies; + } + + /** + * @Description 过滤字符串内容 + * @param rawValue + * 待处理内容 + * @return + */ + protected String filterParamString(String rawValue) { + if (null == rawValue) { + return null; + } + String tmpStr = rawValue; + if (this.filterXSS) { + tmpStr = WafKit.stripXSS(rawValue); + } + if (this.filterSQL) { + tmpStr = WafKit.stripSqlInjection(tmpStr); + } + return tmpStr; + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/vo/KuaiDiCode.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/vo/KuaiDiCode.java new file mode 100644 index 0000000..c038167 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/vo/KuaiDiCode.java @@ -0,0 +1,14 @@ +package com.ruoyi.order.vo; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class KuaiDiCode { + private String comCode; + private String id; + private Integer noCount; + private String noPre; + private LocalDateTime startTime; +} diff --git a/ruoyi-modules/ruoyi-order/src/main/resources/conf/param.properties b/ruoyi-modules/ruoyi-order/src/main/resources/conf/param.properties index 6a728d8..a9677e0 100644 --- a/ruoyi-modules/ruoyi-order/src/main/resources/conf/param.properties +++ b/ruoyi-modules/ruoyi-order/src/main/resources/conf/param.properties @@ -24,13 +24,13 @@ # 微信开发平台(应用APPID) #以前的wx74f8aea529dc99d7 -appID = wx24b9abadcc524e29 +appID = wxe91f1af7638aa5dd # 微信支付分配的商户号ID(微信支付商户号) -mchID = 1600685974 +mchID = 1678345627 # 小程序的商户号 -XmchID = 1600685974 +XmchID = 1678345627 # 应用对应的密钥(商户平台开发设置) key = E10ADC3949BA59ABBE56E057F20F883E @@ -40,6 +40,6 @@ # 小程序的APPID -XappID = wx742b6a65ca132418 +XappID =wxe91f1af7638aa5dd diff --git a/ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml b/ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml index b52a110..67f9864 100644 --- a/ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml +++ b/ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderMapper.xml @@ -6,6 +6,7 @@ SELECT ifnull(count(1), 0) FROM t_order o WHERE o.goods_sku_id = #{id} + AND o.order_from=2 AND o.order_status IN (2 , 3 , 4) @@ -15,14 +16,16 @@ - <select id="getSeckillMembers1" resultType="com.ruoyi.system.api.domain.dto.MemberOrderDTO"> - SELECT ifnull(SUM(o.goods_quantity), 0) FROM t_order o LEFT - WHERE + + <select id="getGoodsGroupPurchase" resultType="java.lang.Integer"> + SELECT ifnull(SUM(o.goods_quantity), 0) FROM t_order o + WHERE o.goods_sku_id = #{goodsSkuId} - AND o.order_status IN (2 - , 3) - and o.member_id =#{memberId} + AND o.order_from=3 + AND o.order_status IN (2,3,4) + and o.member_id =#{memberId} </select> + <select id="getOrderByGroupPurchaseId" resultType="com.ruoyi.system.api.domain.Order" parameterType="java.lang.Long"> @@ -85,7 +88,7 @@ </select> - <select id="getOrderByGroupPurchaseMemberId" resultType="com.ruoyi.system.api.domain.vo.OrderVO"> + <select id="getOrderByGroupPurchaseMemberId" resultType="com.ruoyi.system.api.domain.Order"> SELECT o.* FROM -- Gitblit v1.7.1