From 2aea8d4fbc26c0ff533a86f677f55d805847dc53 Mon Sep 17 00:00:00 2001 From: 199901012 Date: Sat, 27 Mar 2021 00:43:19 +0800 Subject: [PATCH] =?UTF-8?q?'=E5=AE=8C=E6=88=90=E5=88=9B=E5=BB=BA=E8=AE=A2?= =?UTF-8?q?=E5=8D=95'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/cweb/config/SysConfig.java | 36 + .../HighMerchantStoreController.java | 22 +- .../cweb/controller/HighOrderController.java | 176 +++++ .../cweb/controller/pay/OrderController.java | 136 ++++ .../controller/pay/WechatPayController.java | 146 ++++ .../src/main/resources/dev/config.properties | 7 +- .../com/hai/common/exception/ErrorCode.java | 4 + .../com/hai/common/pay/WechatPayUtil.java | 81 ++ .../hai/common/pay/entity/AliPayReqInfo.java | 151 ++++ .../com/hai/common/pay/entity/OrderType.java | 43 ++ .../common/pay/entity/WeChatPayReqInfo.java | 205 ++++++ .../common/pay/entity/WechatCallBackInfo.java | 154 ++++ .../pay/entity/WechatPayReturnParam.java | 151 ++++ .../hai/common/pay/entity/WechatReturn.java | 77 ++ .../com/hai/common/pay/util/HttpReqUtil.java | 329 +++++++++ .../java/com/hai/common/pay/util/IOUtil.java | 73 ++ .../java/com/hai/common/pay/util/MD5Util.java | 55 ++ .../common/pay/util/MyX509TrustManager.java | 24 + .../hai/common/pay/util/SignatureUtil.java | 358 +++++++++ .../java/com/hai/common/pay/util/XmlUtil.java | 274 +++++++ .../hai/common/pay/util/sdk/IWXPayDomain.java | 42 ++ .../com/hai/common/pay/util/sdk/WXPay.java | 689 ++++++++++++++++++ .../hai/common/pay/util/sdk/WXPayConfig.java | 103 +++ .../common/pay/util/sdk/WXPayConstants.java | 59 ++ .../hai/common/pay/util/sdk/WXPayReport.java | 265 +++++++ .../hai/common/pay/util/sdk/WXPayRequest.java | 258 +++++++ .../hai/common/pay/util/sdk/WXPayUtil.java | 295 ++++++++ .../hai/common/pay/util/sdk/WXPayXmlUtil.java | 30 + .../com/hai/common/utils/IDGenerator.java | 63 ++ .../java/com/hai/common/utils/MathUtils.java | 25 + .../com/hai/dao/HighChildOrderMapper.java | 16 +- .../hai/dao/HighChildOrderSqlProvider.java | 16 +- .../java/com/hai/dao/HighCouponMapper.java | 29 +- .../com/hai/dao/HighCouponSqlProvider.java | 44 +- .../java/com/hai/dao/HighOrderMapper.java | 32 +- .../com/hai/dao/HighOrderSqlProvider.java | 44 +- .../java/com/hai/dao/HighPayRecordMapper.java | 65 +- .../com/hai/dao/HighPayRecordSqlProvider.java | 48 +- .../java/com/hai/entity/HighChildOrder.java | 13 +- .../com/hai/entity/HighChildOrderExample.java | 41 +- .../main/java/com/hai/entity/HighCoupon.java | 52 +- .../com/hai/entity/HighCouponExample.java | 168 ++++- .../main/java/com/hai/entity/HighOrder.java | 57 +- .../java/com/hai/entity/HighOrderExample.java | 160 +--- .../java/com/hai/entity/HighPayRecord.java | 47 +- .../com/hai/entity/HighPayRecordExample.java | 137 ++-- .../com/hai/service/HighOrderService.java | 50 ++ .../service/impl/HighOrderServiceImpl.java | 95 +++ .../com/hai/service/pay/NotifyService.java | 30 + .../com/hai/service/pay/PayRecordService.java | 30 + .../java/com/hai/service/pay/PayService.java | 21 + .../pay/impl/GoodsOrderServiceImpl.java | 39 + .../service/pay/impl/NotifyServiceImpl.java | 121 +++ .../pay/impl/PayRecordServiceImpl.java | 60 ++ .../hai/service/pay/impl/TestPayService.java | 23 + 55 files changed, 5282 insertions(+), 487 deletions(-) create mode 100644 hai-cweb/src/main/java/com/cweb/controller/HighOrderController.java create mode 100644 hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java create mode 100644 hai-cweb/src/main/java/com/cweb/controller/pay/WechatPayController.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/WechatPayUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/AliPayReqInfo.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/OrderType.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/WeChatPayReqInfo.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/WechatCallBackInfo.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/WechatPayReturnParam.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/entity/WechatReturn.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/HttpReqUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/IOUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/MD5Util.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/MyX509TrustManager.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/SignatureUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/XmlUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/IWXPayDomain.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPay.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConfig.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConstants.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayReport.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayRequest.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayXmlUtil.java create mode 100644 hai-service/src/main/java/com/hai/common/utils/IDGenerator.java create mode 100644 hai-service/src/main/java/com/hai/common/utils/MathUtils.java create mode 100644 hai-service/src/main/java/com/hai/service/HighOrderService.java create mode 100644 hai-service/src/main/java/com/hai/service/impl/HighOrderServiceImpl.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/NotifyService.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/PayRecordService.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/PayService.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/impl/GoodsOrderServiceImpl.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/impl/NotifyServiceImpl.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/impl/PayRecordServiceImpl.java create mode 100644 hai-service/src/main/java/com/hai/service/pay/impl/TestPayService.java diff --git a/hai-cweb/src/main/java/com/cweb/config/SysConfig.java b/hai-cweb/src/main/java/com/cweb/config/SysConfig.java index fdf16884..fce8ea72 100644 --- a/hai-cweb/src/main/java/com/cweb/config/SysConfig.java +++ b/hai-cweb/src/main/java/com/cweb/config/SysConfig.java @@ -13,6 +13,10 @@ public class SysConfig { private String wxAppId; private String wxAppSecret; + private String wxApiKey; + private String wxMchId; + private String wxUnifiedOrderUrl; + private String notifyUrl; public String getFileUrl() { return fileUrl; @@ -37,4 +41,36 @@ public class SysConfig { public void setWxAppSecret(String wxAppSecret) { this.wxAppSecret = wxAppSecret; } + + public String getWxApiKey() { + return wxApiKey; + } + + public void setWxApiKey(String wxApiKey) { + this.wxApiKey = wxApiKey; + } + + public String getWxMchId() { + return wxMchId; + } + + public void setWxMchId(String wxMchId) { + this.wxMchId = wxMchId; + } + + public String getWxUnifiedOrderUrl() { + return wxUnifiedOrderUrl; + } + + public void setWxUnifiedOrderUrl(String wxUnifiedOrderUrl) { + this.wxUnifiedOrderUrl = wxUnifiedOrderUrl; + } + + public String getNotifyUrl() { + return notifyUrl; + } + + public void setNotifyUrl(String notifyUrl) { + this.notifyUrl = notifyUrl; + } } diff --git a/hai-cweb/src/main/java/com/cweb/controller/HighMerchantStoreController.java b/hai-cweb/src/main/java/com/cweb/controller/HighMerchantStoreController.java index 886b6c20..81c41daf 100644 --- a/hai-cweb/src/main/java/com/cweb/controller/HighMerchantStoreController.java +++ b/hai-cweb/src/main/java/com/cweb/controller/HighMerchantStoreController.java @@ -12,10 +12,7 @@ import com.hai.common.utils.ResponseMsgUtil; import com.hai.entity.HighCoupon; import com.hai.entity.HighMerchant; import com.hai.entity.HighMerchantStore; -import com.hai.model.HighCouponModel; -import com.hai.model.HighMerchantStoreModel; -import com.hai.model.ResponseData; -import com.hai.model.UserInfoModel; +import com.hai.model.*; import com.hai.service.HighCouponService; import com.hai.service.HighMerchantService; import com.hai.service.HighMerchantStoreService; @@ -33,6 +30,7 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -79,7 +77,9 @@ public class HighMerchantStoreController { @RequestMapping(value="/getStoreListByCoupon",method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "根据卡卷查询门店列表") - public ResponseData getStoreListByCoupon(@RequestParam(name = "couponId", required = true) Long couponId) { + public ResponseData getStoreListByCoupon(@RequestParam(name = "couponId", required = true) Long couponId, + @RequestParam(name = "pageNum", required = true) Integer pageNum, + @RequestParam(name = "pageSize", required = true) Integer pageSize) { try { HighCouponModel coupon = highCouponService.getCouponById(couponId); @@ -88,7 +88,17 @@ public class HighMerchantStoreController { } Map map = new HashMap<>(); map.put("merchantId", coupon.getMerchantId()); - return ResponseMsgUtil.success(highMerchantStoreService.getMerchantStoreList(map)); + + PageHelper.startPage(pageNum, pageSize); + List storeList = highMerchantStoreService.getMerchantStoreList(map); + + if (storeList != null && storeList.size() > 0) { + HighMerchantModel merchant = highMerchantService.getMerchantById(coupon.getMerchantId()); + for (HighMerchantStore store : storeList) { + store.setExt1(merchant.getMerchantLogo()); + } + } + return ResponseMsgUtil.success(storeList); } catch (Exception e) { log.error("HighMerchantStoreController -> getStoreListByCoupon() error!",e); diff --git a/hai-cweb/src/main/java/com/cweb/controller/HighOrderController.java b/hai-cweb/src/main/java/com/cweb/controller/HighOrderController.java new file mode 100644 index 00000000..2d83c68d --- /dev/null +++ b/hai-cweb/src/main/java/com/cweb/controller/HighOrderController.java @@ -0,0 +1,176 @@ +package com.cweb.controller; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.hai.common.exception.ErrorCode; +import com.hai.common.exception.ErrorHelp; +import com.hai.common.exception.SysCode; +import com.hai.common.security.SessionObject; +import com.hai.common.security.UserCenter; +import com.hai.common.utils.DateUtil; +import com.hai.common.utils.IDGenerator; +import com.hai.common.utils.ResponseMsgUtil; +import com.hai.entity.HighChildOrder; +import com.hai.entity.HighCoupon; +import com.hai.entity.HighCouponCode; +import com.hai.entity.HighOrder; +import com.hai.model.HighCouponModel; +import com.hai.model.HighUserModel; +import com.hai.model.ResponseData; +import com.hai.model.UserInfoModel; +import com.hai.service.HighCouponCodeService; +import com.hai.service.HighCouponService; +import com.hai.service.HighOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @Auther: 胡锐 + * @Description: + * @Date: 2021/3/26 23:08 + */ +@Controller +@RequestMapping(value = "/highOrder") +@Api(value = "订单接口") +public class HighOrderController { + + private static Logger log = LoggerFactory.getLogger(HighMerchantStoreController.class); + + @Autowired + private UserCenter userCenter; + + @Resource + private HighOrderService highOrderService; + + @Resource + private HighCouponService highCouponService; + + @Resource + private HighCouponCodeService highCouponCodeService; + + @RequestMapping(value="/addOrder",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "增加订单") + public ResponseData addOrder(@RequestBody HighOrder highOrder, HttpServletRequest request) { + try { + + // 用户 + SessionObject sessionObject = userCenter.getSessionObject(request); + HighUserModel userInfoModel = (HighUserModel) sessionObject.getObject(); + + if (highOrder.getPayModel() == null + || highOrder.getPayType() == null + || highOrder.getHighChildOrderList() == null + || highOrder.getHighChildOrderList().size() == 0 + ) { + log.error("HighOrderController --> addOrder() error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + + BigDecimal totalPrice = new BigDecimal("0"); + for (HighChildOrder childOrder : highOrder.getHighChildOrderList()) { + if (childOrder.getGoodsType() == null || childOrder.getGoodsId() == null || childOrder.getSaleCount() == null) { + log.error("HighOrderController --> addOrder() error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + + // 商品类型 1:卡卷 + if (childOrder.getGoodsType() == 1) { + + // 查询卡卷信息 + HighCouponModel coupon = highCouponService.getCouponById(childOrder.getGoodsId()); + if (coupon == null) { + log.error("HighOrderController --> addOrder() error!", "未找到卡卷信息"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_FOUND_COUPON, ""); + } + + if (highCouponCodeService.getStockCountByCoupon(coupon.getId()) <= 0) { + log.error("HighOrderController --> addOrder() error!", "卡卷库存数量不足"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.COUPON_STOCK_INSUFFICIENT, ""); + } + + childOrder.setGoodsName(coupon.getCouponName()); + childOrder.setGoodsImg(coupon.getCouponImg()); + childOrder.setGoodsSpecName("默认"); + childOrder.setGoodsPrice(coupon.getDiscountPrice()); + childOrder.setTotalPrice(childOrder.getGoodsPrice().multiply(new BigDecimal(childOrder.getSaleCount().toString()))); + childOrder.setGiveawayType(false); // 是否是赠品 0:否 1:是 + childOrder.setChildOrdeStatus(1); // 1 待支付 2 已支付 3.已完成 4. 已退款 5.已取消 + childOrder.setPraiseStatus(0); + } + + // 累计订单价格 + totalPrice.add(childOrder.getTotalPrice()); + } + + highOrder.setOrderNo("HF" + DateUtil.date2String(new Date(),"yyyyMMddHHmmss") + IDGenerator.nextId(5)); + highOrder.setMemId(userInfoModel.getHighUser().getId()); + highOrder.setMemName(userInfoModel.getHighUser().getName()); + highOrder.setTotalPrice(totalPrice); + highOrder.setPayPrice(totalPrice); + highOrder.setCreateTime(new Date()); + highOrder.setOrderStatus(1); + + highOrderService.insertOrder(highOrder); + + return ResponseMsgUtil.success("操作成功"); + + } catch (Exception e) { + log.error("HighOrderController -> addOrder() error!",e); + return ResponseMsgUtil.exception(e); + } + } + + + @RequestMapping(value = "/getOrderById", method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "根据id查询订单详情") + public ResponseData getOrderById(@RequestParam(name = "orderId", required = true) Long orderId) { + try { + + return ResponseMsgUtil.success(highOrderService.getOrderById(orderId)); + + } catch (Exception e) { + log.error("HighOrderController --> getOrderById() error!", e); + return ResponseMsgUtil.exception(e); + } + } + + + @RequestMapping(value = "/getUserOrderList", method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取用户订单") + public ResponseData getUserOrderList(@RequestParam(name = "pageNum", required = true) Integer pageNum, + @RequestParam(name = "pageSize", required = true) Integer pageSize, + HttpServletRequest request) { + try { + + // 用户 + SessionObject sessionObject = userCenter.getSessionObject(request); + HighUserModel userInfoModel = (HighUserModel) sessionObject.getObject(); + + Map map = new HashMap<>(); + map.put("memId", userInfoModel.getHighUser().getId()); + + PageHelper.startPage(pageNum,pageSize); + return ResponseMsgUtil.success(new PageInfo<>(highCouponService.getCouponList(map))); + + } catch (Exception e) { + log.error("HighOrderController --> getUserOrderList() error!", e); + return ResponseMsgUtil.exception(e); + } + } +} diff --git a/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java b/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java new file mode 100644 index 00000000..33b89a90 --- /dev/null +++ b/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java @@ -0,0 +1,136 @@ +package com.cweb.controller.pay; + +import com.alibaba.fastjson.JSONObject; +import com.cweb.config.SysConst; +import com.hai.common.exception.ErrorCode; +import com.hai.common.exception.ErrorHelp; +import com.hai.common.exception.SysCode; +import com.hai.common.pay.WechatPayUtil; +import com.hai.common.pay.entity.OrderType; +import com.hai.common.pay.entity.WeChatPayReqInfo; +import com.hai.common.pay.util.MD5Util; +import com.hai.common.security.SessionObject; +import com.hai.common.security.UserCenter; +import com.hai.common.utils.MathUtils; +import com.hai.common.utils.ResponseMsgUtil; +import com.hai.entity.HighOrder; +import com.hai.model.ResponseData; +import com.hai.model.UserInfoModel; +import com.hai.service.HighOrderService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.concurrent.ThreadLocalRandom; + +/** + * + * @Title: + * @Description: 对订单的操作 + * @author: 魏真峰 + * @param: + * @return: + * @throws + */ +@Controller +@RequestMapping("/order") +@Api(value = "对订单的操作") +public class OrderController { + + private static Logger log = LoggerFactory.getLogger(OrderController.class); + + @Autowired + private UserCenter userCenter; + + @Resource + private WechatPayUtil wechatPayUtil; + + @Resource + private HighOrderService highOrderService; + + /** + * + * @Title: orderToPay + * @Description: 订单支付发起支付 + * @author: 魏真峰 + * @param: [pageNum, pageSize] + * @return: com.shinwoten.haj.common.model.ResponseData + * @throws + */ + @RequestMapping(value="/orderToPay",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "订单支付发起支付") + public ResponseData orderToPay(@RequestBody String reqBodyStr, + HttpServletRequest request) { + try { + if (StringUtils.isBlank(reqBodyStr)) { + log.error("orderToPay error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + JSONObject jsonObject = JSONObject.parseObject(reqBodyStr); + Long orderId = jsonObject.getLong("orderId"); + String openId = jsonObject.getString("openId"); // openId + if ( orderId == null || StringUtils.isBlank(openId)) { + log.error("orderToPay error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + + HighOrder order = highOrderService.getOrderById(orderId); + if(order == null) { + log.error("OrderController --> orderToPay() ERROR", "未找到订单信息"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_FOUND_ORDER, ""); + } + //校验订单状态 订单状态:1 待支付 2 已支付 3.已完成 4. 已退款 5.已取消 + if(order.getOrderStatus() != 1) { + log.error("OrderController --> orderToPay() ERROR", "订单不处于待支付状态"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.ORDER_NO_STAY_PAY, ""); + } + + Map map = new HashMap<>(); + map.put("orderNo", order.getOrderNo()); + map.put("payPrice", order.getPayPrice()); + map.put("body","购买卡券"); + map.put("subject","购买卡券"); + + //微信支付 + String nonce_str = MD5Util.MD5Encode(String.valueOf(ThreadLocalRandom.current().nextInt(10000)), "UTF-8"); + int total_fee = MathUtils.objectConvertBigDecimal(map.get("payPrice")).multiply(new BigDecimal("100")).intValue(); + WeChatPayReqInfo weChatPayReqInfo = new WeChatPayReqInfo(); + weChatPayReqInfo.setAppid(SysConst.getSysConfig().getWxAppId()); //公众号id + weChatPayReqInfo.setOpenid(openId); + weChatPayReqInfo.setMch_id(SysConst.getSysConfig().getWxMchId()); //商户号 + weChatPayReqInfo.setNonce_str(nonce_str); //随机字符串 + weChatPayReqInfo.setBody(map.get("body").toString()); //商品描述 + weChatPayReqInfo.setOut_trade_no(map.get("orderNo").toString()); //商户订单号 + weChatPayReqInfo.setTotal_fee(total_fee); //总金额 + weChatPayReqInfo.setSpbill_create_ip("139.159.177.244"); //终端ip + weChatPayReqInfo.setNotify_url(SysConst.getSysConfig().getNotifyUrl()); //通知url + weChatPayReqInfo.setTrade_type("JSAPI"); //交易类型 + // weChatPayReqInfo.setAttach(map.get("orderScene").toString()); //附加数据,区分订单类型 + Map payMap = new HashMap<>(); + + payMap.put("app_id",SysConst.getSysConfig().getWxAppId()); + payMap.put("api_key",SysConst.getSysConfig().getWxApiKey()); + payMap.put("unified_order_url",SysConst.getSysConfig().getWxUnifiedOrderUrl()); + SortedMap sortedMap = wechatPayUtil.goWechatPay(weChatPayReqInfo,payMap); + return ResponseMsgUtil.success(sortedMap); + } catch (Exception e) { + log.error("orderToPay error!", e); + return ResponseMsgUtil.exception(e); + } + } +} diff --git a/hai-cweb/src/main/java/com/cweb/controller/pay/WechatPayController.java b/hai-cweb/src/main/java/com/cweb/controller/pay/WechatPayController.java new file mode 100644 index 00000000..b7229a64 --- /dev/null +++ b/hai-cweb/src/main/java/com/cweb/controller/pay/WechatPayController.java @@ -0,0 +1,146 @@ +package com.cweb.controller.pay; + +import com.cweb.config.SysConst; +import com.hai.common.pay.WechatPayUtil; +import com.hai.common.pay.util.IOUtil; +import com.hai.common.pay.util.SignatureUtil; +import com.hai.common.pay.util.XmlUtil; +import com.hai.service.pay.NotifyService; +import com.hai.service.pay.PayRecordService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.util.SortedMap; + +@Controller +@RequestMapping(value = "/wechatpay") +@Api(value = "微信支付") +public class WechatPayController { + + private static Logger log = LoggerFactory.getLogger(WechatPayController.class); + + @Resource + private NotifyService notifyService; + @Resource + private PayRecordService payRecordService; + @Resource + private WechatPayUtil wechatPayUtil; + + @RequestMapping(value = "/notify", method = RequestMethod.POST) + @ApiOperation(value = "微信支付 -> 异步回调") + public void wechatNotify(HttpServletRequest request, HttpServletResponse response) { + try { + log.info("微信支付 -> 异步通知:处理开始"); + + String resXml = ""; // 反馈给微信服务器 + String notifyXml = null; // 微信支付系统发送的数据(格式) + notifyXml = IOUtil.inputStreamToString(request.getInputStream(), "UTF-8"); + + if (SignatureUtil.reCheckIsSignValidFromWeiXin(notifyXml, SysConst.getSysConfig().getWxApiKey(), "UTF-8")) { + log.info("微信支付系统发送的数据:" + notifyXml); + SortedMap map = XmlUtil.parseXmlToTreeMap(notifyXml, "UTF-8"); + + resXml = notifyService.wechatNotify(map); + } else { + log.error("微信支付 -> 异步通知:验签失败"); + log.error("apiKey:" + SysConst.getSysConfig().getWxApiKey()); + log.error("返回信息:" + notifyXml); + resXml = "" + "" + + "" + " "; + } + + BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); + out.write(resXml.getBytes()); + out.flush(); + out.close(); + log.info("微信支付 -> 异步通知:处理完成"); + } catch (Exception e) { + log.error("WechatPayController --> wechatNotify() error!", e); + } + } + + /*@RequestMapping(value = "/testCreateOrder", method = RequestMethod.GET) + @ApiOperation(value = "微信测试 创建支付信息(发版时注释此接口)") + @ResponseBody + public SortedMap testCreateOrder(@RequestParam(value = "subject", required = true) String subject, + @RequestParam(value = "orderNo", required = true) String orderNo, + @RequestParam(value = "totalPrice", required = true) Integer totalPrice, + HttpServletRequest httpRequest, HttpServletResponse httpResponse) { + try { + String nonce_str = MD5Util.MD5Encode(String.valueOf(ThreadLocalRandom.current().nextInt(10000)), "UTF-8"); + WeChatPayReqInfo weChatPayReqInfo = new WeChatPayReqInfo(); + weChatPayReqInfo.setAppid(wechatConfig.getApp_id()); //公众号id + weChatPayReqInfo.setMch_id(wechatConfig.getMch_id()); //商户号 + weChatPayReqInfo.setNonce_str(nonce_str); //随机字符串 + weChatPayReqInfo.setBody(subject); //商品描述 + weChatPayReqInfo.setOut_trade_no(orderNo); //商户订单号 + weChatPayReqInfo.setTotal_fee(totalPrice); //总 + weChatPayReqInfo.setSpbill_create_ip("182.43.154.4"); //终端ip + weChatPayReqInfo.setNotify_url(wechatConfig.getNotify_url()); //通知url + //weChatPayReqInfo.setTrade_type("APP"); //交易类型 + weChatPayReqInfo.setTrade_type("JSAPI"); + //weChatPayReqInfo.setOpenid(""); + weChatPayReqInfo.setAttach("Test"); + + *//** 获取沙箱key start *//* + String sandboxKey = GetSignKey(); + *//** 获取沙箱key end *//* + String sign = SignatureUtil.createSign(weChatPayReqInfo, sandboxKey, "UTF-8"); // 测试 todo del + weChatPayReqInfo.setSign(sign); + String unifiedXmL = XmlUtil.toSplitXml(weChatPayReqInfo); + + String unifiedOrderResultXmL = HttpReqUtil.HttpsDefaultExecute("POST", wechatConfig.getUnified_order_url(), null, unifiedXmL, null); + log.error("支付信息:" + unifiedOrderResultXmL); + // 签名校验 + SortedMap sortedMap = null; + // 组装支付参数 + WechatCallBackInfo wechatCallBackInfo = XmlUtil.getObjectFromXML(unifiedOrderResultXmL, WechatCallBackInfo.class); + Long timeStamp = System.currentTimeMillis()/1000; + sortedMap = new TreeMap<>(); + sortedMap.put("appid",wechatConfig.getApp_id()); + sortedMap.put("partnerid",wechatConfig.getMch_id()); + sortedMap.put("prepayid",wechatCallBackInfo.getPrepay_id()); + sortedMap.put("noncestr",wechatCallBackInfo.getNonce_str()); + sortedMap.put("timestamp",timeStamp); + sortedMap.put("package","Sign=WXPay"); + String secondSign = SignatureUtil.createSign(sortedMap, wechatConfig.getApi_key(), "UTF-8"); + sortedMap.put("sign",secondSign); + + return sortedMap; + } catch (Exception e) { + log.error("AlipayTest -> createOrder:生成订单错误", e); + } + return null; + }*/ + + + /** + * @desc 获取沙箱key + */ + /*public String GetSignKey() throws Exception { + String nonce_str = WXPayUtil.generateNonceStr(); //生成随机字符 + Map param = new HashMap<>(); + param.put("mch_id", wechatConfig.getMch_id()); //需要真实商户号 + param.put("nonce_str", nonce_str); //随机字符 + String sign = WXPayUtil.generateSignature(param, wechatConfig.getApi_key(), WXPayConstants.SignType.MD5); //通过SDK生成签名其中API_KEY为商户对应的真实密钥 + param.put("sign", sign); + String xml = WXPayUtil.mapToXml(param); //将map转换为xml格式 + String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"; //沙箱密钥获取api + String signKey = HttpUtil.post(url, xml); + System.out.println("signkey+"+signKey); + Map param1 = new HashMap(); + param1 = WXPayUtil.xmlToMap(signKey.toString()); + String key = param1.get("sandbox_signkey"); + return key; + }*/ + +} diff --git a/hai-cweb/src/main/resources/dev/config.properties b/hai-cweb/src/main/resources/dev/config.properties index f15b4fc5..37a2a39c 100644 --- a/hai-cweb/src/main/resources/dev/config.properties +++ b/hai-cweb/src/main/resources/dev/config.properties @@ -1,8 +1,11 @@ # ΢ wxAppId=wx8d49e2f83025229d wxAppSecret=d8d6dcaef77d3b659258a01b5ddba5df -mch_id=1603942866 -api_key=HfkjWxPayHaiShengGuang0123456789 +wxApiKey=HfkjWxPayHaiShengGuang0123456789 +wxMchId=1603942866 +wxUnifiedOrderUrl=https://api.mch.weixin.qq.com/pay/unifiedorder + +notifyUrl=https://hsgcs.dctpay.com//crest/wechatpay/notify fileUrl=/home/project/hsg/filesystem cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/hai-service/src/main/java/com/hai/common/exception/ErrorCode.java b/hai-service/src/main/java/com/hai/common/exception/ErrorCode.java index 8a33512f..87410b11 100644 --- a/hai-service/src/main/java/com/hai/common/exception/ErrorCode.java +++ b/hai-service/src/main/java/com/hai/common/exception/ErrorCode.java @@ -96,6 +96,10 @@ public enum ErrorCode { NEED_WRITE_DISCOUNT_PRICE("2124","请填写正确的折扣数,折扣数范围【0】 ~ 【10】"), DISCOUNT_PRICE_RANGE("2125","请输入正确的"), TEL_EXISTED("2126","联系方式已被使用"), + ORDER_TYPE_ERROR("2127","订单类型错误"), + COUPON_STOCK_INSUFFICIENT("2118","卡卷库存数量不足"), + NOT_FOUND_ORDER("2119","未找到订单信息"), + ORDER_NO_STAY_PAY("2120","订单不处于待支付状态"), STATUS_ERROR("3000","状态错误"), ADD_DATA_ERROR("3001","增加数据失败"), diff --git a/hai-service/src/main/java/com/hai/common/pay/WechatPayUtil.java b/hai-service/src/main/java/com/hai/common/pay/WechatPayUtil.java new file mode 100644 index 00000000..f8bfb563 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/WechatPayUtil.java @@ -0,0 +1,81 @@ +package com.hai.common.pay; + +import com.hai.common.pay.entity.WeChatPayReqInfo; +import com.hai.common.pay.entity.WechatCallBackInfo; +import com.hai.common.pay.util.HttpReqUtil; +import com.hai.common.pay.util.SignatureUtil; +import com.hai.common.pay.util.XmlUtil; +import com.hai.entity.HighPayRecord; +import com.hai.service.pay.PayRecordService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +@Component +public class WechatPayUtil { + + private static Logger log = LoggerFactory.getLogger(WechatPayUtil.class); + @Resource + private PayRecordService payRecordService; + + /** + * @throws + * @Title: goAlipay + * @Description: 微信支付请求体 + * @author: 魏真峰 + * @param: [orderId] + * @return: java.lang.String + */ + @RequestMapping("/goWechatPay") + @ResponseBody + public SortedMap goWechatPay(WeChatPayReqInfo weChatPayReqInfo, Map map) throws Exception{ + log.info("微信支付 -> 组装支付参数:开始"); + + String sign = SignatureUtil.createSign(weChatPayReqInfo, map.get("api_key"), "UTF-8"); + weChatPayReqInfo.setSign(sign); + String unifiedXmL = XmlUtil.toSplitXml(weChatPayReqInfo); + + String unifiedOrderResultXmL = HttpReqUtil.HttpsDefaultExecute("POST", map.get("unified_order_url"), null, unifiedXmL, null); + // 签名校验 + SortedMap sortedMap = null; + if (SignatureUtil.checkIsSignValidFromWeiXin(unifiedOrderResultXmL, map.get("api_key"), "UTF-8")) { + // 组装支付参数 + WechatCallBackInfo wechatCallBackInfo = XmlUtil.getObjectFromXML(unifiedOrderResultXmL, WechatCallBackInfo.class); + Long timeStamp = System.currentTimeMillis()/1000; + sortedMap = new TreeMap<>(); + sortedMap.put("appId",map.get("app_id")); +// sortedMap.put("partnerid",SysConst.getSysConfig().getMch_id()); +// sortedMap.put("prepayid",wechatCallBackInfo.getPrepay_id()); + sortedMap.put("nonceStr",wechatCallBackInfo.getNonce_str()); + sortedMap.put("timeStamp",timeStamp.toString()); + sortedMap.put("signType","MD5"); + sortedMap.put("package", "prepay_id=" + wechatCallBackInfo.getPrepay_id()); + String secondSign = SignatureUtil.createSign(sortedMap, map.get("api_key"), "UTF-8"); + sortedMap.put("sign",secondSign); + + // 将支付请求存入支付纪录 + HighPayRecord payRecord = new HighPayRecord(); + payRecord.setBodyInfo(unifiedXmL); + payRecord.setResType(1); + payRecord.setPayType(2); + payRecord.setPayMoney(new BigDecimal(weChatPayReqInfo.getTotal_fee()/100D)); + payRecordService.addPayRecord(payRecord); + + log.info("微信支付 -> 组装支付参数:完成"); + } else { + log.error("微信支付 -> 组装支付参数:支付信息错误"); + log.error("错误信息:" + unifiedOrderResultXmL); + } + + return sortedMap; + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/AliPayReqInfo.java b/hai-service/src/main/java/com/hai/common/pay/entity/AliPayReqInfo.java new file mode 100644 index 00000000..b8d1f8fa --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/AliPayReqInfo.java @@ -0,0 +1,151 @@ +package com.hai.common.pay.entity; + +/** + * @Description: 支付宝統一下单参数 + */ +public class AliPayReqInfo { + private String timeout_express; //该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。 90m + private String total_amount; //必填。订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 9.00 + private String seller_id; //收款支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID 2088102147948060 + private String product_code; //销售产品码,商家和支付宝签约的产品码 QUICK_MSECURITY_PAY + private String body; //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 Iphone6 16G + private String subject; //必填。商品的标题/交易标题/订单标题/订单关键字等。 大乐透 + private String out_trade_no; //必填。商户网站唯一订单号 70501111111S001111119 + private String time_expire; //绝对超时时间,格式为yyyy-MM-dd HH:mm。 2016-12-31 10:05 + private String goods_type; //商品主类型 :0-虚拟类商品,1-实物类商品 0 + private String promo_params; //优惠参数 + private String passback_params; //必填。公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。 merchantBizType%3d3C%26merchantBizNo%3d2016010101111 + private String enable_pay_channels; //可用渠道,用户只能在指定渠道范围内支付 + private String store_id; //商户门店编号 NJ_001 + private String specified_channel; //指定渠道,目前仅支持传入pcredit + private String disable_pay_channels; //禁用渠道,用户不可用指定渠道支付 + private String business_params; //商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式 + + public String getTimeout_express() { + return timeout_express; + } + + public void setTimeout_express(String timeout_express) { + this.timeout_express = timeout_express; + } + + public String getTotal_amount() { + return total_amount; + } + + public void setTotal_amount(String total_amount) { + this.total_amount = total_amount; + } + + public String getSeller_id() { + return seller_id; + } + + public void setSeller_id(String seller_id) { + this.seller_id = seller_id; + } + + public String getProduct_code() { + return product_code; + } + + public void setProduct_code(String product_code) { + this.product_code = product_code; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getGoods_type() { + return goods_type; + } + + public void setGoods_type(String goods_type) { + this.goods_type = goods_type; + } + + public String getPromo_params() { + return promo_params; + } + + public void setPromo_params(String promo_params) { + this.promo_params = promo_params; + } + + public String getPassback_params() { + return passback_params; + } + + public void setPassback_params(String passback_params) { + this.passback_params = passback_params; + } + + public String getEnable_pay_channels() { + return enable_pay_channels; + } + + public void setEnable_pay_channels(String enable_pay_channels) { + this.enable_pay_channels = enable_pay_channels; + } + + public String getStore_id() { + return store_id; + } + + public void setStore_id(String store_id) { + this.store_id = store_id; + } + + public String getSpecified_channel() { + return specified_channel; + } + + public void setSpecified_channel(String specified_channel) { + this.specified_channel = specified_channel; + } + + public String getDisable_pay_channels() { + return disable_pay_channels; + } + + public void setDisable_pay_channels(String disable_pay_channels) { + this.disable_pay_channels = disable_pay_channels; + } + + public String getBusiness_params() { + return business_params; + } + + public void setBusiness_params(String business_params) { + this.business_params = business_params; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/OrderType.java b/hai-service/src/main/java/com/hai/common/pay/entity/OrderType.java new file mode 100644 index 00000000..b1a6dd6f --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/OrderType.java @@ -0,0 +1,43 @@ +package com.hai.common.pay.entity; + +public enum OrderType { + // 建议将支付频率高的模块放在前面 + GOODS_ORDER("GOODS_ORDER", "goodsOrderService", "购买商品"), + GOLD("GOLD", "", "金币充值"), + TEST("TEST", "testPayService", "支付测试") + ; + + private String moduleCode; + private String service; + private String moduleName; + + private OrderType(String moduleCode, String service, String moduleName) { + this.moduleCode = moduleCode; + this.service = service; + this.moduleName = moduleName; + } + + public String getModuleCode() { + return moduleCode; + } + + private void setModuleCode(String moduleCode) { + this.moduleCode = moduleCode; + } + + public String getService() { + return service; + } + + private void setService(String service) { + this.service = service; + } + + public String getModuleName() { + return moduleName; + } + + private void setModuleName(String moduleName) { + this.moduleName = moduleName; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/WeChatPayReqInfo.java b/hai-service/src/main/java/com/hai/common/pay/entity/WeChatPayReqInfo.java new file mode 100644 index 00000000..7cbe4873 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/WeChatPayReqInfo.java @@ -0,0 +1,205 @@ +package com.hai.common.pay.entity; +import java.io.Serializable; + +/** + * @Description: 微信統一下单参数 + */ +public class WeChatPayReqInfo implements Serializable { + + private static final long serialVersionUID = -7642108447915413137L; + private String appid; // 公众号id 必填 + private String mch_id; // 商户号 必填 + private String nonce_str; // 随机字符串 必填 + private String sign; // 签名 必填 + private String device_info; // 设备号 可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB" + private String body; // 商品描述 必填 + private String detail; // 商品详情 + private String attach; // 附加数据 + private String out_trade_no; // 商户订单号 必填 + private String fee_type; // 货币类型 默认为人民币CNY + private Integer total_fee; // 总金额 传入int型的数据 必填 + private String spbill_create_ip; // 终端ip 必填 + private String time_start; // 交易起始时间 订单生成时间 + private String time_expire; // 交易结束时间 订单失效时间 + private String goods_tag; // 订单优惠标记 + private String notify_url; // 通知url 必填 + private String trade_type; // 交易类型 JSAPI,NATIVE,APP 必填 + private String product_id; //商品id trade_type=NATIVE时(即扫码支付),此参数必传 + private String limit_pay; // 指定支付方式 no_credit--可限制用户不能使用信用卡支付 + private String openid; // 用户标识(trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识) + + private String scene_info; // 该字段用于统一下单时上报场景信息,目前支持上报实际门店信息 格式{"store_id":// "SZT10000", "store_name":"腾讯大厦腾大餐厅"} + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public Integer getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(Integer total_fee) { + this.total_fee = total_fee; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getTime_start() { + return time_start; + } + + public void setTime_start(String time_start) { + this.time_start = time_start; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getGoods_tag() { + return goods_tag; + } + + public void setGoods_tag(String goods_tag) { + this.goods_tag = goods_tag; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getProduct_id() { + return product_id; + } + + public void setProduct_id(String product_id) { + this.product_id = product_id; + } + + public String getLimit_pay() { + return limit_pay; + } + + public void setLimit_pay(String limit_pay) { + this.limit_pay = limit_pay; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getScene_info() { + return scene_info; + } + + public void setScene_info(String scene_info) { + this.scene_info = scene_info; + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/WechatCallBackInfo.java b/hai-service/src/main/java/com/hai/common/pay/entity/WechatCallBackInfo.java new file mode 100644 index 00000000..300f7809 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/WechatCallBackInfo.java @@ -0,0 +1,154 @@ +package com.hai.common.pay.entity; + +/** + * 统一下单返回结果 + * @author phil + * @data 2017年6月27日 + * + */ +public class WechatCallBackInfo { + + private static final long serialVersionUID = 9030465964635155064L; + private String appid; // 公众号id + private String mch_id; // 商户号 + private String nonce_str; // 随机字符串 + private String sign; // 签名 + private String return_code; // 返回状态码 + private String return_msg; // 返回信息 + // 以下字段在return_code为SUCCESS的时候有返回(包括父类) + private String device_info; // 设备号 + private String result_code; // 业务结果 SUCCESS/FAIL + private String err_code; // 错误代码 + private String err_code_des; // 错误代码描述 + // 以下字段在return_code 和result_code都为SUCCESS的时候有返回 + private String trade_type; // 交易类型 + private String prepay_id; // 预支付交易会话标识,有效期为2小时 + private String code_url; // 二维码链接 + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getCode_url() { + return code_url; + } + + public void setCode_url(String code_url) { + this.code_url = code_url; + } + + @Override + public String toString() { + return "WechatCallBackInfo{" + + "appid='" + appid + '\'' + + ", mch_id='" + mch_id + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", sign='" + sign + '\'' + + ", return_code='" + return_code + '\'' + + ", return_msg='" + return_msg + '\'' + + ", device_info='" + device_info + '\'' + + ", result_code='" + result_code + '\'' + + ", err_code='" + err_code + '\'' + + ", err_code_des='" + err_code_des + '\'' + + ", trade_type='" + trade_type + '\'' + + ", prepay_id='" + prepay_id + '\'' + + ", code_url='" + code_url + '\'' + + '}'; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/WechatPayReturnParam.java b/hai-service/src/main/java/com/hai/common/pay/entity/WechatPayReturnParam.java new file mode 100644 index 00000000..a230d257 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/WechatPayReturnParam.java @@ -0,0 +1,151 @@ +package com.hai.common.pay.entity; +/** + * + * @Description: 微信支付异步回调参数 + */ +public class WechatPayReturnParam { + private String appid; //是 String(32) wx8888888888888888 微信开放平台审核通过的应用APPID + private String attach; //否 String(128) 123456 商家数据包,原样返回 + private String bank_type; //是 String(16) CMC 银行类型,采用字符串类型的银行标识,银行类型见银行列表 + private String cash_fee; //是 Int 100 现金支付金额订单现金支付金额,详见支付金额 + private String fee_type; //否 String(8) CNY 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 + private String is_subscribe; //是 String(1) Y 用户是否关注公众账号,Y-关注,N-未关注 + private String mch_id; //是 String(32) 1900000109 微信支付分配的商户号 + private String nonce_str; //是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串,不长于32位 + private String openid; //是 String(128) wxd930ea5d5a258f4f 用户在商户appid下的唯一标识 + private String out_trade_no; //是 String(32) 1212321211201407033568112322 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。 + private String result_code; //是 String(16) SUCCESS SUCCESS/FAIL + private String return_code; + private String time_end; //是 String(14) 20141030133525 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规 + private String total_fee; //是 Int 100 订单总金额,单位为分 + private String trade_type; //是 String(16) APP APP + private String transaction_id; //微信支付订单号 + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getBank_type() { + return bank_type; + } + + public void setBank_type(String bank_type) { + this.bank_type = bank_type; + } + + public String getCash_fee() { + return cash_fee; + } + + public void setCash_fee(String cash_fee) { + this.cash_fee = cash_fee; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getIs_subscribe() { + return is_subscribe; + } + + public void setIs_subscribe(String is_subscribe) { + this.is_subscribe = is_subscribe; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getTime_end() { + return time_end; + } + + public void setTime_end(String time_end) { + this.time_end = time_end; + } + + public String getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(String total_fee) { + this.total_fee = total_fee; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/entity/WechatReturn.java b/hai-service/src/main/java/com/hai/common/pay/entity/WechatReturn.java new file mode 100644 index 00000000..47079fb9 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/entity/WechatReturn.java @@ -0,0 +1,77 @@ +package com.hai.common.pay.entity; + +public class WechatReturn { + private String appid; + private String mch_id; + private String nonce_str; + private String prepay_id; + private String result_code; + private String return_code; + private String return_msg; + private String trade_type; + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/HttpReqUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/HttpReqUtil.java new file mode 100644 index 00000000..a5a4c576 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/HttpReqUtil.java @@ -0,0 +1,329 @@ +package com.hai.common.pay.util; + +import org.apache.commons.lang3.StringUtils; + +import javax.imageio.ImageIO; +import javax.net.ssl.*; +import javax.servlet.http.HttpServletRequest; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +/** + * Http连接工具类 + * + * @author phil + * @date 2017年7月2日 + * + */ +public class HttpReqUtil { + + private static int DEFAULT_CONNTIME = 5000; + private static int DEFAULT_READTIME = 5000; + private static int DEFAULT_UPLOAD_READTIME = 10 * 1000; + public static String POST = "POST"; + public static String GET = "GET"; + /** + * http请求 + * + * @param method + * 请求方法GET/POST + * @param path + * 请求路径 + * @param timeout + * 连接超时时间 默认为5000 + * @param readTimeout + * 读取超时时间 默认为5000 + * @param data + * 数据 + * @return + */ + private static String defaultConnection(String method, String path, int timeout, int readTimeout, String data, String encoding) + throws Exception { + String result = ""; + URL url = new URL(path); + if (url != null) { + HttpURLConnection conn = getConnection(method, url); + conn.setConnectTimeout(timeout == 0 ? DEFAULT_CONNTIME : timeout); + conn.setReadTimeout(readTimeout == 0 ? DEFAULT_READTIME : readTimeout); + if (data != null && !"".equals(data)) { + OutputStream output = conn.getOutputStream(); + output.write(data.getBytes("UTF-8")); + output.flush(); + output.close(); + } + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + InputStream input = conn.getInputStream(); + result = IOUtil.inputStreamToString(input, encoding); + input.close(); + conn.disconnect(); + } + } + return result; + } + + /** + * 根据url的协议选择对应的请求方式 + * + * @param method + * 请求的方法 + * @return + * @throws IOException + */ + private static HttpURLConnection getConnection(String method, URL url) throws IOException { + HttpURLConnection conn = null; + if ("https".equals(url.getProtocol())) { + SSLContext context = null; + try { + context = SSLContext.getInstance("SSL", "SunJSSE"); + context.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() }, + new java.security.SecureRandom()); + } catch (Exception e) { + throw new IOException(e); + } + HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection(); + connHttps.setSSLSocketFactory(context.getSocketFactory()); + connHttps.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + }); + conn = connHttps; + } else { + conn = (HttpURLConnection) url.openConnection(); + } + conn.setRequestMethod(method); + conn.setUseCaches(false); + conn.setDoInput(true); + conn.setDoOutput(true); + return conn; + } + + /** + * 设置参数 + * + * @param map + * 参数map + * @param path + * 需要赋值的path + * @param charset + * 编码格式 默认编码为utf-8(取消默认) + * @return 已经赋值好的url 只需要访问即可 + */ + public static String setParmas(Map map, String path, String charset) throws Exception { + String result = ""; + boolean hasParams = false; + if (path != null && !"".equals(path)) { + if (map != null && map.size() > 0) { + StringBuilder builder = new StringBuilder(); + Set> params = map.entrySet(); + for (Entry entry : params) { + String key = entry.getKey().trim(); + String value = entry.getValue().trim(); + if (hasParams) { + builder.append("&"); + } else { + hasParams = true; + } + if (charset != null && !"".equals(charset)) { + // builder.append(key).append("=").append(URLDecoder.(value,charset)); + builder.append(key).append("=").append(IOUtil.urlEncode(value, charset)); + } else { + builder.append(key).append("=").append(value); + } + } + result = builder.toString(); + } + } + return doUrlPath(path, result).toString(); + } + + /** + * 设置连接参数 + * + * @param path + * 路径 + * @return + */ + private static URL doUrlPath(String path, String query) throws Exception { + URL url = new URL(path); + if (StringUtils.isEmpty(path)) { + return url; + } + if (StringUtils.isEmpty(url.getQuery())) { + if (path.endsWith("?")) { + path += query; + } else { + path = path + "?" + query; + } + } else { + if (path.endsWith("&")) { + path += query; + } else { + path = path + "&" + query; + } + } + return new URL(path); + } + + /** + * 默认的http请求执行方法,返回 + * + * @param method + * 请求的方法 POST/GET + * @param path + * 请求path 路径 + * @param map + * 请求参数集合 + * @param data + * 输入的数据 允许为空 + * @return + */ + public static String HttpDefaultExecute(String method, String path, Map map, String data, String encoding) { + String result = ""; + try { + String url = setParmas((TreeMap) map, path, ""); + result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data, encoding); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 默认的https执行方法,返回 + * + * @param method + * 请求的方法 POST/GET + * @param path + * 请求path 路径 + * @param map + * 请求参数集合 + * @param data + * 输入的数据 允许为空 + * @return + */ + public static String HttpsDefaultExecute(String method, String path, Map map, String data, String encoding) { + String result = ""; + try { + String url = setParmas((TreeMap) map, path, ""); + result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data, encoding); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 文件路径 + * + * @param mediaUrl + * url 例如 + * http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png + * @return logo_white_ee663702.png + */ + private static String getFileName(String mediaUrl) { + String result = mediaUrl.substring(mediaUrl.lastIndexOf("/") + 1, mediaUrl.length()); + return result; + } + + /** + * 根据内容类型判断文件扩展名 + * + * @param ContentType + * 内容类型 + * @return + */ + private static String getFileExt(String contentType) { + String fileExt = ""; + if (contentType == null) { + return null; + } + if (contentType.contains("image/jpeg")) { + fileExt = ".jpg"; + } else if (contentType.contains("audio/mpeg")) { + fileExt = ".mp3"; + } else if (contentType.contains("audio/amr")) { + fileExt = ".amr"; + } else if (contentType.contains("video/mp4")) { + fileExt = ".mp4"; + } else if (contentType.contains("video/mpeg4")) { + fileExt = ".mp4"; + } else if (contentType.contains("image/png")) { + fileExt = ".png"; + } + return fileExt; + } + + + + + /** + * 改变图片大小、格式 + * + * @param is + * @param os + * @param size + * @param format + * @return + * @throws IOException + */ + public static OutputStream resizeImage(InputStream inputStream, OutputStream outputStream, int size, String format) + throws IOException { + BufferedImage prevImage = ImageIO.read(inputStream); + double width = prevImage.getWidth(); + double height = prevImage.getHeight(); + double percent = size / width; + int newWidth = (int) (width * percent); + int newHeight = (int) (height * percent); + BufferedImage image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_BGR); + Graphics graphics = image.createGraphics(); + graphics.drawImage(prevImage, 0, 0, newWidth, newHeight, null); + ImageIO.write(image, format, outputStream); + outputStream.flush(); + return outputStream; + } + + /** + * 获取客户端ip + * + * @param request + * @return + */ + public static String getRemortIP(HttpServletRequest request) { + 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"); + } + + // squid的squid.conf 的配制文件中forwarded_for项改为off时 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + // 多级反向代理 + if (ip != null && ip.indexOf(",") > 0 && ip.split(",").length > 1) { + ip = ip.split(",")[0]; + } + return ip; + } + + + + + +} + diff --git a/hai-service/src/main/java/com/hai/common/pay/util/IOUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/IOUtil.java new file mode 100644 index 00000000..ec6f01f8 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/IOUtil.java @@ -0,0 +1,73 @@ +package com.hai.common.pay.util; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +/** + * IO流工具类 + * @author 魏真峰 + */ +public class IOUtil { + + /** + * 将输入流转换为字符串 + *待转换为字符串的输入流 + * @return 由输入流转换String的字符串 + * @throws IOException + */ + public static String inputStreamToString(InputStream inputStream, String encoding) throws IOException { + if(StringUtils.isEmpty(encoding)) { + encoding = "UTF-8"; + } + return IOUtils.toString(inputStream, encoding); + } + + /** + * 将字符串转换为输入流 + * 待转换为输入流的字符串 + * @return + * @throws IOException + */ + public static InputStream toInputStream(String inputStr, String encoding) throws IOException { + if (StringUtils.isEmpty(inputStr)) { + return null; + } + if(StringUtils.isEmpty(encoding)) { + encoding = "UTF-8"; + } + return IOUtils.toInputStream(inputStr, encoding); + } + + + /** + * 编码 + * + * @param source + * @param encode + * @return + */ + public static String urlEncode(String source, String encode) { + String result = source; + try { + result = URLEncoder.encode(source, encode); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 将输入流转换字节数组 + * @return + * @throws IOException + */ + public static byte[] inputStreamToByteArray(InputStream inputStream) throws IOException { + return IOUtils.toByteArray(inputStream); + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/MD5Util.java b/hai-service/src/main/java/com/hai/common/pay/util/MD5Util.java new file mode 100644 index 00000000..88b0d560 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/MD5Util.java @@ -0,0 +1,55 @@ +package com.hai.common.pay.util; + +import org.apache.commons.lang3.StringUtils; + +import java.security.MessageDigest; + +/** + * MD5加密工具类 + * + * @author phil + * @date 2017年7月2日 + * + */ +public class MD5Util { + + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", + "e", "f" }; + + private static String byteArrayToHexString(byte b[]) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < b.length; i++) + buffer.append(byteToHexString(b[i])); + return buffer.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(StringUtils.isEmpty(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString.getBytes("UTF-8"))); + } else { + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception exception) { + + } + return resultString; + } + + public static void main(String args[]) { + System.out.println(MD5Encode("ceshi", "gbk")); + System.out.println(MD5Encode("ceshi", "utf-8")); + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/MyX509TrustManager.java b/hai-service/src/main/java/com/hai/common/pay/util/MyX509TrustManager.java new file mode 100644 index 00000000..11b4085c --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/MyX509TrustManager.java @@ -0,0 +1,24 @@ +package com.hai.common.pay.util; + +import javax.net.ssl.X509TrustManager; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * 自定义信任管理器 + * + * @author phil + * @date 2017年7月2日 + */ +class MyX509TrustManager implements X509TrustManager { + + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/SignatureUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/SignatureUtil.java new file mode 100644 index 00000000..522112f1 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/SignatureUtil.java @@ -0,0 +1,358 @@ +package com.hai.common.pay.util; + +import com.shinwoten.train.common.pay.entity.WechatPayReturnParam; +import com.shinwoten.train.common.pay.entity.WechatReturn; +import org.apache.commons.lang3.StringUtils; +import org.dom4j.DocumentException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.SortedMap; + +/** + * + * @Title: + * @Description: 微信支付签名工具类 + * @author: 魏真峰 + * @param: + * @return: + * @throws + */ +public class SignatureUtil { + + private static Logger logger = LoggerFactory.getLogger(SignatureUtil.class); + + /** + * 将字节数组转换为十六进制字符串 + * @param byteArray + * @return + */ + private static String byteToStr(byte[] byteArray) { + String strDigest = ""; + for (int i = 0; i < byteArray.length; i++) { + strDigest += byteToHexStr(byteArray[i]); + } + return strDigest; + } + + /** + * 将字节转换为十六进制字符串 + * + * @param mByte + * @return + */ + private static String byteToHexStr(byte mByte) { + char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + char[] tempArr = new char[2]; + tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; + tempArr[1] = Digit[mByte & 0X0F]; + return new String(tempArr); + } + + /** + * 获取签名 + * + * @param o + * 待加密的对象 该处仅限于Class + * @return + */ + public static String createSign(Object o, String apiKey, String encoding) { + String result = notSignParams(o, apiKey); + result = MD5Util.MD5Encode(result, encoding).toUpperCase(); + return result; + } + + /** + * 签名算法 + * + * @param o + * 要参与签名的数据对象 + * @param apiKey + * API密匙 + * @return 签名 + * @throws IllegalAccessException + */ + public static String notSignParams(Object o, String apiKey) { + ArrayList list = new ArrayList<>(); + String result = ""; + try { + Class cls = o.getClass(); + Field[] fields = cls.getDeclaredFields(); + list = getFieldList(fields, o); + Field[] superFields = cls.getSuperclass().getDeclaredFields(); // 获取父类的私有属性 + list.addAll(getFieldList(superFields, o)); + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); // 严格按字母表顺序排序 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + result = sb.toString(); + if (apiKey != null && !"".equals(apiKey)) { + result += "key=" + apiKey; + } else { + result = result.substring(0, result.lastIndexOf("&")); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 将字段集合方法转换 + * + * @param array + * @param object + * @return + * @throws IllegalArgumentException + * @throws IllegalAccessException + */ + private static ArrayList getFieldList(Field[] array, Object object) + throws IllegalArgumentException, IllegalAccessException { + ArrayList list = new ArrayList(); + for (Field f : array) { + f.setAccessible(true); + if (f.get(object) != null && f.get(object) != "" && !f.getName().equals("serialVersionUID") + && !f.getName().equals("sign")) { + if (f.getName().equals("packageStr")) { + list.add("package" + "=" + f.get(object) + "&"); + } else { + list.add(f.getName() + "=" + f.get(object) + "&"); + } + } + } + return list; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSign(Map map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + result = MD5Util.MD5Encode(result, characterEncoding).toUpperCase(); + logger.debug("sign result {}", result); + return result; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSign(SortedMap map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + result = MD5Util.MD5Encode(result, characterEncoding).toUpperCase(); + logger.debug("sign result {}", result); + return result; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSha1Sign(SortedMap map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-1"); + byte[] digest = md.digest(result.getBytes(characterEncoding)); + result = byteToStr(digest); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 返回未加密的字符串 + * + * @param params + * @param apiKey + * @return 待加密的字符串 + */ + private static String notSignParams(SortedMap params, String apiKey) { + StringBuffer buffer = new StringBuffer(); + for (Map.Entry entry : params.entrySet()) { + if (!org.springframework.util.StringUtils.isEmpty(entry.getValue())) { + buffer.append(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + buffer.append("key=" + apiKey); + return buffer.toString(); + } + + /** + * 返回未加密的字符串 + * + * @param params + * @param apiKey + * @return 待加密的字符串 + */ + public static String notSignParams(Map params, String apiKey) { + ArrayList list = new ArrayList<>(); + for (Map.Entry entry : params.entrySet()) { + if (entry.getValue() != "" && entry.getValue() != null) { + list.add(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString(); + if (apiKey != null && !"".equals(apiKey)) { + result += "key=" + apiKey; + } else { + result = result.substring(0, result.lastIndexOf("&")); + } + return result; + } + + /** + * 从API返回的XML数据里面重新计算一次签名 + * + * @param responseString + * API返回的XML数据 + * @param apiKey + * Key + * @return 新的签名 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static String reCreateSign(String responseString, String apiKey, String encoding) + throws IOException, SAXException, ParserConfigurationException { + Map map = XmlUtil.parseXmlToMap(responseString, encoding); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + map.replace("sign",""); + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + return createSign(map, apiKey, encoding); + } + + + /** + * 检验API返回的数据里面的签名是否合法,规则是:按参数名称a-z排序,遇到空值的参数不参加签名 + * + * @param resultXml + * API返回的XML数据字符串 + * @param apiKey + * Key + * @return API签名是否合法 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + * @throws DocumentException + */ + public static boolean checkIsSignValidFromWeiXin(String checktXml, String apiKey, String encoding) + throws ParserConfigurationException, IOException, SAXException, DocumentException { + SortedMap map = XmlUtil.parseXmlToTreeMap(checktXml,encoding); + String signFromresultXml = (String) map.get("sign"); + WechatReturn wechatReturn = new WechatReturn(); + wechatReturn.setAppid((String) map.get("appid")); + wechatReturn.setMch_id((String) map.get("mch_id")); + wechatReturn.setNonce_str((String) map.get("nonce_str")); + wechatReturn.setPrepay_id((String) map.get("prepay_id")); + wechatReturn.setResult_code((String) map.get("result_code")); + wechatReturn.setReturn_code((String) map.get("return_code")); + wechatReturn.setReturn_msg((String) map.get("return_msg")); + wechatReturn.setTrade_type((String) map.get("trade_type")); + if (StringUtils.isEmpty(signFromresultXml)) { + logger.debug("API返回的数据签名数据不存在"); + return false; + } + if(!("SUCCESS".equals(map.get("return_code"))) || !("SUCCESS".equals(map.get("result_code")))){ + logger.debug("返回代码不成功!"); + return false; + } + logger.debug("服务器回包里面的签名{}", signFromresultXml); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + String signForAPIResponse = createSign(wechatReturn, apiKey, encoding); + if (!signForAPIResponse.equals(signFromresultXml)) { + // 签名验不过,表示这个API返回的数据有可能已经被篡改了 + logger.debug("API返回的数据签名验证不通过"); + return false; + } + logger.debug("API返回的数据签名验证通过"); + return true; + } + /** + * + * @Title: reCheckIsSignValidFromWeiXin + * @Description: 微信支付异步回调,检验签名是否正确 + * @author: 魏真峰 + * @param: [checktXml, apiKey, encoding] + * @return: boolean + * @throws + */ + public static boolean reCheckIsSignValidFromWeiXin(String checktXml, String apiKey, String encoding) + throws ParserConfigurationException, IOException, SAXException, DocumentException { + SortedMap map = XmlUtil.parseXmlToTreeMap(checktXml,encoding); + String signFromresultXml = (String) map.get("sign"); + WechatPayReturnParam wechatPayReturnParam = new WechatPayReturnParam(); + wechatPayReturnParam.setAppid((String) map.get("appid")); + wechatPayReturnParam.setAttach((String) map.get("attach")); + wechatPayReturnParam.setBank_type((String) map.get("bank_type")); + wechatPayReturnParam.setCash_fee((String) map.get("cash_fee")); + wechatPayReturnParam.setFee_type((String) map.get("fee_type")); + wechatPayReturnParam.setIs_subscribe((String) map.get("is_subscribe")); + wechatPayReturnParam.setMch_id((String) map.get("mch_id")); + wechatPayReturnParam.setNonce_str((String) map.get("nonce_str")); + wechatPayReturnParam.setOpenid((String) map.get("openid")); + wechatPayReturnParam.setOut_trade_no((String) map.get("out_trade_no")); + wechatPayReturnParam.setResult_code((String) map.get("result_code")); + wechatPayReturnParam.setReturn_code((String) map.get("return_code")); + wechatPayReturnParam.setTime_end((String) map.get("time_end")); + wechatPayReturnParam.setTotal_fee((String) map.get("total_fee")); + wechatPayReturnParam.setTrade_type((String) map.get("trade_type")); + wechatPayReturnParam.setTransaction_id((String) map.get("transaction_id")); + if (StringUtils.isEmpty(signFromresultXml)) { + logger.debug("API返回的数据签名数据不存在"); + return false; + } + if(!("SUCCESS".equals(map.get("return_code"))) || !("SUCCESS".equals(map.get("result_code")))){ + logger.debug("返回代码不成功!"); + return false; + } + logger.debug("服务器回包里面的签名{}", signFromresultXml); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + String signForAPIResponse = createSign(wechatPayReturnParam, apiKey, encoding); + if (!signForAPIResponse.equals(signFromresultXml)) { + // 签名验不过,表示这个API返回的数据有可能已经被篡改了 + logger.debug("API返回的数据签名验证不通过"); + return false; + } + logger.debug("API返回的数据签名验证通过"); + return true; + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/XmlUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/XmlUtil.java new file mode 100644 index 00000000..2ebe9e0f --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/XmlUtil.java @@ -0,0 +1,274 @@ +package com.hai.common.pay.util; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.core.util.QuickWriter; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.xml.DomDriver; +import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; +import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder; +import com.thoughtworks.xstream.io.xml.XppDriver; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.xml.sax.SAXException; + +import javax.servlet.http.HttpServletRequest; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * XML解析工具类 + * + * @author phil + * @date 2017年7月3日 + * + */ +public class XmlUtil { + + /** + * 解析微信发来的请求(XML) xml示例 + * + * 123456789 + * + * + * + * @param request + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Map parseXmlToMap(HttpServletRequest request){ + Map map = new HashMap<>(); + InputStream inputStream = null; + try { + // 从request中取得输入流 + inputStream = request.getInputStream(); + // 读取输入流 + SAXReader reader = new SAXReader(); + Document document = reader.read(inputStream); + // 得到xml根元素 + Element root = document.getRootElement(); + // 得到根元素的所有子节点 + List elementList = root.elements(); + // 遍历所有子节点 + for (Element e : elementList) { + map.put(e.getName(), e.getText()); + } + } catch (IOException | DocumentException e) { + e.printStackTrace(); + } + return map; + } + + /** + * 解析微信发来的请求(XML) xml示例 + * + * 123456789 + * + * + * + * @param request + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Map parseStreamToMap(InputStream inputStream) throws Exception { + Map map = new HashMap<>(); + try { + // 读取输入流 + SAXReader reader = new SAXReader(); + Document document = reader.read(inputStream); + // 得到xml根元素 + Element root = document.getRootElement(); + // 得到根元素的所有子节点 + List elementList = root.elements(); + // 遍历所有子节点 + for (Element e : elementList) { + map.put(e.getName(), e.getText()); + } + } catch (DocumentException e) { + e.printStackTrace(); + } + return map; + } + + /** + * 使用dom4将xml文件中的数据转换成SortedMap + * + * @param xmlString + * xml格式的字符串 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static TreeMap parseXmlToTreeMap(String xml, String encoding) + throws ParserConfigurationException, IOException, SAXException { + // 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputStream is = IOUtil.toInputStream(xml, encoding); + org.w3c.dom.Document document = builder.parse(is); + // 获取到document里面的全部结点 + org.w3c.dom.NodeList allNodes = document.getFirstChild().getChildNodes(); + org.w3c.dom.Node node; + TreeMap map = new TreeMap<>(); + int i = 0; + while (i < allNodes.getLength()) { + node = allNodes.item(i); + if (node instanceof org.w3c.dom.Element) { + map.put(node.getNodeName(), node.getTextContent()); + } + i++; + } + return map; + } + + /** + * 使用dom4将xml文件中的数据转换成Map + * + * @param xmlString xml格式的字符串 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static Map parseXmlToMap(String xml, String encoding) + throws ParserConfigurationException, IOException, SAXException { + // 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputStream is = IOUtil.toInputStream(xml, encoding); + org.w3c.dom.Document document = builder.parse(is); + // 获取到document里面的全部结点 + org.w3c.dom.NodeList allNodes = document.getFirstChild().getChildNodes(); + org.w3c.dom.Node node; + Map map = new HashMap<>(); + int i = 0; + while (i < allNodes.getLength()) { + node = allNodes.item(i); + if (node instanceof org.w3c.dom.Element) { + map.put(node.getNodeName(), node.getTextContent()); + } + i++; + } + return map; + } + + /** + * 示例 + * + * + * + * + * + * + * + * + * + * + * 将xml数据(格式)映射到java对象中 + * + * @param xml + * 待转换的xml格式的数据 + * @param t + * 待转换为的java对象 + * @return + */ + public static T getObjectFromXML(String xml, Class t) { + // 将从API返回的XML数据映射到Java对象 + XStream xstream = XStreamFactroy.init(true); + xstream.alias("xml", t); + xstream.ignoreUnknownElements();// 暂时忽略掉一些新增的字段 +// if(Objects.equals(xstream.fromXML(xml).getClass(), t.getClass())) { +// return t.cast(xstream.fromXML(xml)); +// } +// return null; + return t.cast(xstream.fromXML(xml)); + } + + /** + * 将java对象转换为xml(格式) + * + * @param obj + * @return + */ + public static String toXml(Object obj) { + String result = ""; + XStream xstream = XStreamFactroy.init(true); + xstream.alias("xml", obj.getClass()); + result = xstream.toXML(obj); + return result; + } + + /** + * 将java对象转换为xml文件,并去除 _ 应用场景是 去除实体中有_划线的实体, 默认会有两个_,调用该方法则会去除一个 + * + * @param obj + * @return + */ + public static String toSplitXml(Object obj) { + String result = ""; + XStream xstream = XStreamFactroy.initSplitLine(); + xstream.alias("xml", obj.getClass()); + result = xstream.toXML(obj); + return result; + } + + /** + * XStream工具类 + * @author phil + * + */ + static class XStreamFactroy { + + private static final String START_CADA = ""; + + /** + * 是否启用 + * + * @param flag true 表示启用 false表示不启用 + * @return + */ + static XStream init(boolean flag) { + XStream xstream = null; + if (flag) { + xstream = new XStream(new XppDriver() { + public HierarchicalStreamWriter createWriter(Writer out) { + return new PrettyPrintWriter(out) { + @Override + protected void writeText(QuickWriter writer, String text) { + if (!text.startsWith(START_CADA)) { + text = START_CADA + text + END_CADA; + } + writer.write(text); + } + }; + } + }); + } else { + xstream = new XStream(); + } + return xstream; + } + + /** + * 用于处理在实体对象中带有_的属性,如果用上述方法,会出现有两个__,导致结果不正确! 属性中有_的属性一定要有改方法 + * + * @return 返回xstream 对象 new DomDriver("UTF-8", new + * XmlFriendlyNameCoder("-_", "_") + */ + public static XStream initSplitLine() { + XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_"))); + return xstream; + } + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/IWXPayDomain.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/IWXPayDomain.java new file mode 100644 index 00000000..04834fcc --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/IWXPayDomain.java @@ -0,0 +1,42 @@ +package com.hai.common.pay.util.sdk; + +/** + * 域名管理,实现主备域名自动切换 + */ +public abstract interface IWXPayDomain { + /** + * 上报域名网络状况 + * @param domain 域名。 比如:api.mch.weixin.qq.com + * @param elapsedTimeMillis 耗时 + * @param ex 网络请求中出现的异常。 + * null表示没有异常 + * ConnectTimeoutException,表示建立网络连接异常 + * UnknownHostException, 表示dns解析异常 + */ + abstract void report(final String domain, long elapsedTimeMillis, final Exception ex); + + /** + * 获取域名 + * @param config 配置 + * @return 域名 + */ + abstract DomainInfo getDomain(final WXPayConfig config); + + static class DomainInfo{ + public String domain; //域名 + public boolean primaryDomain; //该域名是否为主域名。例如:api.mch.weixin.qq.com为主域名 + public DomainInfo(String domain, boolean primaryDomain) { + this.domain = domain; + this.primaryDomain = primaryDomain; + } + + @Override + public String toString() { + return "DomainInfo{" + + "domain='" + domain + '\'' + + ", primaryDomain=" + primaryDomain + + '}'; + } + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPay.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPay.java new file mode 100644 index 00000000..89eda811 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPay.java @@ -0,0 +1,689 @@ +package com.hai.common.pay.util.sdk; + +import com.hai.common.pay.util.sdk.WXPayConstants.SignType; + +import java.util.HashMap; +import java.util.Map; + +public class WXPay { + + private WXPayConfig config; + private SignType signType; + private boolean autoReport; + private boolean useSandbox; + private String notifyUrl; + private WXPayRequest wxPayRequest; + + public WXPay(final WXPayConfig config) throws Exception { + this(config, null, true, false); + } + + public WXPay(final WXPayConfig config, final boolean autoReport) throws Exception { + this(config, null, autoReport, false); + } + + + public WXPay(final WXPayConfig config, final boolean autoReport, final boolean useSandbox) throws Exception{ + this(config, null, autoReport, useSandbox); + } + + public WXPay(final WXPayConfig config, final String notifyUrl) throws Exception { + this(config, notifyUrl, true, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport) throws Exception { + this(config, notifyUrl, autoReport, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception { + this.config = config; + this.notifyUrl = notifyUrl; + this.autoReport = autoReport; + this.useSandbox = useSandbox; + if (useSandbox) { + this.signType = SignType.MD5; // 沙箱环境 + } + else { + this.signType = SignType.HMACSHA256; + } + this.wxPayRequest = new WXPayRequest(config); + } + + private void checkWXPayConfig() throws Exception { + if (this.config == null) { + throw new Exception("config is null"); + } + if (this.config.getAppID() == null || this.config.getAppID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getMchID() == null || this.config.getMchID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getCertStream() == null) { + throw new Exception("cert stream in config is empty"); + } + if (this.config.getWXPayDomain() == null){ + throw new Exception("config.getWXPayDomain() is null"); + } + + if (this.config.getHttpConnectTimeoutMs() < 10) { + throw new Exception("http connect timeout is too small"); + } + if (this.config.getHttpReadTimeoutMs() < 10) { + throw new Exception("http read timeout is too small"); + } + + } + + /** + * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign
+ * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 + * + * @param reqData + * @return + * @throws Exception + */ + public Map fillRequestData(Map reqData) throws Exception { + reqData.put("appid", config.getAppID()); + reqData.put("mch_id", config.getMchID()); + reqData.put("nonce_str", WXPayUtil.generateNonceStr()); + if (SignType.MD5.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.MD5); + } + else if (SignType.HMACSHA256.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.HMACSHA256); + } + reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType)); + return reqData; + } + + /** + * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isResponseSignatureValid(Map reqData) throws Exception { + // 返回数据的签名方式和请求中给定的签名方式是一致的 + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), this.signType); + } + + /** + * 判断支付结果通知中的sign是否有效 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isPayResultNotifySignatureValid(Map reqData) throws Exception { + String signTypeInData = reqData.get(WXPayConstants.FIELD_SIGN_TYPE); + SignType signType; + if (signTypeInData == null) { + signType = SignType.MD5; + } + else { + signTypeInData = signTypeInData.trim(); + if (signTypeInData.length() == 0) { + signType = SignType.MD5; + } + else if (WXPayConstants.MD5.equals(signTypeInData)) { + signType = SignType.MD5; + } + else if (WXPayConstants.HMACSHA256.equals(signTypeInData)) { + signType = SignType.HMACSHA256; + } + else { + throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData)); + } + } + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), signType); + } + + + /** + * 不需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithoutCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID = reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithoutCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, autoReport); + return resp; + } + + + /** + * 需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 Map + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID= reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, this.autoReport); + return resp; + } + + /** + * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。 + * @param xmlStr API返回的XML格式数据 + * @return Map类型数据 + * @throws Exception + */ + public Map processResponseXml(String xmlStr) throws Exception { + String RETURN_CODE = "return_code"; + String return_code; + Map respData = WXPayUtil.xmlToMap(xmlStr); + if (respData.containsKey(RETURN_CODE)) { + return_code = respData.get(RETURN_CODE); + } + else { + throw new Exception(String.format("No `return_code` in XML: %s", xmlStr)); + } + + if (return_code.equals(WXPayConstants.FAIL)) { + return respData; + } + else if (return_code.equals(WXPayConstants.SUCCESS)) { + if (this.isResponseSignatureValid(respData)) { + return respData; + } + else { + throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr)); + } + } + else { + throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr)); + } + } + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData) throws Exception { + return this.microPay(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_MICROPAY_URL_SUFFIX; + } + else { + url = WXPayConstants.MICROPAY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData) throws Exception { + return this.microPayWithPos(reqData, this.config.getHttpConnectTimeoutMs()); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @param connectTimeoutMs + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData, int connectTimeoutMs) throws Exception { + int remainingTimeMs = 60*1000; + long startTimestampMs = 0; + Map lastResult = null; + Exception lastException = null; + + while (true) { + startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + int readTimeoutMs = remainingTimeMs - connectTimeoutMs; + if (readTimeoutMs > 1000) { + try { + lastResult = this.microPay(reqData, connectTimeoutMs, readTimeoutMs); + String returnCode = lastResult.get("return_code"); + if (returnCode.equals("SUCCESS")) { + String resultCode = lastResult.get("result_code"); + String errCode = lastResult.get("err_code"); + if (resultCode.equals("SUCCESS")) { + break; + } + else { + // 看错误码,若支付结果未知,则重试提交刷卡支付 + if (errCode.equals("SYSTEMERROR") || errCode.equals("BANKERROR") || errCode.equals("USERPAYING")) { + remainingTimeMs = remainingTimeMs - (int)(WXPayUtil.getCurrentTimestampMs() - startTimestampMs); + if (remainingTimeMs <= 100) { + break; + } + else { + WXPayUtil.getLogger().info("microPayWithPos: try micropay again"); + if (remainingTimeMs > 5*1000) { + Thread.sleep(5*1000); + } + else { + Thread.sleep(1*1000); + } + continue; + } + } + else { + break; + } + } + } + else { + break; + } + } + catch (Exception ex) { + lastResult = null; + lastException = ex; + } + } + else { + break; + } + } + + if (lastResult == null) { + throw lastException; + } + else { + return lastResult; + } + } + + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData) throws Exception { + return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.UNIFIEDORDER_URL_SUFFIX; + } + if(this.notifyUrl != null) { + reqData.put("notify_url", this.notifyUrl); + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData) throws Exception { + return this.orderQuery(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 int + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_ORDERQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.ORDERQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData) throws Exception { + return this.reverse(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REVERSE_URL_SUFFIX; + } + else { + url = WXPayConstants.REVERSE_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData) throws Exception { + return this.closeOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_CLOSEORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.CLOSEORDER_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData) throws Exception { + return this.refund(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUND_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUND_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData) throws Exception { + return this.refundQuery(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUNDQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUNDQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:对账单下载(成功时返回对账单数据,失败时返回XML格式数据)
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData) throws Exception { + return this.downloadBill(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:对账单下载
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:无论是否成功都返回Map。若成功,返回的Map中含有return_code、return_msg、data, + * 其中return_code为`SUCCESS`,data为对账单数据。 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return 经过封装的API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_DOWNLOADBILL_URL_SUFFIX; + } + else { + url = WXPayConstants.DOWNLOADBILL_URL_SUFFIX; + } + String respStr = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs).trim(); + Map ret; + // 出现错误,返回XML数据 + if (respStr.indexOf("<") == 0) { + ret = WXPayUtil.xmlToMap(respStr); + } + else { + // 正常返回csv数据 + ret = new HashMap(); + ret.put("return_code", WXPayConstants.SUCCESS); + ret.put("return_msg", "ok"); + ret.put("data", respStr); + } + return ret; + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData) throws Exception { + return this.report(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REPORT_URL_SUFFIX; + } + else { + url = WXPayConstants.REPORT_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return WXPayUtil.xmlToMap(respXml); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData) throws Exception { + return this.shortUrl(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_SHORTURL_URL_SUFFIX; + } + else { + url = WXPayConstants.SHORTURL_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData) throws Exception { + return this.authCodeToOpenid(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_AUTHCODETOOPENID_URL_SUFFIX; + } + else { + url = WXPayConstants.AUTHCODETOOPENID_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + +} // end class diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConfig.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConfig.java new file mode 100644 index 00000000..21dbc894 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConfig.java @@ -0,0 +1,103 @@ +package com.hai.common.pay.util.sdk; + +import java.io.InputStream; + +public abstract class WXPayConfig { + + + + /** + * 获取 App ID + * + * @return App ID + */ + abstract String getAppID(); + + + /** + * 获取 Mch ID + * + * @return Mch ID + */ + abstract String getMchID(); + + + /** + * 获取 API 密钥 + * + * @return API密钥 + */ + abstract String getKey(); + + + /** + * 获取商户证书内容 + * + * @return 商户证书内容 + */ + abstract InputStream getCertStream(); + + /** + * HTTP(S) 连接超时时间,单位毫秒 + * + * @return + */ + public int getHttpConnectTimeoutMs() { + return 6*1000; + } + + /** + * HTTP(S) 读数据超时时间,单位毫秒 + * + * @return + */ + public int getHttpReadTimeoutMs() { + return 8*1000; + } + + /** + * 获取WXPayDomain, 用于多域名容灾自动切换 + * @return + */ + abstract IWXPayDomain getWXPayDomain(); + + /** + * 是否自动上报。 + * 若要关闭自动上报,子类中实现该函数返回 false 即可。 + * + * @return + */ + public boolean shouldAutoReport() { + return true; + } + + /** + * 进行健康上报的线程的数量 + * + * @return + */ + public int getReportWorkerNum() { + return 6; + } + + + /** + * 健康上报缓存消息的最大数量。会有线程去独立上报 + * 粗略计算:加入一条消息200B,10000消息占用空间 2000 KB,约为2MB,可以接受 + * + * @return + */ + public int getReportQueueMaxSize() { + return 10000; + } + + /** + * 批量上报,一次最多上报多个数据 + * + * @return + */ + public int getReportBatchSize() { + return 10; + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConstants.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConstants.java new file mode 100644 index 00000000..f9f44716 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayConstants.java @@ -0,0 +1,59 @@ +package com.hai.common.pay.util.sdk; + +import org.apache.http.client.HttpClient; + +/** + * 常量 + */ +public class WXPayConstants { + + public enum SignType { + MD5, HMACSHA256 + } + + public static final String DOMAIN_API = "api.mch.weixin.qq.com"; + public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com"; + public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com"; + public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com"; + + + public static final String FAIL = "FAIL"; + public static final String SUCCESS = "SUCCESS"; + public static final String HMACSHA256 = "HMAC-SHA256"; + public static final String MD5 = "MD5"; + + public static final String FIELD_SIGN = "sign"; + public static final String FIELD_SIGN_TYPE = "sign_type"; + + public static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9"; + public static final String USER_AGENT = WXPAYSDK_VERSION + + " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") + + ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion(); + + public static final String MICROPAY_URL_SUFFIX = "/pay/micropay"; + public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder"; + public static final String ORDERQUERY_URL_SUFFIX = "/pay/orderquery"; + public static final String REVERSE_URL_SUFFIX = "/secapi/pay/reverse"; + public static final String CLOSEORDER_URL_SUFFIX = "/pay/closeorder"; + public static final String REFUND_URL_SUFFIX = "/secapi/pay/refund"; + public static final String REFUNDQUERY_URL_SUFFIX = "/pay/refundquery"; + public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill"; + public static final String REPORT_URL_SUFFIX = "/payitil/report"; + public static final String SHORTURL_URL_SUFFIX = "/tools/shorturl"; + public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid"; + + // sandbox + public static final String SANDBOX_MICROPAY_URL_SUFFIX = "/sandboxnew/pay/micropay"; + public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder"; + public static final String SANDBOX_ORDERQUERY_URL_SUFFIX = "/sandboxnew/pay/orderquery"; + public static final String SANDBOX_REVERSE_URL_SUFFIX = "/sandboxnew/secapi/pay/reverse"; + public static final String SANDBOX_CLOSEORDER_URL_SUFFIX = "/sandboxnew/pay/closeorder"; + public static final String SANDBOX_REFUND_URL_SUFFIX = "/sandboxnew/secapi/pay/refund"; + public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX = "/sandboxnew/pay/refundquery"; + public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill"; + public static final String SANDBOX_REPORT_URL_SUFFIX = "/sandboxnew/payitil/report"; + public static final String SANDBOX_SHORTURL_URL_SUFFIX = "/sandboxnew/tools/shorturl"; + public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid"; + +} + diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayReport.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayReport.java new file mode 100644 index 00000000..843cdb4d --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayReport.java @@ -0,0 +1,265 @@ +package com.hai.common.pay.util.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; + +/** + * 交易保障 + */ +public class WXPayReport { + + public static class ReportInfo { + + /** + * 布尔变量使用int。0为false, 1为true。 + */ + + // 基本信息 + private String version = "v1"; + private String sdk = WXPayConstants.WXPAYSDK_VERSION; + private String uuid; // 交易的标识 + private long timestamp; // 上报时的时间戳,单位秒 + private long elapsedTimeMillis; // 耗时,单位 毫秒 + + // 针对主域名 + private String firstDomain; // 第1次请求的域名 + private boolean primaryDomain; //是否主域名 + private int firstConnectTimeoutMillis; // 第1次请求设置的连接超时时间,单位 毫秒 + private int firstReadTimeoutMillis; // 第1次请求设置的读写超时时间,单位 毫秒 + private int firstHasDnsError; // 第1次请求是否出现dns问题 + private int firstHasConnectTimeout; // 第1次请求是否出现连接超时 + private int firstHasReadTimeout; // 第1次请求是否出现连接超时 + + public ReportInfo(String uuid, long timestamp, long elapsedTimeMillis, String firstDomain, boolean primaryDomain, int firstConnectTimeoutMillis, int firstReadTimeoutMillis, boolean firstHasDnsError, boolean firstHasConnectTimeout, boolean firstHasReadTimeout) { + this.uuid = uuid; + this.timestamp = timestamp; + this.elapsedTimeMillis = elapsedTimeMillis; + this.firstDomain = firstDomain; + this.primaryDomain = primaryDomain; + this.firstConnectTimeoutMillis = firstConnectTimeoutMillis; + this.firstReadTimeoutMillis = firstReadTimeoutMillis; + this.firstHasDnsError = firstHasDnsError?1:0; + this.firstHasConnectTimeout = firstHasConnectTimeout?1:0; + this.firstHasReadTimeout = firstHasReadTimeout?1:0; + } + + @Override + public String toString() { + return "ReportInfo{" + + "version='" + version + '\'' + + ", sdk='" + sdk + '\'' + + ", uuid='" + uuid + '\'' + + ", timestamp=" + timestamp + + ", elapsedTimeMillis=" + elapsedTimeMillis + + ", firstDomain='" + firstDomain + '\'' + + ", primaryDomain=" + primaryDomain + + ", firstConnectTimeoutMillis=" + firstConnectTimeoutMillis + + ", firstReadTimeoutMillis=" + firstReadTimeoutMillis + + ", firstHasDnsError=" + firstHasDnsError + + ", firstHasConnectTimeout=" + firstHasConnectTimeout + + ", firstHasReadTimeout=" + firstHasReadTimeout + + '}'; + } + + /** + * 转换成 csv 格式 + * + * @return + */ + public String toLineString(String key) { + String separator = ","; + Object[] objects = new Object[] { + version, sdk, uuid, timestamp, elapsedTimeMillis, + firstDomain, primaryDomain, firstConnectTimeoutMillis, firstReadTimeoutMillis, + firstHasDnsError, firstHasConnectTimeout, firstHasReadTimeout + }; + StringBuffer sb = new StringBuffer(); + for(Object obj: objects) { + sb.append(obj).append(separator); + } + try { + String sign = WXPayUtil.HMACSHA256(sb.toString(), key); + sb.append(sign); + return sb.toString(); + } + catch (Exception ex) { + return null; + } + + } + + } + + private static final String REPORT_URL = "http://report.mch.weixin.qq.com/wxpay/report/default"; + // private static final String REPORT_URL = "http://127.0.0.1:5000/test"; + + + private static final int DEFAULT_CONNECT_TIMEOUT_MS = 6*1000; + private static final int DEFAULT_READ_TIMEOUT_MS = 8*1000; + + private LinkedBlockingQueue reportMsgQueue = null; + private WXPayConfig config; + private ExecutorService executorService; + + private volatile static WXPayReport INSTANCE; + + private WXPayReport(final WXPayConfig config) { + this.config = config; + reportMsgQueue = new LinkedBlockingQueue(config.getReportQueueMaxSize()); + + // 添加处理线程 + executorService = Executors.newFixedThreadPool(config.getReportWorkerNum(), new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setDaemon(true); + return t; + } + }); + + if (config.shouldAutoReport()) { + WXPayUtil.getLogger().info("report worker num: {}", config.getReportWorkerNum()); + for (int i = 0; i < config.getReportWorkerNum(); ++i) { + executorService.execute(new Runnable() { + public void run() { + while (true) { + // 先用 take 获取数据 + try { + StringBuffer sb = new StringBuffer(); + String firstMsg = reportMsgQueue.take(); + WXPayUtil.getLogger().info("get first report msg: {}", firstMsg); + String msg = null; + sb.append(firstMsg); //会阻塞至有消息 + int remainNum = config.getReportBatchSize() - 1; + for (int j=0; jcreate() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + HttpPost httpPost = new HttpPost(REPORT_URL); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayRequest.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayRequest.java new file mode 100644 index 00000000..58a7baa4 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayRequest.java @@ -0,0 +1,258 @@ +package com.hai.common.pay.util.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.InputStream; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.security.KeyStore; +import java.security.SecureRandom; + +import static com.shinwoten.train.common.pay.util.sdk.WXPayConstants.USER_AGENT; + +public class WXPayRequest { + private WXPayConfig config; + public WXPayRequest(WXPayConfig config) throws Exception{ + + this.config = config; + } + + /** + * 请求,只请求一次,不做重试 + * @param domain + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @param useCert 是否使用证书,针对退款、撤销等操作 + * @return + * @throws Exception + */ + private String requestOnce(final String domain, String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception { + BasicHttpClientConnectionManager connManager; + if (useCert) { + // 证书 + char[] password = config.getMchID().toCharArray(); + InputStream certStream = config.getCertStream(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(certStream, password); + + // 实例化密钥库 & 初始化密钥工厂 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password); + + // 创建 SSLContext + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, new SecureRandom()); + + SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( + sslContext, + new String[]{"TLSv1"}, + null, + new DefaultHostnameVerifier()); + + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", sslConnectionSocketFactory) + .build(), + null, + null, + null + ); + } + else { + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + } + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + String url = "https://" + domain + urlSuffix; + HttpPost httpPost = new HttpPost(url); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", USER_AGENT + " " + config.getMchID()); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + + } + + + private String request(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert, boolean autoReport) throws Exception { + Exception exception = null; + long elapsedTimeMillis = 0; + long startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + boolean firstHasDnsErr = false; + boolean firstHasConnectTimeout = false; + boolean firstHasReadTimeout = false; + IWXPayDomain.DomainInfo domainInfo = config.getWXPayDomain().getDomain(config); + if(domainInfo == null){ + throw new Exception("WXPayConfig.getWXPayDomain().getDomain() is empty or null"); + } + try { + String result = requestOnce(domainInfo.domain, urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, useCert); + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, null); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + return result; + } + catch (UnknownHostException ex) { // dns 解析错误,或域名不存在 + exception = ex; + firstHasDnsErr = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("UnknownHostException for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (ConnectTimeoutException ex) { + exception = ex; + firstHasConnectTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("connect timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (SocketTimeoutException ex) { + exception = ex; + firstHasReadTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + catch (Exception ex) { + exception = ex; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, exception); + throw exception; + } + + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), false, autoReport); + } + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, false, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), true, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, true, autoReport); + } +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayUtil.java new file mode 100644 index 00000000..99ee0c8d --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayUtil.java @@ -0,0 +1,295 @@ +package com.hai.common.pay.util.sdk; + +import com.hai.common.pay.util.sdk.WXPayConstants.SignType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.*; + + +public class WXPayUtil { + + private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + private static final Random RANDOM = new SecureRandom(); + + /** + * XML格式字符串转换为Map + * + * @param strXML XML字符串 + * @return XML数据转换后的Map + * @throws Exception + */ + public static Map xmlToMap(String strXML) throws Exception { + try { + Map data = new HashMap(); + DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder(); + InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); + org.w3c.dom.Document doc = documentBuilder.parse(stream); + doc.getDocumentElement().normalize(); + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + for (int idx = 0; idx < nodeList.getLength(); ++idx) { + Node node = nodeList.item(idx); + if (node.getNodeType() == Node.ELEMENT_NODE) { + org.w3c.dom.Element element = (org.w3c.dom.Element) node; + data.put(element.getNodeName(), element.getTextContent()); + } + } + try { + stream.close(); + } catch (Exception ex) { + // do nothing + } + return data; + } catch (Exception ex) { + WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML); + throw ex; + } + + } + + /** + * 将Map转换为XML格式的字符串 + * + * @param data Map类型数据 + * @return XML格式的字符串 + * @throws Exception + */ + public static String mapToXml(Map data) throws Exception { + org.w3c.dom.Document document = WXPayXmlUtil.newDocument(); + org.w3c.dom.Element root = document.createElement("xml"); + document.appendChild(root); + for (String key: data.keySet()) { + String value = data.get(key); + if (value == null) { + value = ""; + } + value = value.trim(); + org.w3c.dom.Element filed = document.createElement(key); + filed.appendChild(document.createTextNode(value)); + root.appendChild(filed); + } + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + DOMSource source = new DOMSource(document); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); + try { + writer.close(); + } + catch (Exception ex) { + } + return output; + } + + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key) throws Exception { + return generateSignedXml(data, key, SignType.MD5); + } + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名类型 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key, SignType signType) throws Exception { + String sign = generateSignature(data, key, signType); + data.put(WXPayConstants.FIELD_SIGN, sign); + return mapToXml(data); + } + + + /** + * 判断签名是否正确 + * + * @param xmlStr XML格式数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(String xmlStr, String key) throws Exception { + Map data = xmlToMap(xmlStr); + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key).equals(sign); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key) throws Exception { + return isSignatureValid(data, key, SignType.MD5); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key, SignType signType) throws Exception { + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key, signType).equals(sign); + } + + /** + * 生成签名 + * + * @param data 待签名数据 + * @param key API密钥 + * @return 签名 + */ + public static String generateSignature(final Map data, String key) throws Exception { + return generateSignature(data, key, SignType.MD5); + } + + /** + * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 + * + * @param data 待签名数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名 + */ + public static String generateSignature(final Map data, String key, SignType signType) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k).trim()).append("&"); + } + sb.append("key=").append(key); + if (SignType.MD5.equals(signType)) { + return MD5(sb.toString()).toUpperCase(); + } + else if (SignType.HMACSHA256.equals(signType)) { + return HMACSHA256(sb.toString(), key); + } + else { + throw new Exception(String.format("Invalid sign_type: %s", signType)); + } + } + + + /** + * 获取随机字符串 Nonce Str + * + * @return String 随机字符串 + */ + public static String generateNonceStr() { + char[] nonceChars = new char[32]; + for (int index = 0; index < nonceChars.length; ++index) { + nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + return new String(nonceChars); + } + + + /** + * 生成 MD5 + * + * @param data 待处理数据 + * @return MD5结果 + */ + public static String MD5(String data) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] array = md.digest(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 生成 HMACSHA256 + * @param data 待处理数据 + * @param key 密钥 + * @return 加密结果 + * @throws Exception + */ + public static String HMACSHA256(String data, String key) throws Exception { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 日志 + * @return + */ + public static Logger getLogger() { + Logger logger = LoggerFactory.getLogger("wxpay java sdk"); + return logger; + } + + /** + * 获取当前时间戳,单位秒 + * @return + */ + public static long getCurrentTimestamp() { + return System.currentTimeMillis()/1000; + } + + /** + * 获取当前时间戳,单位毫秒 + * @return + */ + public static long getCurrentTimestampMs() { + return System.currentTimeMillis(); + } + +} diff --git a/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayXmlUtil.java b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayXmlUtil.java new file mode 100644 index 00000000..5e109976 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/pay/util/sdk/WXPayXmlUtil.java @@ -0,0 +1,30 @@ +package com.hai.common.pay.util.sdk; + +import org.w3c.dom.Document; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * 2018/7/3 + */ +public final class WXPayXmlUtil { + public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + documentBuilderFactory.setXIncludeAware(false); + documentBuilderFactory.setExpandEntityReferences(false); + + return documentBuilderFactory.newDocumentBuilder(); + } + + public static Document newDocument() throws ParserConfigurationException { + return newDocumentBuilder().newDocument(); + } +} diff --git a/hai-service/src/main/java/com/hai/common/utils/IDGenerator.java b/hai-service/src/main/java/com/hai/common/utils/IDGenerator.java new file mode 100644 index 00000000..afc0b933 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/utils/IDGenerator.java @@ -0,0 +1,63 @@ +package com.hai.common.utils; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class IDGenerator { + + private static final long ONE_STEP = 10; + private static final Lock LOCK = new ReentrantLock(); + private static long lastTime = System.nanoTime(); + private static short lastCount = 0; + private static int count = 0; + /** + * 可传入指定长度的值 + * @param length + * @return + */ + @SuppressWarnings("finally") + public static String nextId(int... length) + { + LOCK.lock(); + try { + if (lastCount == ONE_STEP) { + boolean done = false; + while (!done) { + long now = System.nanoTime(); + if (now == lastTime) { + try { + Thread.currentThread(); + Thread.sleep(1); + } catch (InterruptedException e) { + } + continue; + } else { + lastTime = now; + lastCount = 0; + done = true; + } + } + } + count = lastCount++; + } + finally + { + LOCK.unlock(); + String idStr = lastTime+""+String.format("%02d",count); + if(length.length > 0 && length[0] > 0){ + idStr = idStr.substring(idStr.length()-length[0]<0?0:idStr.length()-length[0], idStr.length()); + } + return idStr; + } + } + public static void main(String[] args) + { +// for(int i=0;i<100;i++) +// { +// System.out.println(nextId()); +// } +// nextId(20); + System.out.println(System.currentTimeMillis()); + } + +} diff --git a/hai-service/src/main/java/com/hai/common/utils/MathUtils.java b/hai-service/src/main/java/com/hai/common/utils/MathUtils.java new file mode 100644 index 00000000..ecd3d811 --- /dev/null +++ b/hai-service/src/main/java/com/hai/common/utils/MathUtils.java @@ -0,0 +1,25 @@ +package com.hai.common.utils; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class MathUtils { + + public static BigDecimal objectConvertBigDecimal(Object value) { + BigDecimal ret = null; + if (value != null) { + if (value instanceof BigDecimal) { + ret = (BigDecimal) value; + } else if (value instanceof String) { + ret = new BigDecimal((String) value); + } else if (value instanceof BigInteger) { + ret = new BigDecimal((BigInteger) value); + } else if (value instanceof Number) { + ret = new BigDecimal(((Number) value).doubleValue()); + } else { + throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal."); + } + } + return ret; + } +} diff --git a/hai-service/src/main/java/com/hai/dao/HighChildOrderMapper.java b/hai-service/src/main/java/com/hai/dao/HighChildOrderMapper.java index da39cff6..58533678 100644 --- a/hai-service/src/main/java/com/hai/dao/HighChildOrderMapper.java +++ b/hai-service/src/main/java/com/hai/dao/HighChildOrderMapper.java @@ -49,8 +49,8 @@ public interface HighChildOrderMapper extends HighChildOrderMapperExt { "values (#{orderId,jdbcType=BIGINT}, #{goodsType,jdbcType=INTEGER}, ", "#{goodsId,jdbcType=BIGINT}, #{goodsName,jdbcType=VARCHAR}, ", "#{goodsImg,jdbcType=VARCHAR}, #{goodsSpecName,jdbcType=VARCHAR}, ", - "#{goodsPrice,jdbcType=REAL}, #{saleCount,jdbcType=INTEGER}, ", - "#{totalPrice,jdbcType=REAL}, #{giveawayType,jdbcType=BIT}, ", + "#{goodsPrice,jdbcType=DECIMAL}, #{saleCount,jdbcType=INTEGER}, ", + "#{totalPrice,jdbcType=DECIMAL}, #{giveawayType,jdbcType=BIT}, ", "#{childOrdeStatus,jdbcType=INTEGER}, #{praiseStatus,jdbcType=INTEGER}, ", "#{ext1,jdbcType=VARCHAR}, #{ext2,jdbcType=VARCHAR}, #{ext3,jdbcType=VARCHAR})" }) @@ -70,9 +70,9 @@ public interface HighChildOrderMapper extends HighChildOrderMapperExt { @Result(column="goods_name", property="goodsName", jdbcType=JdbcType.VARCHAR), @Result(column="goods_img", property="goodsImg", jdbcType=JdbcType.VARCHAR), @Result(column="goods_spec_name", property="goodsSpecName", jdbcType=JdbcType.VARCHAR), - @Result(column="goods_price", property="goodsPrice", jdbcType=JdbcType.REAL), + @Result(column="goods_price", property="goodsPrice", jdbcType=JdbcType.DECIMAL), @Result(column="sale_count", property="saleCount", jdbcType=JdbcType.INTEGER), - @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.REAL), + @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.DECIMAL), @Result(column="giveaway_type", property="giveawayType", jdbcType=JdbcType.BIT), @Result(column="child_orde_status", property="childOrdeStatus", jdbcType=JdbcType.INTEGER), @Result(column="praise_status", property="praiseStatus", jdbcType=JdbcType.INTEGER), @@ -98,9 +98,9 @@ public interface HighChildOrderMapper extends HighChildOrderMapperExt { @Result(column="goods_name", property="goodsName", jdbcType=JdbcType.VARCHAR), @Result(column="goods_img", property="goodsImg", jdbcType=JdbcType.VARCHAR), @Result(column="goods_spec_name", property="goodsSpecName", jdbcType=JdbcType.VARCHAR), - @Result(column="goods_price", property="goodsPrice", jdbcType=JdbcType.REAL), + @Result(column="goods_price", property="goodsPrice", jdbcType=JdbcType.DECIMAL), @Result(column="sale_count", property="saleCount", jdbcType=JdbcType.INTEGER), - @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.REAL), + @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.DECIMAL), @Result(column="giveaway_type", property="giveawayType", jdbcType=JdbcType.BIT), @Result(column="child_orde_status", property="childOrdeStatus", jdbcType=JdbcType.INTEGER), @Result(column="praise_status", property="praiseStatus", jdbcType=JdbcType.INTEGER), @@ -127,9 +127,9 @@ public interface HighChildOrderMapper extends HighChildOrderMapperExt { "goods_name = #{goodsName,jdbcType=VARCHAR},", "goods_img = #{goodsImg,jdbcType=VARCHAR},", "goods_spec_name = #{goodsSpecName,jdbcType=VARCHAR},", - "goods_price = #{goodsPrice,jdbcType=REAL},", + "goods_price = #{goodsPrice,jdbcType=DECIMAL},", "sale_count = #{saleCount,jdbcType=INTEGER},", - "total_price = #{totalPrice,jdbcType=REAL},", + "total_price = #{totalPrice,jdbcType=DECIMAL},", "giveaway_type = #{giveawayType,jdbcType=BIT},", "child_orde_status = #{childOrdeStatus,jdbcType=INTEGER},", "praise_status = #{praiseStatus,jdbcType=INTEGER},", diff --git a/hai-service/src/main/java/com/hai/dao/HighChildOrderSqlProvider.java b/hai-service/src/main/java/com/hai/dao/HighChildOrderSqlProvider.java index fa73e176..948647d4 100644 --- a/hai-service/src/main/java/com/hai/dao/HighChildOrderSqlProvider.java +++ b/hai-service/src/main/java/com/hai/dao/HighChildOrderSqlProvider.java @@ -53,7 +53,7 @@ public class HighChildOrderSqlProvider { } if (record.getGoodsPrice() != null) { - sql.VALUES("goods_price", "#{goodsPrice,jdbcType=REAL}"); + sql.VALUES("goods_price", "#{goodsPrice,jdbcType=DECIMAL}"); } if (record.getSaleCount() != null) { @@ -61,7 +61,7 @@ public class HighChildOrderSqlProvider { } if (record.getTotalPrice() != null) { - sql.VALUES("total_price", "#{totalPrice,jdbcType=REAL}"); + sql.VALUES("total_price", "#{totalPrice,jdbcType=DECIMAL}"); } if (record.getGiveawayType() != null) { @@ -159,7 +159,7 @@ public class HighChildOrderSqlProvider { } if (record.getGoodsPrice() != null) { - sql.SET("goods_price = #{record.goodsPrice,jdbcType=REAL}"); + sql.SET("goods_price = #{record.goodsPrice,jdbcType=DECIMAL}"); } if (record.getSaleCount() != null) { @@ -167,7 +167,7 @@ public class HighChildOrderSqlProvider { } if (record.getTotalPrice() != null) { - sql.SET("total_price = #{record.totalPrice,jdbcType=REAL}"); + sql.SET("total_price = #{record.totalPrice,jdbcType=DECIMAL}"); } if (record.getGiveawayType() != null) { @@ -209,9 +209,9 @@ public class HighChildOrderSqlProvider { sql.SET("goods_name = #{record.goodsName,jdbcType=VARCHAR}"); sql.SET("goods_img = #{record.goodsImg,jdbcType=VARCHAR}"); sql.SET("goods_spec_name = #{record.goodsSpecName,jdbcType=VARCHAR}"); - sql.SET("goods_price = #{record.goodsPrice,jdbcType=REAL}"); + sql.SET("goods_price = #{record.goodsPrice,jdbcType=DECIMAL}"); sql.SET("sale_count = #{record.saleCount,jdbcType=INTEGER}"); - sql.SET("total_price = #{record.totalPrice,jdbcType=REAL}"); + sql.SET("total_price = #{record.totalPrice,jdbcType=DECIMAL}"); sql.SET("giveaway_type = #{record.giveawayType,jdbcType=BIT}"); sql.SET("child_orde_status = #{record.childOrdeStatus,jdbcType=INTEGER}"); sql.SET("praise_status = #{record.praiseStatus,jdbcType=INTEGER}"); @@ -253,7 +253,7 @@ public class HighChildOrderSqlProvider { } if (record.getGoodsPrice() != null) { - sql.SET("goods_price = #{goodsPrice,jdbcType=REAL}"); + sql.SET("goods_price = #{goodsPrice,jdbcType=DECIMAL}"); } if (record.getSaleCount() != null) { @@ -261,7 +261,7 @@ public class HighChildOrderSqlProvider { } if (record.getTotalPrice() != null) { - sql.SET("total_price = #{totalPrice,jdbcType=REAL}"); + sql.SET("total_price = #{totalPrice,jdbcType=DECIMAL}"); } if (record.getGiveawayType() != null) { diff --git a/hai-service/src/main/java/com/hai/dao/HighCouponMapper.java b/hai-service/src/main/java/com/hai/dao/HighCouponMapper.java index 5f7a6a4c..68941832 100644 --- a/hai-service/src/main/java/com/hai/dao/HighCouponMapper.java +++ b/hai-service/src/main/java/com/hai/dao/HighCouponMapper.java @@ -49,8 +49,8 @@ public interface HighCouponMapper extends HighCouponMapperExt { "sales_count, is_present, ", "create_time, update_time, ", "operator_id, operator_name, ", - "`status`, ext_1, ext_2, ", - "ext_3)", + "pay_type, ext_1, ext_2, ", + "ext_3, `status`, display_area)", "values (#{companyId,jdbcType=BIGINT}, #{merchantId,jdbcType=BIGINT}, ", "#{couponKey,jdbcType=VARCHAR}, #{couponName,jdbcType=VARCHAR}, ", "#{couponPrice,jdbcType=DECIMAL}, #{couponImg,jdbcType=VARCHAR}, ", @@ -61,8 +61,8 @@ public interface HighCouponMapper extends HighCouponMapperExt { "#{salesCount,jdbcType=INTEGER}, #{isPresent,jdbcType=BIT}, ", "#{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, ", "#{operatorId,jdbcType=BIGINT}, #{operatorName,jdbcType=VARCHAR}, ", - "#{status,jdbcType=INTEGER}, #{ext1,jdbcType=VARCHAR}, #{ext2,jdbcType=VARCHAR}, ", - "#{ext3,jdbcType=VARCHAR})" + "#{payType,jdbcType=INTEGER}, #{ext1,jdbcType=VARCHAR}, #{ext2,jdbcType=VARCHAR}, ", + "#{ext3,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, #{displayArea,jdbcType=INTEGER})" }) @Options(useGeneratedKeys=true,keyProperty="id") int insert(HighCoupon record); @@ -94,10 +94,12 @@ public interface HighCouponMapper extends HighCouponMapperExt { @Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP), @Result(column="operator_id", property="operatorId", jdbcType=JdbcType.BIGINT), @Result(column="operator_name", property="operatorName", jdbcType=JdbcType.VARCHAR), - @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), @Result(column="ext_1", property="ext1", jdbcType=JdbcType.VARCHAR), @Result(column="ext_2", property="ext2", jdbcType=JdbcType.VARCHAR), - @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR) + @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR), + @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="display_area", property="displayArea", jdbcType=JdbcType.INTEGER) }) List selectByExample(HighCouponExample example); @@ -106,7 +108,8 @@ public interface HighCouponMapper extends HighCouponMapperExt { "id, company_id, merchant_id, coupon_key, coupon_name, coupon_price, coupon_img, ", "coupon_carousel_img, coupon_desc, coupon_type, sales_end_time, recycle_day, ", "limit_number, sales_price, discount_price, sales_count, is_present, create_time, ", - "update_time, operator_id, operator_name, `status`, ext_1, ext_2, ext_3", + "update_time, operator_id, operator_name, pay_type, ext_1, ext_2, ext_3, `status`, ", + "display_area", "from high_coupon", "where id = #{id,jdbcType=BIGINT}" }) @@ -132,10 +135,12 @@ public interface HighCouponMapper extends HighCouponMapperExt { @Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP), @Result(column="operator_id", property="operatorId", jdbcType=JdbcType.BIGINT), @Result(column="operator_name", property="operatorName", jdbcType=JdbcType.VARCHAR), - @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), @Result(column="ext_1", property="ext1", jdbcType=JdbcType.VARCHAR), @Result(column="ext_2", property="ext2", jdbcType=JdbcType.VARCHAR), - @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR) + @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR), + @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="display_area", property="displayArea", jdbcType=JdbcType.INTEGER) }) HighCoupon selectByPrimaryKey(Long id); @@ -170,10 +175,12 @@ public interface HighCouponMapper extends HighCouponMapperExt { "update_time = #{updateTime,jdbcType=TIMESTAMP},", "operator_id = #{operatorId,jdbcType=BIGINT},", "operator_name = #{operatorName,jdbcType=VARCHAR},", - "`status` = #{status,jdbcType=INTEGER},", + "pay_type = #{payType,jdbcType=INTEGER},", "ext_1 = #{ext1,jdbcType=VARCHAR},", "ext_2 = #{ext2,jdbcType=VARCHAR},", - "ext_3 = #{ext3,jdbcType=VARCHAR}", + "ext_3 = #{ext3,jdbcType=VARCHAR},", + "`status` = #{status,jdbcType=INTEGER},", + "display_area = #{displayArea,jdbcType=INTEGER}", "where id = #{id,jdbcType=BIGINT}" }) int updateByPrimaryKey(HighCoupon record); diff --git a/hai-service/src/main/java/com/hai/dao/HighCouponSqlProvider.java b/hai-service/src/main/java/com/hai/dao/HighCouponSqlProvider.java index 27c5fcf7..c6aaeb6f 100644 --- a/hai-service/src/main/java/com/hai/dao/HighCouponSqlProvider.java +++ b/hai-service/src/main/java/com/hai/dao/HighCouponSqlProvider.java @@ -108,8 +108,8 @@ public class HighCouponSqlProvider { sql.VALUES("operator_name", "#{operatorName,jdbcType=VARCHAR}"); } - if (record.getStatus() != null) { - sql.VALUES("`status`", "#{status,jdbcType=INTEGER}"); + if (record.getPayType() != null) { + sql.VALUES("pay_type", "#{payType,jdbcType=INTEGER}"); } if (record.getExt1() != null) { @@ -124,6 +124,14 @@ public class HighCouponSqlProvider { sql.VALUES("ext_3", "#{ext3,jdbcType=VARCHAR}"); } + if (record.getStatus() != null) { + sql.VALUES("`status`", "#{status,jdbcType=INTEGER}"); + } + + if (record.getDisplayArea() != null) { + sql.VALUES("display_area", "#{displayArea,jdbcType=INTEGER}"); + } + return sql.toString(); } @@ -154,10 +162,12 @@ public class HighCouponSqlProvider { sql.SELECT("update_time"); sql.SELECT("operator_id"); sql.SELECT("operator_name"); - sql.SELECT("`status`"); + sql.SELECT("pay_type"); sql.SELECT("ext_1"); sql.SELECT("ext_2"); sql.SELECT("ext_3"); + sql.SELECT("`status`"); + sql.SELECT("display_area"); sql.FROM("high_coupon"); applyWhere(sql, example, false); @@ -259,8 +269,8 @@ public class HighCouponSqlProvider { sql.SET("operator_name = #{record.operatorName,jdbcType=VARCHAR}"); } - if (record.getStatus() != null) { - sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + if (record.getPayType() != null) { + sql.SET("pay_type = #{record.payType,jdbcType=INTEGER}"); } if (record.getExt1() != null) { @@ -275,6 +285,14 @@ public class HighCouponSqlProvider { sql.SET("ext_3 = #{record.ext3,jdbcType=VARCHAR}"); } + if (record.getStatus() != null) { + sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + } + + if (record.getDisplayArea() != null) { + sql.SET("display_area = #{record.displayArea,jdbcType=INTEGER}"); + } + applyWhere(sql, example, true); return sql.toString(); } @@ -304,10 +322,12 @@ public class HighCouponSqlProvider { sql.SET("update_time = #{record.updateTime,jdbcType=TIMESTAMP}"); sql.SET("operator_id = #{record.operatorId,jdbcType=BIGINT}"); sql.SET("operator_name = #{record.operatorName,jdbcType=VARCHAR}"); - sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + sql.SET("pay_type = #{record.payType,jdbcType=INTEGER}"); sql.SET("ext_1 = #{record.ext1,jdbcType=VARCHAR}"); sql.SET("ext_2 = #{record.ext2,jdbcType=VARCHAR}"); sql.SET("ext_3 = #{record.ext3,jdbcType=VARCHAR}"); + sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + sql.SET("display_area = #{record.displayArea,jdbcType=INTEGER}"); HighCouponExample example = (HighCouponExample) parameter.get("example"); applyWhere(sql, example, true); @@ -398,8 +418,8 @@ public class HighCouponSqlProvider { sql.SET("operator_name = #{operatorName,jdbcType=VARCHAR}"); } - if (record.getStatus() != null) { - sql.SET("`status` = #{status,jdbcType=INTEGER}"); + if (record.getPayType() != null) { + sql.SET("pay_type = #{payType,jdbcType=INTEGER}"); } if (record.getExt1() != null) { @@ -414,6 +434,14 @@ public class HighCouponSqlProvider { sql.SET("ext_3 = #{ext3,jdbcType=VARCHAR}"); } + if (record.getStatus() != null) { + sql.SET("`status` = #{status,jdbcType=INTEGER}"); + } + + if (record.getDisplayArea() != null) { + sql.SET("display_area = #{displayArea,jdbcType=INTEGER}"); + } + sql.WHERE("id = #{id,jdbcType=BIGINT}"); return sql.toString(); diff --git a/hai-service/src/main/java/com/hai/dao/HighOrderMapper.java b/hai-service/src/main/java/com/hai/dao/HighOrderMapper.java index d10d38c2..a36c9c44 100644 --- a/hai-service/src/main/java/com/hai/dao/HighOrderMapper.java +++ b/hai-service/src/main/java/com/hai/dao/HighOrderMapper.java @@ -39,8 +39,7 @@ public interface HighOrderMapper extends HighOrderMapperExt { int deleteByPrimaryKey(Long id); @Insert({ - "insert into high_order (order_no, order_type, ", - "order_source, mem_id, ", + "insert into high_order (order_no, mem_id, ", "mem_name, pay_model, ", "pay_type, pay_gold, ", "pay_price, pay_real_price, ", @@ -49,11 +48,10 @@ public interface HighOrderMapper extends HighOrderMapperExt { "pay_time, cancel_time, ", "finish_time, remarks, ", "ext_1, ext_2, ext_3)", - "values (#{orderNo,jdbcType=VARCHAR}, #{orderType,jdbcType=INTEGER}, ", - "#{orderSource,jdbcType=BIGINT}, #{memId,jdbcType=BIGINT}, ", + "values (#{orderNo,jdbcType=VARCHAR}, #{memId,jdbcType=BIGINT}, ", "#{memName,jdbcType=VARCHAR}, #{payModel,jdbcType=INTEGER}, ", "#{payType,jdbcType=INTEGER}, #{payGold,jdbcType=INTEGER}, ", - "#{payPrice,jdbcType=REAL}, #{payRealPrice,jdbcType=REAL}, ", + "#{payPrice,jdbcType=DECIMAL}, #{payRealPrice,jdbcType=DECIMAL}, ", "#{paySerialNo,jdbcType=VARCHAR}, #{orderStatus,jdbcType=INTEGER}, ", "#{totalPrice,jdbcType=DECIMAL}, #{createTime,jdbcType=TIMESTAMP}, ", "#{payTime,jdbcType=TIMESTAMP}, #{cancelTime,jdbcType=TIMESTAMP}, ", @@ -71,15 +69,13 @@ public interface HighOrderMapper extends HighOrderMapperExt { @Results({ @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), @Result(column="order_no", property="orderNo", jdbcType=JdbcType.VARCHAR), - @Result(column="order_type", property="orderType", jdbcType=JdbcType.INTEGER), - @Result(column="order_source", property="orderSource", jdbcType=JdbcType.BIGINT), @Result(column="mem_id", property="memId", jdbcType=JdbcType.BIGINT), @Result(column="mem_name", property="memName", jdbcType=JdbcType.VARCHAR), @Result(column="pay_model", property="payModel", jdbcType=JdbcType.INTEGER), @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), @Result(column="pay_gold", property="payGold", jdbcType=JdbcType.INTEGER), - @Result(column="pay_price", property="payPrice", jdbcType=JdbcType.REAL), - @Result(column="pay_real_price", property="payRealPrice", jdbcType=JdbcType.REAL), + @Result(column="pay_price", property="payPrice", jdbcType=JdbcType.DECIMAL), + @Result(column="pay_real_price", property="payRealPrice", jdbcType=JdbcType.DECIMAL), @Result(column="pay_serial_no", property="paySerialNo", jdbcType=JdbcType.VARCHAR), @Result(column="order_status", property="orderStatus", jdbcType=JdbcType.INTEGER), @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.DECIMAL), @@ -96,24 +92,22 @@ public interface HighOrderMapper extends HighOrderMapperExt { @Select({ "select", - "id, order_no, order_type, order_source, mem_id, mem_name, pay_model, pay_type, ", - "pay_gold, pay_price, pay_real_price, pay_serial_no, order_status, total_price, ", - "create_time, pay_time, cancel_time, finish_time, remarks, ext_1, ext_2, ext_3", + "id, order_no, mem_id, mem_name, pay_model, pay_type, pay_gold, pay_price, pay_real_price, ", + "pay_serial_no, order_status, total_price, create_time, pay_time, cancel_time, ", + "finish_time, remarks, ext_1, ext_2, ext_3", "from high_order", "where id = #{id,jdbcType=BIGINT}" }) @Results({ @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), @Result(column="order_no", property="orderNo", jdbcType=JdbcType.VARCHAR), - @Result(column="order_type", property="orderType", jdbcType=JdbcType.INTEGER), - @Result(column="order_source", property="orderSource", jdbcType=JdbcType.BIGINT), @Result(column="mem_id", property="memId", jdbcType=JdbcType.BIGINT), @Result(column="mem_name", property="memName", jdbcType=JdbcType.VARCHAR), @Result(column="pay_model", property="payModel", jdbcType=JdbcType.INTEGER), @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), @Result(column="pay_gold", property="payGold", jdbcType=JdbcType.INTEGER), - @Result(column="pay_price", property="payPrice", jdbcType=JdbcType.REAL), - @Result(column="pay_real_price", property="payRealPrice", jdbcType=JdbcType.REAL), + @Result(column="pay_price", property="payPrice", jdbcType=JdbcType.DECIMAL), + @Result(column="pay_real_price", property="payRealPrice", jdbcType=JdbcType.DECIMAL), @Result(column="pay_serial_no", property="paySerialNo", jdbcType=JdbcType.VARCHAR), @Result(column="order_status", property="orderStatus", jdbcType=JdbcType.INTEGER), @Result(column="total_price", property="totalPrice", jdbcType=JdbcType.DECIMAL), @@ -140,15 +134,13 @@ public interface HighOrderMapper extends HighOrderMapperExt { @Update({ "update high_order", "set order_no = #{orderNo,jdbcType=VARCHAR},", - "order_type = #{orderType,jdbcType=INTEGER},", - "order_source = #{orderSource,jdbcType=BIGINT},", "mem_id = #{memId,jdbcType=BIGINT},", "mem_name = #{memName,jdbcType=VARCHAR},", "pay_model = #{payModel,jdbcType=INTEGER},", "pay_type = #{payType,jdbcType=INTEGER},", "pay_gold = #{payGold,jdbcType=INTEGER},", - "pay_price = #{payPrice,jdbcType=REAL},", - "pay_real_price = #{payRealPrice,jdbcType=REAL},", + "pay_price = #{payPrice,jdbcType=DECIMAL},", + "pay_real_price = #{payRealPrice,jdbcType=DECIMAL},", "pay_serial_no = #{paySerialNo,jdbcType=VARCHAR},", "order_status = #{orderStatus,jdbcType=INTEGER},", "total_price = #{totalPrice,jdbcType=DECIMAL},", diff --git a/hai-service/src/main/java/com/hai/dao/HighOrderSqlProvider.java b/hai-service/src/main/java/com/hai/dao/HighOrderSqlProvider.java index 5a751719..c18f2885 100644 --- a/hai-service/src/main/java/com/hai/dao/HighOrderSqlProvider.java +++ b/hai-service/src/main/java/com/hai/dao/HighOrderSqlProvider.java @@ -32,14 +32,6 @@ public class HighOrderSqlProvider { sql.VALUES("order_no", "#{orderNo,jdbcType=VARCHAR}"); } - if (record.getOrderType() != null) { - sql.VALUES("order_type", "#{orderType,jdbcType=INTEGER}"); - } - - if (record.getOrderSource() != null) { - sql.VALUES("order_source", "#{orderSource,jdbcType=BIGINT}"); - } - if (record.getMemId() != null) { sql.VALUES("mem_id", "#{memId,jdbcType=BIGINT}"); } @@ -61,11 +53,11 @@ public class HighOrderSqlProvider { } if (record.getPayPrice() != null) { - sql.VALUES("pay_price", "#{payPrice,jdbcType=REAL}"); + sql.VALUES("pay_price", "#{payPrice,jdbcType=DECIMAL}"); } if (record.getPayRealPrice() != null) { - sql.VALUES("pay_real_price", "#{payRealPrice,jdbcType=REAL}"); + sql.VALUES("pay_real_price", "#{payRealPrice,jdbcType=DECIMAL}"); } if (record.getPaySerialNo() != null) { @@ -123,8 +115,6 @@ public class HighOrderSqlProvider { sql.SELECT("id"); } sql.SELECT("order_no"); - sql.SELECT("order_type"); - sql.SELECT("order_source"); sql.SELECT("mem_id"); sql.SELECT("mem_name"); sql.SELECT("pay_model"); @@ -168,14 +158,6 @@ public class HighOrderSqlProvider { sql.SET("order_no = #{record.orderNo,jdbcType=VARCHAR}"); } - if (record.getOrderType() != null) { - sql.SET("order_type = #{record.orderType,jdbcType=INTEGER}"); - } - - if (record.getOrderSource() != null) { - sql.SET("order_source = #{record.orderSource,jdbcType=BIGINT}"); - } - if (record.getMemId() != null) { sql.SET("mem_id = #{record.memId,jdbcType=BIGINT}"); } @@ -197,11 +179,11 @@ public class HighOrderSqlProvider { } if (record.getPayPrice() != null) { - sql.SET("pay_price = #{record.payPrice,jdbcType=REAL}"); + sql.SET("pay_price = #{record.payPrice,jdbcType=DECIMAL}"); } if (record.getPayRealPrice() != null) { - sql.SET("pay_real_price = #{record.payRealPrice,jdbcType=REAL}"); + sql.SET("pay_real_price = #{record.payRealPrice,jdbcType=DECIMAL}"); } if (record.getPaySerialNo() != null) { @@ -258,15 +240,13 @@ public class HighOrderSqlProvider { sql.SET("id = #{record.id,jdbcType=BIGINT}"); sql.SET("order_no = #{record.orderNo,jdbcType=VARCHAR}"); - sql.SET("order_type = #{record.orderType,jdbcType=INTEGER}"); - sql.SET("order_source = #{record.orderSource,jdbcType=BIGINT}"); sql.SET("mem_id = #{record.memId,jdbcType=BIGINT}"); sql.SET("mem_name = #{record.memName,jdbcType=VARCHAR}"); sql.SET("pay_model = #{record.payModel,jdbcType=INTEGER}"); sql.SET("pay_type = #{record.payType,jdbcType=INTEGER}"); sql.SET("pay_gold = #{record.payGold,jdbcType=INTEGER}"); - sql.SET("pay_price = #{record.payPrice,jdbcType=REAL}"); - sql.SET("pay_real_price = #{record.payRealPrice,jdbcType=REAL}"); + sql.SET("pay_price = #{record.payPrice,jdbcType=DECIMAL}"); + sql.SET("pay_real_price = #{record.payRealPrice,jdbcType=DECIMAL}"); sql.SET("pay_serial_no = #{record.paySerialNo,jdbcType=VARCHAR}"); sql.SET("order_status = #{record.orderStatus,jdbcType=INTEGER}"); sql.SET("total_price = #{record.totalPrice,jdbcType=DECIMAL}"); @@ -292,14 +272,6 @@ public class HighOrderSqlProvider { sql.SET("order_no = #{orderNo,jdbcType=VARCHAR}"); } - if (record.getOrderType() != null) { - sql.SET("order_type = #{orderType,jdbcType=INTEGER}"); - } - - if (record.getOrderSource() != null) { - sql.SET("order_source = #{orderSource,jdbcType=BIGINT}"); - } - if (record.getMemId() != null) { sql.SET("mem_id = #{memId,jdbcType=BIGINT}"); } @@ -321,11 +293,11 @@ public class HighOrderSqlProvider { } if (record.getPayPrice() != null) { - sql.SET("pay_price = #{payPrice,jdbcType=REAL}"); + sql.SET("pay_price = #{payPrice,jdbcType=DECIMAL}"); } if (record.getPayRealPrice() != null) { - sql.SET("pay_real_price = #{payRealPrice,jdbcType=REAL}"); + sql.SET("pay_real_price = #{payRealPrice,jdbcType=DECIMAL}"); } if (record.getPaySerialNo() != null) { diff --git a/hai-service/src/main/java/com/hai/dao/HighPayRecordMapper.java b/hai-service/src/main/java/com/hai/dao/HighPayRecordMapper.java index b56a4d7b..6321abd9 100644 --- a/hai-service/src/main/java/com/hai/dao/HighPayRecordMapper.java +++ b/hai-service/src/main/java/com/hai/dao/HighPayRecordMapper.java @@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.DeleteProvider; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.InsertProvider; +import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; @@ -33,38 +34,38 @@ public interface HighPayRecordMapper extends HighPayRecordMapperExt { @Delete({ "delete from high_pay_record", - "where pay_record_id = #{payRecordId,jdbcType=BIGINT}" + "where id = #{id,jdbcType=BIGINT}" }) - int deleteByPrimaryKey(Long payRecordId); + int deleteByPrimaryKey(Long id); @Insert({ - "insert into high_pay_record (pay_record_id, pay_serial_no, ", - "serail_state, pay_type, ", - "pay_money, pay_time, ", - "body_info, pay_result, ", - "fail_code, fail_reason, ", - "create_time, ext_1, ", - "ext_2, ext_3)", - "values (#{payRecordId,jdbcType=BIGINT}, #{paySerialNo,jdbcType=VARCHAR}, ", - "#{serailState,jdbcType=INTEGER}, #{payType,jdbcType=BIGINT}, ", - "#{payMoney,jdbcType=REAL}, #{payTime,jdbcType=TIMESTAMP}, ", - "#{bodyInfo,jdbcType=VARCHAR}, #{payResult,jdbcType=VARCHAR}, ", - "#{failCode,jdbcType=VARCHAR}, #{failReason,jdbcType=TIMESTAMP}, ", - "#{createTime,jdbcType=TIMESTAMP}, #{ext1,jdbcType=VARCHAR}, ", - "#{ext2,jdbcType=VARCHAR}, #{ext3,jdbcType=VARCHAR})" + "insert into high_pay_record (pay_serial_no, res_type, ", + "pay_type, pay_money, ", + "pay_time, body_info, ", + "pay_result, fail_code, ", + "fail_reason, create_time, ", + "ext_1, ext_2, ext_3)", + "values (#{paySerialNo,jdbcType=VARCHAR}, #{resType,jdbcType=INTEGER}, ", + "#{payType,jdbcType=INTEGER}, #{payMoney,jdbcType=DECIMAL}, ", + "#{payTime,jdbcType=TIMESTAMP}, #{bodyInfo,jdbcType=VARCHAR}, ", + "#{payResult,jdbcType=VARCHAR}, #{failCode,jdbcType=VARCHAR}, ", + "#{failReason,jdbcType=TIMESTAMP}, #{createTime,jdbcType=TIMESTAMP}, ", + "#{ext1,jdbcType=VARCHAR}, #{ext2,jdbcType=VARCHAR}, #{ext3,jdbcType=VARCHAR})" }) + @Options(useGeneratedKeys=true,keyProperty="id") int insert(HighPayRecord record); @InsertProvider(type=HighPayRecordSqlProvider.class, method="insertSelective") + @Options(useGeneratedKeys=true,keyProperty="id") int insertSelective(HighPayRecord record); @SelectProvider(type=HighPayRecordSqlProvider.class, method="selectByExample") @Results({ - @Result(column="pay_record_id", property="payRecordId", jdbcType=JdbcType.BIGINT, id=true), + @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), @Result(column="pay_serial_no", property="paySerialNo", jdbcType=JdbcType.VARCHAR), - @Result(column="serail_state", property="serailState", jdbcType=JdbcType.INTEGER), - @Result(column="pay_type", property="payType", jdbcType=JdbcType.BIGINT), - @Result(column="pay_money", property="payMoney", jdbcType=JdbcType.REAL), + @Result(column="res_type", property="resType", jdbcType=JdbcType.INTEGER), + @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), + @Result(column="pay_money", property="payMoney", jdbcType=JdbcType.DECIMAL), @Result(column="pay_time", property="payTime", jdbcType=JdbcType.TIMESTAMP), @Result(column="body_info", property="bodyInfo", jdbcType=JdbcType.VARCHAR), @Result(column="pay_result", property="payResult", jdbcType=JdbcType.VARCHAR), @@ -79,17 +80,17 @@ public interface HighPayRecordMapper extends HighPayRecordMapperExt { @Select({ "select", - "pay_record_id, pay_serial_no, serail_state, pay_type, pay_money, pay_time, body_info, ", - "pay_result, fail_code, fail_reason, create_time, ext_1, ext_2, ext_3", + "id, pay_serial_no, res_type, pay_type, pay_money, pay_time, body_info, pay_result, ", + "fail_code, fail_reason, create_time, ext_1, ext_2, ext_3", "from high_pay_record", - "where pay_record_id = #{payRecordId,jdbcType=BIGINT}" + "where id = #{id,jdbcType=BIGINT}" }) @Results({ - @Result(column="pay_record_id", property="payRecordId", jdbcType=JdbcType.BIGINT, id=true), + @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true), @Result(column="pay_serial_no", property="paySerialNo", jdbcType=JdbcType.VARCHAR), - @Result(column="serail_state", property="serailState", jdbcType=JdbcType.INTEGER), - @Result(column="pay_type", property="payType", jdbcType=JdbcType.BIGINT), - @Result(column="pay_money", property="payMoney", jdbcType=JdbcType.REAL), + @Result(column="res_type", property="resType", jdbcType=JdbcType.INTEGER), + @Result(column="pay_type", property="payType", jdbcType=JdbcType.INTEGER), + @Result(column="pay_money", property="payMoney", jdbcType=JdbcType.DECIMAL), @Result(column="pay_time", property="payTime", jdbcType=JdbcType.TIMESTAMP), @Result(column="body_info", property="bodyInfo", jdbcType=JdbcType.VARCHAR), @Result(column="pay_result", property="payResult", jdbcType=JdbcType.VARCHAR), @@ -100,7 +101,7 @@ public interface HighPayRecordMapper extends HighPayRecordMapperExt { @Result(column="ext_2", property="ext2", jdbcType=JdbcType.VARCHAR), @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR) }) - HighPayRecord selectByPrimaryKey(Long payRecordId); + HighPayRecord selectByPrimaryKey(Long id); @UpdateProvider(type=HighPayRecordSqlProvider.class, method="updateByExampleSelective") int updateByExampleSelective(@Param("record") HighPayRecord record, @Param("example") HighPayRecordExample example); @@ -114,9 +115,9 @@ public interface HighPayRecordMapper extends HighPayRecordMapperExt { @Update({ "update high_pay_record", "set pay_serial_no = #{paySerialNo,jdbcType=VARCHAR},", - "serail_state = #{serailState,jdbcType=INTEGER},", - "pay_type = #{payType,jdbcType=BIGINT},", - "pay_money = #{payMoney,jdbcType=REAL},", + "res_type = #{resType,jdbcType=INTEGER},", + "pay_type = #{payType,jdbcType=INTEGER},", + "pay_money = #{payMoney,jdbcType=DECIMAL},", "pay_time = #{payTime,jdbcType=TIMESTAMP},", "body_info = #{bodyInfo,jdbcType=VARCHAR},", "pay_result = #{payResult,jdbcType=VARCHAR},", @@ -126,7 +127,7 @@ public interface HighPayRecordMapper extends HighPayRecordMapperExt { "ext_1 = #{ext1,jdbcType=VARCHAR},", "ext_2 = #{ext2,jdbcType=VARCHAR},", "ext_3 = #{ext3,jdbcType=VARCHAR}", - "where pay_record_id = #{payRecordId,jdbcType=BIGINT}" + "where id = #{id,jdbcType=BIGINT}" }) int updateByPrimaryKey(HighPayRecord record); } \ No newline at end of file diff --git a/hai-service/src/main/java/com/hai/dao/HighPayRecordSqlProvider.java b/hai-service/src/main/java/com/hai/dao/HighPayRecordSqlProvider.java index 918a1a97..3744e19b 100644 --- a/hai-service/src/main/java/com/hai/dao/HighPayRecordSqlProvider.java +++ b/hai-service/src/main/java/com/hai/dao/HighPayRecordSqlProvider.java @@ -28,24 +28,20 @@ public class HighPayRecordSqlProvider { SQL sql = new SQL(); sql.INSERT_INTO("high_pay_record"); - if (record.getPayRecordId() != null) { - sql.VALUES("pay_record_id", "#{payRecordId,jdbcType=BIGINT}"); - } - if (record.getPaySerialNo() != null) { sql.VALUES("pay_serial_no", "#{paySerialNo,jdbcType=VARCHAR}"); } - if (record.getSerailState() != null) { - sql.VALUES("serail_state", "#{serailState,jdbcType=INTEGER}"); + if (record.getResType() != null) { + sql.VALUES("res_type", "#{resType,jdbcType=INTEGER}"); } if (record.getPayType() != null) { - sql.VALUES("pay_type", "#{payType,jdbcType=BIGINT}"); + sql.VALUES("pay_type", "#{payType,jdbcType=INTEGER}"); } if (record.getPayMoney() != null) { - sql.VALUES("pay_money", "#{payMoney,jdbcType=REAL}"); + sql.VALUES("pay_money", "#{payMoney,jdbcType=DECIMAL}"); } if (record.getPayTime() != null) { @@ -90,12 +86,12 @@ public class HighPayRecordSqlProvider { public String selectByExample(HighPayRecordExample example) { SQL sql = new SQL(); if (example != null && example.isDistinct()) { - sql.SELECT_DISTINCT("pay_record_id"); + sql.SELECT_DISTINCT("id"); } else { - sql.SELECT("pay_record_id"); + sql.SELECT("id"); } sql.SELECT("pay_serial_no"); - sql.SELECT("serail_state"); + sql.SELECT("res_type"); sql.SELECT("pay_type"); sql.SELECT("pay_money"); sql.SELECT("pay_time"); @@ -124,24 +120,24 @@ public class HighPayRecordSqlProvider { SQL sql = new SQL(); sql.UPDATE("high_pay_record"); - if (record.getPayRecordId() != null) { - sql.SET("pay_record_id = #{record.payRecordId,jdbcType=BIGINT}"); + if (record.getId() != null) { + sql.SET("id = #{record.id,jdbcType=BIGINT}"); } if (record.getPaySerialNo() != null) { sql.SET("pay_serial_no = #{record.paySerialNo,jdbcType=VARCHAR}"); } - if (record.getSerailState() != null) { - sql.SET("serail_state = #{record.serailState,jdbcType=INTEGER}"); + if (record.getResType() != null) { + sql.SET("res_type = #{record.resType,jdbcType=INTEGER}"); } if (record.getPayType() != null) { - sql.SET("pay_type = #{record.payType,jdbcType=BIGINT}"); + sql.SET("pay_type = #{record.payType,jdbcType=INTEGER}"); } if (record.getPayMoney() != null) { - sql.SET("pay_money = #{record.payMoney,jdbcType=REAL}"); + sql.SET("pay_money = #{record.payMoney,jdbcType=DECIMAL}"); } if (record.getPayTime() != null) { @@ -188,11 +184,11 @@ public class HighPayRecordSqlProvider { SQL sql = new SQL(); sql.UPDATE("high_pay_record"); - sql.SET("pay_record_id = #{record.payRecordId,jdbcType=BIGINT}"); + sql.SET("id = #{record.id,jdbcType=BIGINT}"); sql.SET("pay_serial_no = #{record.paySerialNo,jdbcType=VARCHAR}"); - sql.SET("serail_state = #{record.serailState,jdbcType=INTEGER}"); - sql.SET("pay_type = #{record.payType,jdbcType=BIGINT}"); - sql.SET("pay_money = #{record.payMoney,jdbcType=REAL}"); + sql.SET("res_type = #{record.resType,jdbcType=INTEGER}"); + sql.SET("pay_type = #{record.payType,jdbcType=INTEGER}"); + sql.SET("pay_money = #{record.payMoney,jdbcType=DECIMAL}"); sql.SET("pay_time = #{record.payTime,jdbcType=TIMESTAMP}"); sql.SET("body_info = #{record.bodyInfo,jdbcType=VARCHAR}"); sql.SET("pay_result = #{record.payResult,jdbcType=VARCHAR}"); @@ -216,16 +212,16 @@ public class HighPayRecordSqlProvider { sql.SET("pay_serial_no = #{paySerialNo,jdbcType=VARCHAR}"); } - if (record.getSerailState() != null) { - sql.SET("serail_state = #{serailState,jdbcType=INTEGER}"); + if (record.getResType() != null) { + sql.SET("res_type = #{resType,jdbcType=INTEGER}"); } if (record.getPayType() != null) { - sql.SET("pay_type = #{payType,jdbcType=BIGINT}"); + sql.SET("pay_type = #{payType,jdbcType=INTEGER}"); } if (record.getPayMoney() != null) { - sql.SET("pay_money = #{payMoney,jdbcType=REAL}"); + sql.SET("pay_money = #{payMoney,jdbcType=DECIMAL}"); } if (record.getPayTime() != null) { @@ -264,7 +260,7 @@ public class HighPayRecordSqlProvider { sql.SET("ext_3 = #{ext3,jdbcType=VARCHAR}"); } - sql.WHERE("pay_record_id = #{payRecordId,jdbcType=BIGINT}"); + sql.WHERE("id = #{id,jdbcType=BIGINT}"); return sql.toString(); } diff --git a/hai-service/src/main/java/com/hai/entity/HighChildOrder.java b/hai-service/src/main/java/com/hai/entity/HighChildOrder.java index 5cfd277a..97444872 100644 --- a/hai-service/src/main/java/com/hai/entity/HighChildOrder.java +++ b/hai-service/src/main/java/com/hai/entity/HighChildOrder.java @@ -1,6 +1,7 @@ package com.hai.entity; import java.io.Serializable; +import java.math.BigDecimal; /** * high_child_order @@ -50,7 +51,7 @@ public class HighChildOrder implements Serializable { /** * 商品的单价 */ - private Float goodsPrice; + private BigDecimal goodsPrice; /** * 商品的数量 @@ -60,7 +61,7 @@ public class HighChildOrder implements Serializable { /** * 商品的价格(单价*数量) */ - private Float totalPrice; + private BigDecimal totalPrice; /** * 是否是赠品 0:否 1:是 @@ -141,11 +142,11 @@ public class HighChildOrder implements Serializable { this.goodsSpecName = goodsSpecName; } - public Float getGoodsPrice() { + public BigDecimal getGoodsPrice() { return goodsPrice; } - public void setGoodsPrice(Float goodsPrice) { + public void setGoodsPrice(BigDecimal goodsPrice) { this.goodsPrice = goodsPrice; } @@ -157,11 +158,11 @@ public class HighChildOrder implements Serializable { this.saleCount = saleCount; } - public Float getTotalPrice() { + public BigDecimal getTotalPrice() { return totalPrice; } - public void setTotalPrice(Float totalPrice) { + public void setTotalPrice(BigDecimal totalPrice) { this.totalPrice = totalPrice; } diff --git a/hai-service/src/main/java/com/hai/entity/HighChildOrderExample.java b/hai-service/src/main/java/com/hai/entity/HighChildOrderExample.java index d84a661c..6d85286b 100644 --- a/hai-service/src/main/java/com/hai/entity/HighChildOrderExample.java +++ b/hai-service/src/main/java/com/hai/entity/HighChildOrderExample.java @@ -1,5 +1,6 @@ package com.hai.entity; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -584,52 +585,52 @@ public class HighChildOrderExample { return (Criteria) this; } - public Criteria andGoodsPriceEqualTo(Float value) { + public Criteria andGoodsPriceEqualTo(BigDecimal value) { addCriterion("goods_price =", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceNotEqualTo(Float value) { + public Criteria andGoodsPriceNotEqualTo(BigDecimal value) { addCriterion("goods_price <>", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceGreaterThan(Float value) { + public Criteria andGoodsPriceGreaterThan(BigDecimal value) { addCriterion("goods_price >", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceGreaterThanOrEqualTo(Float value) { + public Criteria andGoodsPriceGreaterThanOrEqualTo(BigDecimal value) { addCriterion("goods_price >=", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceLessThan(Float value) { + public Criteria andGoodsPriceLessThan(BigDecimal value) { addCriterion("goods_price <", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceLessThanOrEqualTo(Float value) { + public Criteria andGoodsPriceLessThanOrEqualTo(BigDecimal value) { addCriterion("goods_price <=", value, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceIn(List values) { + public Criteria andGoodsPriceIn(List values) { addCriterion("goods_price in", values, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceNotIn(List values) { + public Criteria andGoodsPriceNotIn(List values) { addCriterion("goods_price not in", values, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceBetween(Float value1, Float value2) { + public Criteria andGoodsPriceBetween(BigDecimal value1, BigDecimal value2) { addCriterion("goods_price between", value1, value2, "goodsPrice"); return (Criteria) this; } - public Criteria andGoodsPriceNotBetween(Float value1, Float value2) { + public Criteria andGoodsPriceNotBetween(BigDecimal value1, BigDecimal value2) { addCriterion("goods_price not between", value1, value2, "goodsPrice"); return (Criteria) this; } @@ -704,52 +705,52 @@ public class HighChildOrderExample { return (Criteria) this; } - public Criteria andTotalPriceEqualTo(Float value) { + public Criteria andTotalPriceEqualTo(BigDecimal value) { addCriterion("total_price =", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceNotEqualTo(Float value) { + public Criteria andTotalPriceNotEqualTo(BigDecimal value) { addCriterion("total_price <>", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceGreaterThan(Float value) { + public Criteria andTotalPriceGreaterThan(BigDecimal value) { addCriterion("total_price >", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceGreaterThanOrEqualTo(Float value) { + public Criteria andTotalPriceGreaterThanOrEqualTo(BigDecimal value) { addCriterion("total_price >=", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceLessThan(Float value) { + public Criteria andTotalPriceLessThan(BigDecimal value) { addCriterion("total_price <", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceLessThanOrEqualTo(Float value) { + public Criteria andTotalPriceLessThanOrEqualTo(BigDecimal value) { addCriterion("total_price <=", value, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceIn(List values) { + public Criteria andTotalPriceIn(List values) { addCriterion("total_price in", values, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceNotIn(List values) { + public Criteria andTotalPriceNotIn(List values) { addCriterion("total_price not in", values, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceBetween(Float value1, Float value2) { + public Criteria andTotalPriceBetween(BigDecimal value1, BigDecimal value2) { addCriterion("total_price between", value1, value2, "totalPrice"); return (Criteria) this; } - public Criteria andTotalPriceNotBetween(Float value1, Float value2) { + public Criteria andTotalPriceNotBetween(BigDecimal value1, BigDecimal value2) { addCriterion("total_price not between", value1, value2, "totalPrice"); return (Criteria) this; } diff --git a/hai-service/src/main/java/com/hai/entity/HighCoupon.java b/hai-service/src/main/java/com/hai/entity/HighCoupon.java index 863bb678..e14a7252 100644 --- a/hai-service/src/main/java/com/hai/entity/HighCoupon.java +++ b/hai-service/src/main/java/com/hai/entity/HighCoupon.java @@ -120,9 +120,9 @@ public class HighCoupon implements Serializable { private String operatorName; /** - * 状态:0.删除 1.编辑中 2.已上架 3.已下架 101.上架审批中 102.上架审批驳回 + * 支付类型:1.微信支付 2.金币支付 */ - private Integer status; + private Integer payType; private String ext1; @@ -130,6 +130,16 @@ public class HighCoupon implements Serializable { private String ext3; + /** + * 状态:0.删除 1.编辑中 2.已上架 3.已下架 101.上架审批中 102.上架审批驳回 + */ + private Integer status; + + /** + * 1.赠券专区 2.金币专区 + */ + private Integer displayArea; + private static final long serialVersionUID = 1L; public Long getId() { @@ -300,12 +310,12 @@ public class HighCoupon implements Serializable { this.operatorName = operatorName; } - public Integer getStatus() { - return status; + public Integer getPayType() { + return payType; } - public void setStatus(Integer status) { - this.status = status; + public void setPayType(Integer payType) { + this.payType = payType; } public String getExt1() { @@ -332,6 +342,22 @@ public class HighCoupon implements Serializable { this.ext3 = ext3; } + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getDisplayArea() { + return displayArea; + } + + public void setDisplayArea(Integer displayArea) { + this.displayArea = displayArea; + } + @Override public boolean equals(Object that) { if (this == that) { @@ -365,10 +391,12 @@ public class HighCoupon implements Serializable { && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime())) && (this.getOperatorId() == null ? other.getOperatorId() == null : this.getOperatorId().equals(other.getOperatorId())) && (this.getOperatorName() == null ? other.getOperatorName() == null : this.getOperatorName().equals(other.getOperatorName())) - && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getPayType() == null ? other.getPayType() == null : this.getPayType().equals(other.getPayType())) && (this.getExt1() == null ? other.getExt1() == null : this.getExt1().equals(other.getExt1())) && (this.getExt2() == null ? other.getExt2() == null : this.getExt2().equals(other.getExt2())) - && (this.getExt3() == null ? other.getExt3() == null : this.getExt3().equals(other.getExt3())); + && (this.getExt3() == null ? other.getExt3() == null : this.getExt3().equals(other.getExt3())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getDisplayArea() == null ? other.getDisplayArea() == null : this.getDisplayArea().equals(other.getDisplayArea())); } @Override @@ -396,10 +424,12 @@ public class HighCoupon implements Serializable { result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode()); result = prime * result + ((getOperatorId() == null) ? 0 : getOperatorId().hashCode()); result = prime * result + ((getOperatorName() == null) ? 0 : getOperatorName().hashCode()); - result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getPayType() == null) ? 0 : getPayType().hashCode()); result = prime * result + ((getExt1() == null) ? 0 : getExt1().hashCode()); result = prime * result + ((getExt2() == null) ? 0 : getExt2().hashCode()); result = prime * result + ((getExt3() == null) ? 0 : getExt3().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getDisplayArea() == null) ? 0 : getDisplayArea().hashCode()); return result; } @@ -430,10 +460,12 @@ public class HighCoupon implements Serializable { sb.append(", updateTime=").append(updateTime); sb.append(", operatorId=").append(operatorId); sb.append(", operatorName=").append(operatorName); - sb.append(", status=").append(status); + sb.append(", payType=").append(payType); sb.append(", ext1=").append(ext1); sb.append(", ext2=").append(ext2); sb.append(", ext3=").append(ext3); + sb.append(", status=").append(status); + sb.append(", displayArea=").append(displayArea); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); diff --git a/hai-service/src/main/java/com/hai/entity/HighCouponExample.java b/hai-service/src/main/java/com/hai/entity/HighCouponExample.java index 7dd3cec4..d8f7805b 100644 --- a/hai-service/src/main/java/com/hai/entity/HighCouponExample.java +++ b/hai-service/src/main/java/com/hai/entity/HighCouponExample.java @@ -1446,63 +1446,63 @@ public class HighCouponExample { return (Criteria) this; } - public Criteria andStatusIsNull() { - addCriterion("`status` is null"); + public Criteria andPayTypeIsNull() { + addCriterion("pay_type is null"); return (Criteria) this; } - public Criteria andStatusIsNotNull() { - addCriterion("`status` is not null"); + public Criteria andPayTypeIsNotNull() { + addCriterion("pay_type is not null"); return (Criteria) this; } - public Criteria andStatusEqualTo(Integer value) { - addCriterion("`status` =", value, "status"); + public Criteria andPayTypeEqualTo(Integer value) { + addCriterion("pay_type =", value, "payType"); return (Criteria) this; } - public Criteria andStatusNotEqualTo(Integer value) { - addCriterion("`status` <>", value, "status"); + public Criteria andPayTypeNotEqualTo(Integer value) { + addCriterion("pay_type <>", value, "payType"); return (Criteria) this; } - public Criteria andStatusGreaterThan(Integer value) { - addCriterion("`status` >", value, "status"); + public Criteria andPayTypeGreaterThan(Integer value) { + addCriterion("pay_type >", value, "payType"); return (Criteria) this; } - public Criteria andStatusGreaterThanOrEqualTo(Integer value) { - addCriterion("`status` >=", value, "status"); + public Criteria andPayTypeGreaterThanOrEqualTo(Integer value) { + addCriterion("pay_type >=", value, "payType"); return (Criteria) this; } - public Criteria andStatusLessThan(Integer value) { - addCriterion("`status` <", value, "status"); + public Criteria andPayTypeLessThan(Integer value) { + addCriterion("pay_type <", value, "payType"); return (Criteria) this; } - public Criteria andStatusLessThanOrEqualTo(Integer value) { - addCriterion("`status` <=", value, "status"); + public Criteria andPayTypeLessThanOrEqualTo(Integer value) { + addCriterion("pay_type <=", value, "payType"); return (Criteria) this; } - public Criteria andStatusIn(List values) { - addCriterion("`status` in", values, "status"); + public Criteria andPayTypeIn(List values) { + addCriterion("pay_type in", values, "payType"); return (Criteria) this; } - public Criteria andStatusNotIn(List values) { - addCriterion("`status` not in", values, "status"); + public Criteria andPayTypeNotIn(List values) { + addCriterion("pay_type not in", values, "payType"); return (Criteria) this; } - public Criteria andStatusBetween(Integer value1, Integer value2) { - addCriterion("`status` between", value1, value2, "status"); + public Criteria andPayTypeBetween(Integer value1, Integer value2) { + addCriterion("pay_type between", value1, value2, "payType"); return (Criteria) this; } - public Criteria andStatusNotBetween(Integer value1, Integer value2) { - addCriterion("`status` not between", value1, value2, "status"); + public Criteria andPayTypeNotBetween(Integer value1, Integer value2) { + addCriterion("pay_type not between", value1, value2, "payType"); return (Criteria) this; } @@ -1715,6 +1715,126 @@ public class HighCouponExample { addCriterion("ext_3 not between", value1, value2, "ext3"); return (Criteria) this; } + + public Criteria andStatusIsNull() { + addCriterion("`status` is null"); + return (Criteria) this; + } + + public Criteria andStatusIsNotNull() { + addCriterion("`status` is not null"); + return (Criteria) this; + } + + public Criteria andStatusEqualTo(Integer value) { + addCriterion("`status` =", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotEqualTo(Integer value) { + addCriterion("`status` <>", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThan(Integer value) { + addCriterion("`status` >", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThanOrEqualTo(Integer value) { + addCriterion("`status` >=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThan(Integer value) { + addCriterion("`status` <", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThanOrEqualTo(Integer value) { + addCriterion("`status` <=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusIn(List values) { + addCriterion("`status` in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotIn(List values) { + addCriterion("`status` not in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusBetween(Integer value1, Integer value2) { + addCriterion("`status` between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotBetween(Integer value1, Integer value2) { + addCriterion("`status` not between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andDisplayAreaIsNull() { + addCriterion("display_area is null"); + return (Criteria) this; + } + + public Criteria andDisplayAreaIsNotNull() { + addCriterion("display_area is not null"); + return (Criteria) this; + } + + public Criteria andDisplayAreaEqualTo(Integer value) { + addCriterion("display_area =", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaNotEqualTo(Integer value) { + addCriterion("display_area <>", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaGreaterThan(Integer value) { + addCriterion("display_area >", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaGreaterThanOrEqualTo(Integer value) { + addCriterion("display_area >=", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaLessThan(Integer value) { + addCriterion("display_area <", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaLessThanOrEqualTo(Integer value) { + addCriterion("display_area <=", value, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaIn(List values) { + addCriterion("display_area in", values, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaNotIn(List values) { + addCriterion("display_area not in", values, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaBetween(Integer value1, Integer value2) { + addCriterion("display_area between", value1, value2, "displayArea"); + return (Criteria) this; + } + + public Criteria andDisplayAreaNotBetween(Integer value1, Integer value2) { + addCriterion("display_area not between", value1, value2, "displayArea"); + return (Criteria) this; + } } /** diff --git a/hai-service/src/main/java/com/hai/entity/HighOrder.java b/hai-service/src/main/java/com/hai/entity/HighOrder.java index f3e5f238..558523bb 100644 --- a/hai-service/src/main/java/com/hai/entity/HighOrder.java +++ b/hai-service/src/main/java/com/hai/entity/HighOrder.java @@ -3,6 +3,7 @@ package com.hai.entity; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; +import java.util.List; /** * high_order @@ -24,16 +25,6 @@ public class HighOrder implements Serializable { */ private String orderNo; - /** - * 订单类型 1:卡券 - */ - private Integer orderType; - - /** - * 订单来源id - */ - private Long orderSource; - /** * 用户表ID */ @@ -62,12 +53,12 @@ public class HighOrder implements Serializable { /** * 支付金额 */ - private Float payPrice; + private BigDecimal payPrice; /** * 实付金额 */ - private Float payRealPrice; + private BigDecimal payRealPrice; /** * 支付流水号 @@ -117,6 +108,16 @@ public class HighOrder implements Serializable { private static final long serialVersionUID = 1L; + private List highChildOrderList; + + public List getHighChildOrderList() { + return highChildOrderList; + } + + public void setHighChildOrderList(List highChildOrderList) { + this.highChildOrderList = highChildOrderList; + } + public Long getId() { return id; } @@ -133,22 +134,6 @@ public class HighOrder implements Serializable { this.orderNo = orderNo; } - public Integer getOrderType() { - return orderType; - } - - public void setOrderType(Integer orderType) { - this.orderType = orderType; - } - - public Long getOrderSource() { - return orderSource; - } - - public void setOrderSource(Long orderSource) { - this.orderSource = orderSource; - } - public Long getMemId() { return memId; } @@ -189,19 +174,19 @@ public class HighOrder implements Serializable { this.payGold = payGold; } - public Float getPayPrice() { + public BigDecimal getPayPrice() { return payPrice; } - public void setPayPrice(Float payPrice) { + public void setPayPrice(BigDecimal payPrice) { this.payPrice = payPrice; } - public Float getPayRealPrice() { + public BigDecimal getPayRealPrice() { return payRealPrice; } - public void setPayRealPrice(Float payRealPrice) { + public void setPayRealPrice(BigDecimal payRealPrice) { this.payRealPrice = payRealPrice; } @@ -307,8 +292,6 @@ public class HighOrder implements Serializable { HighOrder other = (HighOrder) that; return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getOrderNo() == null ? other.getOrderNo() == null : this.getOrderNo().equals(other.getOrderNo())) - && (this.getOrderType() == null ? other.getOrderType() == null : this.getOrderType().equals(other.getOrderType())) - && (this.getOrderSource() == null ? other.getOrderSource() == null : this.getOrderSource().equals(other.getOrderSource())) && (this.getMemId() == null ? other.getMemId() == null : this.getMemId().equals(other.getMemId())) && (this.getMemName() == null ? other.getMemName() == null : this.getMemName().equals(other.getMemName())) && (this.getPayModel() == null ? other.getPayModel() == null : this.getPayModel().equals(other.getPayModel())) @@ -335,8 +318,6 @@ public class HighOrder implements Serializable { int result = 1; result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getOrderNo() == null) ? 0 : getOrderNo().hashCode()); - result = prime * result + ((getOrderType() == null) ? 0 : getOrderType().hashCode()); - result = prime * result + ((getOrderSource() == null) ? 0 : getOrderSource().hashCode()); result = prime * result + ((getMemId() == null) ? 0 : getMemId().hashCode()); result = prime * result + ((getMemName() == null) ? 0 : getMemName().hashCode()); result = prime * result + ((getPayModel() == null) ? 0 : getPayModel().hashCode()); @@ -366,8 +347,6 @@ public class HighOrder implements Serializable { sb.append("Hash = ").append(hashCode()); sb.append(", id=").append(id); sb.append(", orderNo=").append(orderNo); - sb.append(", orderType=").append(orderType); - sb.append(", orderSource=").append(orderSource); sb.append(", memId=").append(memId); sb.append(", memName=").append(memName); sb.append(", payModel=").append(payModel); @@ -390,4 +369,4 @@ public class HighOrder implements Serializable { sb.append("]"); return sb.toString(); } -} \ No newline at end of file +} diff --git a/hai-service/src/main/java/com/hai/entity/HighOrderExample.java b/hai-service/src/main/java/com/hai/entity/HighOrderExample.java index 0c3a5794..4e038c4d 100644 --- a/hai-service/src/main/java/com/hai/entity/HighOrderExample.java +++ b/hai-service/src/main/java/com/hai/entity/HighOrderExample.java @@ -256,126 +256,6 @@ public class HighOrderExample { return (Criteria) this; } - public Criteria andOrderTypeIsNull() { - addCriterion("order_type is null"); - return (Criteria) this; - } - - public Criteria andOrderTypeIsNotNull() { - addCriterion("order_type is not null"); - return (Criteria) this; - } - - public Criteria andOrderTypeEqualTo(Integer value) { - addCriterion("order_type =", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeNotEqualTo(Integer value) { - addCriterion("order_type <>", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeGreaterThan(Integer value) { - addCriterion("order_type >", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeGreaterThanOrEqualTo(Integer value) { - addCriterion("order_type >=", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeLessThan(Integer value) { - addCriterion("order_type <", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeLessThanOrEqualTo(Integer value) { - addCriterion("order_type <=", value, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeIn(List values) { - addCriterion("order_type in", values, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeNotIn(List values) { - addCriterion("order_type not in", values, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeBetween(Integer value1, Integer value2) { - addCriterion("order_type between", value1, value2, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderTypeNotBetween(Integer value1, Integer value2) { - addCriterion("order_type not between", value1, value2, "orderType"); - return (Criteria) this; - } - - public Criteria andOrderSourceIsNull() { - addCriterion("order_source is null"); - return (Criteria) this; - } - - public Criteria andOrderSourceIsNotNull() { - addCriterion("order_source is not null"); - return (Criteria) this; - } - - public Criteria andOrderSourceEqualTo(Long value) { - addCriterion("order_source =", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceNotEqualTo(Long value) { - addCriterion("order_source <>", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceGreaterThan(Long value) { - addCriterion("order_source >", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceGreaterThanOrEqualTo(Long value) { - addCriterion("order_source >=", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceLessThan(Long value) { - addCriterion("order_source <", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceLessThanOrEqualTo(Long value) { - addCriterion("order_source <=", value, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceIn(List values) { - addCriterion("order_source in", values, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceNotIn(List values) { - addCriterion("order_source not in", values, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceBetween(Long value1, Long value2) { - addCriterion("order_source between", value1, value2, "orderSource"); - return (Criteria) this; - } - - public Criteria andOrderSourceNotBetween(Long value1, Long value2) { - addCriterion("order_source not between", value1, value2, "orderSource"); - return (Criteria) this; - } - public Criteria andMemIdIsNull() { addCriterion("mem_id is null"); return (Criteria) this; @@ -696,52 +576,52 @@ public class HighOrderExample { return (Criteria) this; } - public Criteria andPayPriceEqualTo(Float value) { + public Criteria andPayPriceEqualTo(BigDecimal value) { addCriterion("pay_price =", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceNotEqualTo(Float value) { + public Criteria andPayPriceNotEqualTo(BigDecimal value) { addCriterion("pay_price <>", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceGreaterThan(Float value) { + public Criteria andPayPriceGreaterThan(BigDecimal value) { addCriterion("pay_price >", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceGreaterThanOrEqualTo(Float value) { + public Criteria andPayPriceGreaterThanOrEqualTo(BigDecimal value) { addCriterion("pay_price >=", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceLessThan(Float value) { + public Criteria andPayPriceLessThan(BigDecimal value) { addCriterion("pay_price <", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceLessThanOrEqualTo(Float value) { + public Criteria andPayPriceLessThanOrEqualTo(BigDecimal value) { addCriterion("pay_price <=", value, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceIn(List values) { + public Criteria andPayPriceIn(List values) { addCriterion("pay_price in", values, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceNotIn(List values) { + public Criteria andPayPriceNotIn(List values) { addCriterion("pay_price not in", values, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceBetween(Float value1, Float value2) { + public Criteria andPayPriceBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_price between", value1, value2, "payPrice"); return (Criteria) this; } - public Criteria andPayPriceNotBetween(Float value1, Float value2) { + public Criteria andPayPriceNotBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_price not between", value1, value2, "payPrice"); return (Criteria) this; } @@ -756,52 +636,52 @@ public class HighOrderExample { return (Criteria) this; } - public Criteria andPayRealPriceEqualTo(Float value) { + public Criteria andPayRealPriceEqualTo(BigDecimal value) { addCriterion("pay_real_price =", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceNotEqualTo(Float value) { + public Criteria andPayRealPriceNotEqualTo(BigDecimal value) { addCriterion("pay_real_price <>", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceGreaterThan(Float value) { + public Criteria andPayRealPriceGreaterThan(BigDecimal value) { addCriterion("pay_real_price >", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceGreaterThanOrEqualTo(Float value) { + public Criteria andPayRealPriceGreaterThanOrEqualTo(BigDecimal value) { addCriterion("pay_real_price >=", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceLessThan(Float value) { + public Criteria andPayRealPriceLessThan(BigDecimal value) { addCriterion("pay_real_price <", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceLessThanOrEqualTo(Float value) { + public Criteria andPayRealPriceLessThanOrEqualTo(BigDecimal value) { addCriterion("pay_real_price <=", value, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceIn(List values) { + public Criteria andPayRealPriceIn(List values) { addCriterion("pay_real_price in", values, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceNotIn(List values) { + public Criteria andPayRealPriceNotIn(List values) { addCriterion("pay_real_price not in", values, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceBetween(Float value1, Float value2) { + public Criteria andPayRealPriceBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_real_price between", value1, value2, "payRealPrice"); return (Criteria) this; } - public Criteria andPayRealPriceNotBetween(Float value1, Float value2) { + public Criteria andPayRealPriceNotBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_real_price not between", value1, value2, "payRealPrice"); return (Criteria) this; } diff --git a/hai-service/src/main/java/com/hai/entity/HighPayRecord.java b/hai-service/src/main/java/com/hai/entity/HighPayRecord.java index a78a31e9..47f0f3b7 100644 --- a/hai-service/src/main/java/com/hai/entity/HighPayRecord.java +++ b/hai-service/src/main/java/com/hai/entity/HighPayRecord.java @@ -1,6 +1,7 @@ package com.hai.entity; import java.io.Serializable; +import java.math.BigDecimal; import java.util.Date; /** @@ -16,7 +17,7 @@ public class HighPayRecord implements Serializable { /** * 主键ID */ - private Long payRecordId; + private Long id; /** * 支付的流水号 @@ -26,17 +27,17 @@ public class HighPayRecord implements Serializable { /** * 流水类型:1:请求,2:响应 */ - private Integer serailState; + private Integer resType; /** - * 支付方式: 1:支付宝 2:微信 3:金币 + * 支付方式: 1:支付宝, 2:微信 */ - private Long payType; + private Integer payType; /** * 支付的金额 */ - private Float payMoney; + private BigDecimal payMoney; /** * 支付订单的时间 @@ -76,12 +77,12 @@ public class HighPayRecord implements Serializable { private static final long serialVersionUID = 1L; - public Long getPayRecordId() { - return payRecordId; + public Long getId() { + return id; } - public void setPayRecordId(Long payRecordId) { - this.payRecordId = payRecordId; + public void setId(Long id) { + this.id = id; } public String getPaySerialNo() { @@ -92,27 +93,27 @@ public class HighPayRecord implements Serializable { this.paySerialNo = paySerialNo; } - public Integer getSerailState() { - return serailState; + public Integer getResType() { + return resType; } - public void setSerailState(Integer serailState) { - this.serailState = serailState; + public void setResType(Integer resType) { + this.resType = resType; } - public Long getPayType() { + public Integer getPayType() { return payType; } - public void setPayType(Long payType) { + public void setPayType(Integer payType) { this.payType = payType; } - public Float getPayMoney() { + public BigDecimal getPayMoney() { return payMoney; } - public void setPayMoney(Float payMoney) { + public void setPayMoney(BigDecimal payMoney) { this.payMoney = payMoney; } @@ -200,9 +201,9 @@ public class HighPayRecord implements Serializable { return false; } HighPayRecord other = (HighPayRecord) that; - return (this.getPayRecordId() == null ? other.getPayRecordId() == null : this.getPayRecordId().equals(other.getPayRecordId())) + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getPaySerialNo() == null ? other.getPaySerialNo() == null : this.getPaySerialNo().equals(other.getPaySerialNo())) - && (this.getSerailState() == null ? other.getSerailState() == null : this.getSerailState().equals(other.getSerailState())) + && (this.getResType() == null ? other.getResType() == null : this.getResType().equals(other.getResType())) && (this.getPayType() == null ? other.getPayType() == null : this.getPayType().equals(other.getPayType())) && (this.getPayMoney() == null ? other.getPayMoney() == null : this.getPayMoney().equals(other.getPayMoney())) && (this.getPayTime() == null ? other.getPayTime() == null : this.getPayTime().equals(other.getPayTime())) @@ -220,9 +221,9 @@ public class HighPayRecord implements Serializable { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((getPayRecordId() == null) ? 0 : getPayRecordId().hashCode()); + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getPaySerialNo() == null) ? 0 : getPaySerialNo().hashCode()); - result = prime * result + ((getSerailState() == null) ? 0 : getSerailState().hashCode()); + result = prime * result + ((getResType() == null) ? 0 : getResType().hashCode()); result = prime * result + ((getPayType() == null) ? 0 : getPayType().hashCode()); result = prime * result + ((getPayMoney() == null) ? 0 : getPayMoney().hashCode()); result = prime * result + ((getPayTime() == null) ? 0 : getPayTime().hashCode()); @@ -243,9 +244,9 @@ public class HighPayRecord implements Serializable { sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); - sb.append(", payRecordId=").append(payRecordId); + sb.append(", id=").append(id); sb.append(", paySerialNo=").append(paySerialNo); - sb.append(", serailState=").append(serailState); + sb.append(", resType=").append(resType); sb.append(", payType=").append(payType); sb.append(", payMoney=").append(payMoney); sb.append(", payTime=").append(payTime); diff --git a/hai-service/src/main/java/com/hai/entity/HighPayRecordExample.java b/hai-service/src/main/java/com/hai/entity/HighPayRecordExample.java index 35d0d969..c2b78aa1 100644 --- a/hai-service/src/main/java/com/hai/entity/HighPayRecordExample.java +++ b/hai-service/src/main/java/com/hai/entity/HighPayRecordExample.java @@ -1,5 +1,6 @@ package com.hai.entity; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -125,63 +126,63 @@ public class HighPayRecordExample { criteria.add(new Criterion(condition, value1, value2)); } - public Criteria andPayRecordIdIsNull() { - addCriterion("pay_record_id is null"); + public Criteria andIdIsNull() { + addCriterion("id is null"); return (Criteria) this; } - public Criteria andPayRecordIdIsNotNull() { - addCriterion("pay_record_id is not null"); + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); return (Criteria) this; } - public Criteria andPayRecordIdEqualTo(Long value) { - addCriterion("pay_record_id =", value, "payRecordId"); + public Criteria andIdEqualTo(Long value) { + addCriterion("id =", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdNotEqualTo(Long value) { - addCriterion("pay_record_id <>", value, "payRecordId"); + public Criteria andIdNotEqualTo(Long value) { + addCriterion("id <>", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdGreaterThan(Long value) { - addCriterion("pay_record_id >", value, "payRecordId"); + public Criteria andIdGreaterThan(Long value) { + addCriterion("id >", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdGreaterThanOrEqualTo(Long value) { - addCriterion("pay_record_id >=", value, "payRecordId"); + public Criteria andIdGreaterThanOrEqualTo(Long value) { + addCriterion("id >=", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdLessThan(Long value) { - addCriterion("pay_record_id <", value, "payRecordId"); + public Criteria andIdLessThan(Long value) { + addCriterion("id <", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdLessThanOrEqualTo(Long value) { - addCriterion("pay_record_id <=", value, "payRecordId"); + public Criteria andIdLessThanOrEqualTo(Long value) { + addCriterion("id <=", value, "id"); return (Criteria) this; } - public Criteria andPayRecordIdIn(List values) { - addCriterion("pay_record_id in", values, "payRecordId"); + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); return (Criteria) this; } - public Criteria andPayRecordIdNotIn(List values) { - addCriterion("pay_record_id not in", values, "payRecordId"); + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); return (Criteria) this; } - public Criteria andPayRecordIdBetween(Long value1, Long value2) { - addCriterion("pay_record_id between", value1, value2, "payRecordId"); + public Criteria andIdBetween(Long value1, Long value2) { + addCriterion("id between", value1, value2, "id"); return (Criteria) this; } - public Criteria andPayRecordIdNotBetween(Long value1, Long value2) { - addCriterion("pay_record_id not between", value1, value2, "payRecordId"); + public Criteria andIdNotBetween(Long value1, Long value2) { + addCriterion("id not between", value1, value2, "id"); return (Criteria) this; } @@ -255,63 +256,63 @@ public class HighPayRecordExample { return (Criteria) this; } - public Criteria andSerailStateIsNull() { - addCriterion("serail_state is null"); + public Criteria andResTypeIsNull() { + addCriterion("res_type is null"); return (Criteria) this; } - public Criteria andSerailStateIsNotNull() { - addCriterion("serail_state is not null"); + public Criteria andResTypeIsNotNull() { + addCriterion("res_type is not null"); return (Criteria) this; } - public Criteria andSerailStateEqualTo(Integer value) { - addCriterion("serail_state =", value, "serailState"); + public Criteria andResTypeEqualTo(Integer value) { + addCriterion("res_type =", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateNotEqualTo(Integer value) { - addCriterion("serail_state <>", value, "serailState"); + public Criteria andResTypeNotEqualTo(Integer value) { + addCriterion("res_type <>", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateGreaterThan(Integer value) { - addCriterion("serail_state >", value, "serailState"); + public Criteria andResTypeGreaterThan(Integer value) { + addCriterion("res_type >", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateGreaterThanOrEqualTo(Integer value) { - addCriterion("serail_state >=", value, "serailState"); + public Criteria andResTypeGreaterThanOrEqualTo(Integer value) { + addCriterion("res_type >=", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateLessThan(Integer value) { - addCriterion("serail_state <", value, "serailState"); + public Criteria andResTypeLessThan(Integer value) { + addCriterion("res_type <", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateLessThanOrEqualTo(Integer value) { - addCriterion("serail_state <=", value, "serailState"); + public Criteria andResTypeLessThanOrEqualTo(Integer value) { + addCriterion("res_type <=", value, "resType"); return (Criteria) this; } - public Criteria andSerailStateIn(List values) { - addCriterion("serail_state in", values, "serailState"); + public Criteria andResTypeIn(List values) { + addCriterion("res_type in", values, "resType"); return (Criteria) this; } - public Criteria andSerailStateNotIn(List values) { - addCriterion("serail_state not in", values, "serailState"); + public Criteria andResTypeNotIn(List values) { + addCriterion("res_type not in", values, "resType"); return (Criteria) this; } - public Criteria andSerailStateBetween(Integer value1, Integer value2) { - addCriterion("serail_state between", value1, value2, "serailState"); + public Criteria andResTypeBetween(Integer value1, Integer value2) { + addCriterion("res_type between", value1, value2, "resType"); return (Criteria) this; } - public Criteria andSerailStateNotBetween(Integer value1, Integer value2) { - addCriterion("serail_state not between", value1, value2, "serailState"); + public Criteria andResTypeNotBetween(Integer value1, Integer value2) { + addCriterion("res_type not between", value1, value2, "resType"); return (Criteria) this; } @@ -325,52 +326,52 @@ public class HighPayRecordExample { return (Criteria) this; } - public Criteria andPayTypeEqualTo(Long value) { + public Criteria andPayTypeEqualTo(Integer value) { addCriterion("pay_type =", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeNotEqualTo(Long value) { + public Criteria andPayTypeNotEqualTo(Integer value) { addCriterion("pay_type <>", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeGreaterThan(Long value) { + public Criteria andPayTypeGreaterThan(Integer value) { addCriterion("pay_type >", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeGreaterThanOrEqualTo(Long value) { + public Criteria andPayTypeGreaterThanOrEqualTo(Integer value) { addCriterion("pay_type >=", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeLessThan(Long value) { + public Criteria andPayTypeLessThan(Integer value) { addCriterion("pay_type <", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeLessThanOrEqualTo(Long value) { + public Criteria andPayTypeLessThanOrEqualTo(Integer value) { addCriterion("pay_type <=", value, "payType"); return (Criteria) this; } - public Criteria andPayTypeIn(List values) { + public Criteria andPayTypeIn(List values) { addCriterion("pay_type in", values, "payType"); return (Criteria) this; } - public Criteria andPayTypeNotIn(List values) { + public Criteria andPayTypeNotIn(List values) { addCriterion("pay_type not in", values, "payType"); return (Criteria) this; } - public Criteria andPayTypeBetween(Long value1, Long value2) { + public Criteria andPayTypeBetween(Integer value1, Integer value2) { addCriterion("pay_type between", value1, value2, "payType"); return (Criteria) this; } - public Criteria andPayTypeNotBetween(Long value1, Long value2) { + public Criteria andPayTypeNotBetween(Integer value1, Integer value2) { addCriterion("pay_type not between", value1, value2, "payType"); return (Criteria) this; } @@ -385,52 +386,52 @@ public class HighPayRecordExample { return (Criteria) this; } - public Criteria andPayMoneyEqualTo(Float value) { + public Criteria andPayMoneyEqualTo(BigDecimal value) { addCriterion("pay_money =", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyNotEqualTo(Float value) { + public Criteria andPayMoneyNotEqualTo(BigDecimal value) { addCriterion("pay_money <>", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyGreaterThan(Float value) { + public Criteria andPayMoneyGreaterThan(BigDecimal value) { addCriterion("pay_money >", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyGreaterThanOrEqualTo(Float value) { + public Criteria andPayMoneyGreaterThanOrEqualTo(BigDecimal value) { addCriterion("pay_money >=", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyLessThan(Float value) { + public Criteria andPayMoneyLessThan(BigDecimal value) { addCriterion("pay_money <", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyLessThanOrEqualTo(Float value) { + public Criteria andPayMoneyLessThanOrEqualTo(BigDecimal value) { addCriterion("pay_money <=", value, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyIn(List values) { + public Criteria andPayMoneyIn(List values) { addCriterion("pay_money in", values, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyNotIn(List values) { + public Criteria andPayMoneyNotIn(List values) { addCriterion("pay_money not in", values, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyBetween(Float value1, Float value2) { + public Criteria andPayMoneyBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_money between", value1, value2, "payMoney"); return (Criteria) this; } - public Criteria andPayMoneyNotBetween(Float value1, Float value2) { + public Criteria andPayMoneyNotBetween(BigDecimal value1, BigDecimal value2) { addCriterion("pay_money not between", value1, value2, "payMoney"); return (Criteria) this; } diff --git a/hai-service/src/main/java/com/hai/service/HighOrderService.java b/hai-service/src/main/java/com/hai/service/HighOrderService.java new file mode 100644 index 00000000..5e163c17 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/HighOrderService.java @@ -0,0 +1,50 @@ +package com.hai.service; + +import com.hai.entity.HighOrder; + +import java.util.List; +import java.util.Map; + +/** + * @Auther: 胡锐 + * @Description: + * @Date: 2021/3/26 23:04 + */ +public interface HighOrderService { + + /** + * @Author 胡锐 + * @Description 增加订单 + * @Date 2021/3/26 23:05 + **/ + void insertOrder(HighOrder highOrder); + + /** + * @Author 胡锐 + * @Description 修改订单 + * @Date 2021/3/26 23:06 + **/ + void updateOrder(HighOrder highOrder); + + /** + * @Author 胡锐 + * @Description 根据id查询 + * @Date 2021/3/26 23:06 + **/ + HighOrder getOrderById(Long id); + + /** + * @Author 胡锐 + * @Description 根据订单号查询 + * @Date 2021/3/27 0:38 + **/ + HighOrder getOrderByOrderNo(String orderNo); + + /** + * @Author 胡锐 + * @Description 查询订单列表 + * @Date 2021/3/26 23:06 + **/ + List getOrderList(Map map); + +} diff --git a/hai-service/src/main/java/com/hai/service/impl/HighOrderServiceImpl.java b/hai-service/src/main/java/com/hai/service/impl/HighOrderServiceImpl.java new file mode 100644 index 00000000..9094f5c5 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/impl/HighOrderServiceImpl.java @@ -0,0 +1,95 @@ +package com.hai.service.impl; + +import com.hai.dao.HighChildOrderMapper; +import com.hai.dao.HighOrderMapper; +import com.hai.entity.HighChildOrder; +import com.hai.entity.HighChildOrderExample; +import com.hai.entity.HighOrder; +import com.hai.entity.HighOrderExample; +import com.hai.service.HighOrderService; +import org.apache.commons.collections4.MapUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +/** + * @Auther: 胡锐 + * @Description: + * @Date: 2021/3/26 23:06 + */ +@Service("highOrderService") +public class HighOrderServiceImpl implements HighOrderService { + + @Resource + private HighOrderMapper highOrderMapper; + + @Resource + private HighChildOrderMapper highChildOrderMapper; + + @Override + @Transactional(propagation= Propagation.REQUIRES_NEW) + public void insertOrder(HighOrder highOrder) { + highOrderMapper.insert(highOrder); + + for (HighChildOrder childOrder : highOrder.getHighChildOrderList()) { + childOrder.setOrderId(highOrder.getId()); + highChildOrderMapper.insert(childOrder); + } + } + + @Override + public void updateOrder(HighOrder highOrder) { + + } + + @Override + public HighOrder getOrderById(Long id) { + HighOrder order = highOrderMapper.selectByPrimaryKey(id); + if (order == null) { + return null; + } + + HighChildOrderExample example = new HighChildOrderExample(); + example.createCriteria().andOrderIdEqualTo(order.getId()); + order.setHighChildOrderList(highChildOrderMapper.selectByExample(example)); + + return order; + } + + @Override + public HighOrder getOrderByOrderNo(String orderNo) { + HighOrderExample example = new HighOrderExample(); + example.createCriteria().andOrderNoEqualTo(orderNo); + + List list = highOrderMapper.selectByExample(example); + if (list != null && list.size() > 0) { + return getOrderById(list.get(0).getId()); + } + return null; + } + + @Override + public List getOrderList(Map map) { + HighOrderExample example = new HighOrderExample(); + HighOrderExample.Criteria criteria = example.createCriteria(); + + if (MapUtils.getLong(map, "memId") != null) { + criteria.andMemIdEqualTo(MapUtils.getLong(map, "memId")); + } + + if (MapUtils.getInteger(map, "status") != null) { + criteria.andOrderStatusEqualTo(MapUtils.getInteger(map, "status")); + } + + if (MapUtils.getString(map, "orderNo") != null) { + criteria.andOrderNoEqualTo(MapUtils.getString(map, "orderNo")); + } + + example.setOrderByClause("create_time desc"); + return highOrderMapper.selectByExample(example); + } +} diff --git a/hai-service/src/main/java/com/hai/service/pay/NotifyService.java b/hai-service/src/main/java/com/hai/service/pay/NotifyService.java new file mode 100644 index 00000000..7c567461 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/NotifyService.java @@ -0,0 +1,30 @@ +package com.hai.service.pay; + +import java.util.Map; + +/** + * @Description 支付宝/微信 支付回调 + * @author gongjia + * @date 2020/3/27 15:30 + * @Copyright 2019 www.shinwoten.com Inc. All rights reserved. + */ +public interface NotifyService { + + /** + * + * @Title alipayNotify + * @Description 支付宝 验签成功后业务调用 + * @author gongjia + * @param paramsMap 异步回调返回的参数 + */ + String alipayNotify(Map paramsMap) throws Exception; + + /** + * + * @Title alipayNotify + * @Description 微信 验签成功后业务调用 + * @author gongjia + * @param paramsMap 异步回调返回的参数 + */ + String wechatNotify(Map paramsMap) throws Exception; +} diff --git a/hai-service/src/main/java/com/hai/service/pay/PayRecordService.java b/hai-service/src/main/java/com/hai/service/pay/PayRecordService.java new file mode 100644 index 00000000..11a06446 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/PayRecordService.java @@ -0,0 +1,30 @@ +package com.hai.service.pay; + +import com.hai.entity.HighPayRecord; + +import java.util.Map; + +/** + * @ClassName: PayRecordService + * @Description: 支付纪录 + * @author: gongjia + * @date: 2020/3/27 9:48 + * @Copyright: 2019 www.shinwoten.com Inc. All rights reserved. + */ +public interface PayRecordService { + + /** + * + * @author gongjia + * @param paramsMap 支付纪录信息(支付宝或微信回调传回的信息) + * @param payType 支付方式:Alipay-支付宝 WechatPay-微信 + */ + int addPayRecord(Map paramsMap, String payType) throws Exception; + + /** + * @desc 插入支付纪录 + * @author gongjia + */ + int addPayRecord(HighPayRecord payRecord) throws Exception; + +} diff --git a/hai-service/src/main/java/com/hai/service/pay/PayService.java b/hai-service/src/main/java/com/hai/service/pay/PayService.java new file mode 100644 index 00000000..f3b47bf1 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/PayService.java @@ -0,0 +1,21 @@ +package com.hai.service.pay; + +import java.util.Map; + +/** + * @ClassName: PayService + * @Description: 支付完成 不同模块实际的业务处理 + * @author: gongjia + * @date: 2020/3/27 16:28 + * @Copyright: 2019 www.shinwoten.com Inc. All rights reserved. + */ +public interface PayService { + + /** + * @desc 不同模块实际的业务处理 + * @param map 支付宝/微信 异步回调返回的参数 + * @param payType 支付方式:Alipay-支付宝 WechatPay-微信 + */ + void paySuccess(Map map, String payType) throws Exception; + +} diff --git a/hai-service/src/main/java/com/hai/service/pay/impl/GoodsOrderServiceImpl.java b/hai-service/src/main/java/com/hai/service/pay/impl/GoodsOrderServiceImpl.java new file mode 100644 index 00000000..f43acae0 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/impl/GoodsOrderServiceImpl.java @@ -0,0 +1,39 @@ +package com.hai.service.pay.impl; + +import com.alibaba.fastjson.JSONObject; +import com.hai.entity.HighOrder; +import com.hai.service.HighOrderService; +import com.hai.service.pay.PayService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * @Auther: 胡锐 + * @Description: + * @Date: 2021/3/27 00:35 + */ +@Service("goodsOrderService") +public class GoodsOrderServiceImpl implements PayService { + + @Resource + private HighOrderService highOrderService; + + @Override + public void paySuccess(Map map, String payType) throws Exception { + if (payType.equals("Alipay")) { + // 支付宝支付 todo 暂未开发 + return; + } + if (payType.equals("WechatPay")) { + HighOrder order = highOrderService.getOrderByOrderNo(map.get("out_trade_no")); + if (order == null) { + + } + } + } +} diff --git a/hai-service/src/main/java/com/hai/service/pay/impl/NotifyServiceImpl.java b/hai-service/src/main/java/com/hai/service/pay/impl/NotifyServiceImpl.java new file mode 100644 index 00000000..c81c165c --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/impl/NotifyServiceImpl.java @@ -0,0 +1,121 @@ +package com.hai.service.pay.impl; + +import com.alibaba.fastjson.JSONObject; +import com.hai.common.pay.entity.OrderType; +import com.hai.common.utils.SpringContextUtil; +import com.hai.service.pay.NotifyService; +import com.hai.service.pay.PayRecordService; +import com.hai.service.pay.PayService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Map; + +@Service(value = "notifyService") +public class NotifyServiceImpl implements NotifyService { + + private static Logger log = LoggerFactory.getLogger(NotifyServiceImpl.class); + @Resource + private PayRecordService payRecordService; + + @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public String alipayNotify(Map params) throws Exception { + String result = "failure"; + String trade_status = params.get("trade_status"); + if ("TRADE_SUCCESS".equals(trade_status)) { + // 交易支付成功 默认触发 + + String orderType = params.get("passback_params"); + PayService payService = getPayService(orderType); + if (payService != null) { + payService.paySuccess(params, "Alipay"); // 商户内部实际的交易业务处理 + log.info("支付宝异步通知 -> 业务处理完成"); + result = "success"; + } else { + log.info("支付宝异步通知 -> 业务处理:payService获取失败"); + } + + } else if ("TRADE_CLOSED".equals(trade_status)) { + // 未付款交易超时关闭,或支付完成后全额退款 默认触发 + + // todo 业务流程 + + log.info("支付宝异步通知 -> 未付款交易超时关闭,或支付完成后全额退款"); + result = "success"; + } else if ("WAIT_BUYER_PAY".equals(trade_status)) { + // 交易创建,等待买家付款 默认不触发 + + // todo 业务流程 + + log.info("支付宝异步通知 -> 交易创建,等待买家付款"); + result = "success"; + } else if ("TRADE_FINISHED".equals(trade_status)) { + // 交易结束,不可退款 默认不触发 + + // todo 业务流程 + + log.info("支付宝异步通知 -> 交易结束,不可退款"); + result = "success"; + } + + // 增加支付纪录(实际是支付宝回调纪录) + payRecordService.addPayRecord(params, "Alipay"); + return result; + } + + @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) + public String wechatNotify(Map paramsMap) throws Exception { + String resXml = null; + + if ("SUCCESS".equals(paramsMap.get("return_code")) && "SUCCESS".equals(paramsMap.get("result_code"))) { + log.info("微信支付 -> 异步通知:支付成功,进入订单处理"); + String orderScene = paramsMap.get("attach"); + JSONObject object = JSONObject.parseObject(orderScene); + // 订单类型 + String orderType = object.getString("orderScene"); + PayService payService = getPayService(orderType); + if (payService != null) { + payService.paySuccess(paramsMap, "WechatPay"); // 商户内部实际的交易业务处理 + log.info("微信支付 -> 异步通知:订单处理完成"); + } else { + log.error("微信支付 -> 异步通知:业务处理,payService获取失败"); + } + + // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了 + resXml = "" + "" + + "" + " "; + } else { + log.error("微信支付 -> 异步通知:支付失败,错误信息:" + paramsMap.get("err_code_des")); + resXml = "" + "" + "" + " "; + } + + if ("SUCCESS".equals(paramsMap.get("return_code"))) { + // 增加支付纪录(实际是微信回调纪录) + payRecordService.addPayRecord(paramsMap, "WechatPay"); + } + return resXml; + } + + /** + * @desc 根据回调回传参数 选择业务service + * @param orderType 订单类型(回传参数) + */ + private PayService getPayService(String orderType) throws Exception{ + PayService payService = null; + for (OrderType item : OrderType.values()) { + if (item.getModuleCode().equals(orderType)) { + payService = (PayService) SpringContextUtil.getBean(item.getService()); + break; + } + } + + return payService; + } +} diff --git a/hai-service/src/main/java/com/hai/service/pay/impl/PayRecordServiceImpl.java b/hai-service/src/main/java/com/hai/service/pay/impl/PayRecordServiceImpl.java new file mode 100644 index 00000000..f4610591 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/impl/PayRecordServiceImpl.java @@ -0,0 +1,60 @@ +package com.hai.service.pay.impl; + +import com.alibaba.fastjson.JSONObject; +import com.hai.common.utils.DateUtil; +import com.hai.dao.HighPayRecordMapper; +import com.hai.entity.HighPayRecord; +import com.hai.service.pay.PayRecordService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Date; +import java.util.Map; + +@Service(value = "payRecordService") +public class PayRecordServiceImpl implements PayRecordService { + + @Resource + private HighPayRecordMapper payRecordMapper; + + @Override + public int addPayRecord(Map paramsMap, String payType) throws Exception { + HighPayRecord payRecord = new HighPayRecord(); + if ("Alipay".equals(payType)) { + + payRecord.setPaySerialNo(paramsMap.get("trade_no")); + payRecord.setResType(2); + payRecord.setPayType(1); + payRecord.setPayMoney(new BigDecimal(paramsMap.get("receipt_amount"))); + payRecord.setPayTime(DateUtil.StringToDate(paramsMap.get("gmt_payment"), "yyyy-MM-dd HH:mm:ss")); + payRecord.setBodyInfo(JSONObject.toJSONString(paramsMap)); + payRecord.setPayResult(paramsMap.get("trade_status")); + + } else if ("WechatPay".equals(payType)) { + + payRecord.setPaySerialNo(paramsMap.get("transaction_id")); + payRecord.setResType(2); + payRecord.setPayType(2); + payRecord.setPayMoney(new BigDecimal(paramsMap.get("cash_fee")).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP)); + payRecord.setPayTime(DateUtil.StringToDate(paramsMap.get("time_end"), "yyyyMMddHHmmss")); + payRecord.setBodyInfo(JSONObject.toJSONString(paramsMap)); + payRecord.setPayResult(paramsMap.get("result_code")); + + } else { + return 0; + } + + payRecord.setCreateTime(new Date()); + return payRecordMapper.insertSelective(payRecord); + } + + @Override + public int addPayRecord(HighPayRecord payRecord) throws Exception { + + payRecord.setCreateTime(new Date()); + return payRecordMapper.insertSelective(payRecord); + } + +} diff --git a/hai-service/src/main/java/com/hai/service/pay/impl/TestPayService.java b/hai-service/src/main/java/com/hai/service/pay/impl/TestPayService.java new file mode 100644 index 00000000..f397d9a0 --- /dev/null +++ b/hai-service/src/main/java/com/hai/service/pay/impl/TestPayService.java @@ -0,0 +1,23 @@ +package com.hai.service.pay.impl; + +import com.hai.service.pay.PayService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service(value = "testPayService") +public class TestPayService implements PayService { + + private static Logger log = LoggerFactory.getLogger(TestPayService.class); + + @Override + public void paySuccess(Map map, String payType) throws Exception { + log.info("AlipayNotify Test --------> start"); + System.out.println("\nAlipayNotify Test --------> start"); + System.out.println("\nAlipayNotify Test --------> done"); + log.info("AlipayNotify Test --------> done"); + } + +}