diff --git a/order/src/main/java/com/order/controller/OrderPayController.java b/order/src/main/java/com/order/controller/OrderPayController.java index b2e1c1b..2543c2b 100644 --- a/order/src/main/java/com/order/controller/OrderPayController.java +++ b/order/src/main/java/com/order/controller/OrderPayController.java @@ -18,6 +18,7 @@ import com.hfkj.service.order.BsOrderChildService; import com.hfkj.service.order.BsOrderService; import com.hfkj.service.order.OrderPayService; import com.hfkj.service.pay.HuiPayService; +import com.hfkj.service.pay.huift.TradeService; import com.hfkj.sysenum.UserCardTypeEnum; import com.hfkj.sysenum.mer.PayPlatformEnum; import com.hfkj.sysenum.order.OrderPayChannelEnum; @@ -59,6 +60,8 @@ public class OrderPayController { @Resource private BsUserCardService userCardService; @Resource + private TradeService huiftTradeService; + @Resource private BsMerPayConfigService merPayConfigService; @RequestMapping(value="/wechat",method = RequestMethod.POST) @@ -145,6 +148,47 @@ public class OrderPayController { } } + @RequestMapping(value="/huiftPay",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "贵行V家园小程序支付") + public ResponseData huiftPay(@RequestBody JSONObject body) { + try { + if (body == null|| StringUtils.isBlank(body.getString("orderNo"))) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + // 查询订单 + OrderModel order = orderService.getDetail(body.getString("orderNo")); + if (order == null) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的订单号"); + } + if (order.getOrderStatus().equals(OrderStatusEnum.status2.getCode())) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "交易订单不处于待支付"); + } + order.setPayType(OrderPayTypeEnum.type2.getCode()); + Long merId = order.getOrderChildList().get(0).getMerId(); + // 查询平台 + BsMerPayConfig merPay = merPayConfigService.getMerPay(merId, PayPlatformEnum.type3); + if (merPay == null) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "商户未配置支付"); + } + // 请求支付渠道 + JSONObject thirdPreOrder = huiftTradeService.thirdPreOrder(order); + for (OrderChildModel orderChild : order.getOrderChildList()) { + orderChild.setSettleAccount(merPay.getPayMerNo()); + orderChild.setSettleAccountKey(merPay.getPayMerKey()); + orderChildService.editData(orderChild); + } + order.setPayChannelOrderNo(thirdPreOrder.getString("preOrderNo")); + orderService.editData(order); + + orderService.cacheDelete(order.getOrderNo()); + return ResponseMsgUtil.success(thirdPreOrder); + } catch (Exception e) { + log.error("error!",e); + return ResponseMsgUtil.exception(e); + } + } + @RequestMapping(value = "/cardPay", method = RequestMethod.POST) @ResponseBody @ApiOperation(value = "卡支付") diff --git a/order/src/main/java/com/order/controller/OrderPayNotifyController.java b/order/src/main/java/com/order/controller/OrderPayNotifyController.java index 6d056f4..13d1088 100644 --- a/order/src/main/java/com/order/controller/OrderPayNotifyController.java +++ b/order/src/main/java/com/order/controller/OrderPayNotifyController.java @@ -11,6 +11,7 @@ import com.hfkj.sysenum.order.OrderPayTypeEnum; import com.hfkj.sysenum.order.OrderStatusEnum; 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.stereotype.Controller; @@ -20,8 +21,11 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; import java.io.PrintWriter; +import java.net.URLDecoder; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -87,4 +91,42 @@ public class OrderPayNotifyController { } } + @RequestMapping(value = "/huiftPay", method = RequestMethod.POST) + @ApiOperation(value = "贵行V家园小程序支付 -> 异步回调") + public void huiftPay(@RequestBody String params, HttpServletRequest request, HttpServletResponse response) { + try { + log.info("===============贵行V家园小程序支付回调start=================="); + log.info("回调参数: " + params); + if (StringUtils.isNotBlank(params)) { + // 参数解码 + String paramsStr = URLDecoder.decode(params,"utf-8"); + JSONObject body = JSONObject.parseObject(paramsStr); + log.info("开始处理订单: " + body.getString("outTradeNo")); + + // 查询订单信息 + OrderModel order = orderService.getDetail(body.getString("outTradeNo")); + if (order != null && order.getOrderStatus().equals(OrderStatusEnum.status1.getCode())) { + log.info("开始处理业务"); + // 处理订单业务 + order.setPayChannel(OrderPayChannelEnum.type3.getCode()); + order.setPayType(OrderPayTypeEnum.type3.getCode()); + order.setPayTime(new Date(body.getLong("payTime"))); + order.setPaySerialNo(body.getString("bankTraceNo")); + orderService.orderPaySuccessHandle(order); + } + log.info("处理业务完成"); + } + BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); + JSONObject result = new JSONObject(); + result.put("messagecode", "0"); + result.put("message", "回调成功"); + out.write(result.toJSONString().getBytes()); + out.flush(); + out.close(); + } catch (Exception e) { + log.error("订单处理异常", e); + } finally { + log.info("===============贵行V家园小程序支付回调end=================="); + } + } } diff --git a/service/src/main/java/com/hfkj/config/CommonSysConfig.java b/service/src/main/java/com/hfkj/config/CommonSysConfig.java index 80ea550..aba5d24 100644 --- a/service/src/main/java/com/hfkj/config/CommonSysConfig.java +++ b/service/src/main/java/com/hfkj/config/CommonSysConfig.java @@ -11,6 +11,11 @@ import org.springframework.stereotype.Component; @Data public class CommonSysConfig { + /** + * 普惠GO域名地址 + */ + private String domainName; + /** * 微信小程序appid */ @@ -98,4 +103,10 @@ public class CommonSysConfig { private String etcChannelCode; private String etcPublicKey; private String etcPrivateKey; + + // 贵行V家园小程序支付 + private String huiftReqUrl; + private String huiftShopCode; + private String huiftSignSecret; + } diff --git a/service/src/main/java/com/hfkj/service/order/impl/BsOrderRefundServiceImpl.java b/service/src/main/java/com/hfkj/service/order/impl/BsOrderRefundServiceImpl.java index a48a6ae..2b0c3e3 100644 --- a/service/src/main/java/com/hfkj/service/order/impl/BsOrderRefundServiceImpl.java +++ b/service/src/main/java/com/hfkj/service/order/impl/BsOrderRefundServiceImpl.java @@ -19,6 +19,7 @@ import com.hfkj.service.order.BsOrderChildService; import com.hfkj.service.order.BsOrderRefundService; import com.hfkj.service.order.BsOrderService; import com.hfkj.service.pay.HuiPayService; +import com.hfkj.service.pay.huift.TradeService; import com.hfkj.service.user.UserIntegralService; import com.hfkj.sysenum.UserIntegralRecordOpUserTypeEnum; import com.hfkj.sysenum.UserIntegralRecordSourceTypeEnum; @@ -57,6 +58,8 @@ public class BsOrderRefundServiceImpl implements BsOrderRefundService { private UserIntegralService userIntegralService; @Resource private BsMerPayConfigService merPayConfigService; + @Resource + private TradeService huiftTradeService; @Override public void editData(BsOrderRefund data) { data.setUpdateTime(new Date()); @@ -89,12 +92,13 @@ public class BsOrderRefundServiceImpl implements BsOrderRefundService { editData(orderRefund); } - }/* else if (OrderPayChannelEnum.type2.getCode() == orderRefund.getRefundPayChannel()) { - // TODO 暂无该支付方式 - - } else if (OrderPayChannelEnum.type3.getCode() ==orderRefund.getRefundPayChannel()) { - // TODO 暂无该支付方式 - }*/ else { + } else if (OrderPayChannelEnum.type3.getCode() == orderRefund.getRefundPayChannel()) { + // 商户退款 + JSONObject refundObj = huiftTradeService.thirdPayRefund(orderRefund.getRefundOrderNo(), orderRefund.getRefundPrice(), orderRefund.getOrderNo()); + orderRefund.setRefundSerialNo(refundObj.getString("refundTraceNo")); + orderRefund.setRefundPayChannelOrderNo(refundObj.getString("refundOrderNo")); + return true; + } else { throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败!该支付方式暂不支持退款"); } } catch (BaseException e) { diff --git a/service/src/main/java/com/hfkj/service/pay/huift/TradeService.java b/service/src/main/java/com/hfkj/service/pay/huift/TradeService.java new file mode 100644 index 0000000..45b471e --- /dev/null +++ b/service/src/main/java/com/hfkj/service/pay/huift/TradeService.java @@ -0,0 +1,109 @@ +package com.hfkj.service.pay.huift; + +import com.alibaba.fastjson.JSONObject; +import com.hfkj.common.exception.ErrorCode; +import com.hfkj.common.exception.ErrorHelp; +import com.hfkj.common.exception.SysCode; +import com.hfkj.common.utils.HttpsUtils; +import com.hfkj.config.CommonSysConst; +import com.hfkj.entity.BsOrder; +import com.hfkj.model.order.OrderModel; +import com.hfkj.service.order.BsOrderService; +import com.hfkj.service.pay.huift.config.HuiftConfig; +import com.hfkj.sysenum.order.OrderPayTypeEnum; +import com.hfkj.sysenum.order.OrderStatusEnum; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +/** + * @className: TradeService + * @author: HuRui + * @date: 2024/4/7 + **/ +@Component +public class TradeService { + + @Resource + private BsOrderService orderService; + + /** + * 交易-预下单 + * @param order + * @return + * @throws Exception + */ + public JSONObject thirdPreOrder(OrderModel order) throws Exception { + Map param = new HashMap<>(); + param.put("shopCode", HuiftConfig.shopcode); + param.put("outTradeNo", order.getOrderNo()); + param.put("transAmt", order.getPayRealPrice().multiply(new BigDecimal("100")).intValue()); + param.put("mobileNbr", order.getUserPhone()); // 用户标识 + param.put("callbackUrl", CommonSysConst.getSysConfig().getDomainName() + "/order/payNotify/huiftPay"); + // param.put("remark", ""); // 备注 + // param.put("outAppId", ""); + param.put("outRedirectPath", CommonSysConst.getSysConfig().getDomainName()+"/phg/#/pages/user/order_list/order_list?tbIndex=-1"); + param.put("sign", HuiftConfig.md5Encode(HuiftConfig.paramSort(param, HuiftConfig.signSecret).getBytes()).toLowerCase()); + JSONObject response = HttpsUtils.doPost(HuiftConfig.reqUrl + "/hfq/v1/thirdPay/thirdPreOrder", JSONObject.toJSONString(param)); + if (response.getString("status").equals("ok")) { + return response.getJSONObject("data"); + } + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR , response.getString("message")); + } + + /** + * 查询交易结果 + * @param preOrderNo + * @return + * @throws Exception + */ + public JSONObject thirdPayResult(String preOrderNo) throws Exception { + Map param = new HashMap<>(); + param.put("shopCode", HuiftConfig.shopcode); + param.put("preOrderNo", preOrderNo); + param.put("sign", HuiftConfig.md5Encode(HuiftConfig.paramSort(param, HuiftConfig.signSecret).getBytes()).toLowerCase()); + JSONObject response = HttpsUtils.doPost(HuiftConfig.reqUrl + "/hfq/v1/thirdPay/thirdPayResult", JSONObject.toJSONString(param)); + if (response.getString("status").equals("ok")) { + return response.getJSONObject("data"); + } + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR , response.getString("message")); + } + + /** + * 交易退款 + * @param refundOrderNo 退款订单号 + * @param refundPrice 退款金额 + * @param orderNo 订单号 + * @return + * @throws Exception + */ + public JSONObject thirdPayRefund(String refundOrderNo, BigDecimal refundPrice, String orderNo) throws Exception { + // 查询订单 + BsOrder order = orderService.getOrder(orderNo); + if (order == null) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的的订单"); + } + if (!order.getOrderStatus().equals(OrderStatusEnum.status2.getCode()) + && !order.getOrderStatus().equals(OrderStatusEnum.status3.getCode())) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单当前状态无法退款"); + } + if (!order.getPayType().equals(OrderPayTypeEnum.type3.getCode())) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "支付方式错误"); + } + Map param = new HashMap<>(); + param.put("shopCode", HuiftConfig.shopcode); + param.put("preOrderNo", order.getPayChannelOrderNo()); + param.put("outRefundNo", refundOrderNo); + param.put("refundAmt", refundPrice.multiply(new BigDecimal("100")).intValue()); + param.put("sign", HuiftConfig.md5Encode(HuiftConfig.paramSort(param, HuiftConfig.signSecret).getBytes()).toLowerCase()); + JSONObject response = HttpsUtils.doPost(HuiftConfig.reqUrl + "/hfq/v1/thirdPay/thirdPayRefund", JSONObject.toJSONString(param)); + if (response.getString("status").equals("ok")) { + return response.getJSONObject("data"); + } + throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR , response.getString("message")); + } + +} diff --git a/service/src/main/java/com/hfkj/service/pay/huift/config/HuiftConfig.java b/service/src/main/java/com/hfkj/service/pay/huift/config/HuiftConfig.java new file mode 100644 index 0000000..39625db --- /dev/null +++ b/service/src/main/java/com/hfkj/service/pay/huift/config/HuiftConfig.java @@ -0,0 +1,59 @@ +package com.hfkj.service.pay.huift.config; + +import com.hfkj.config.CommonSysConst; +import org.apache.commons.lang3.StringUtils; + +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * @className: HuiftConfig + * @author: HuRui + * @date: 2024/4/7 + **/ +public class HuiftConfig { + + public final static String reqUrl = CommonSysConst.getSysConfig().getHuiftReqUrl(); + public final static String shopcode = CommonSysConst.getSysConfig().getHuiftShopCode(); + public final static String signSecret = CommonSysConst.getSysConfig().getHuiftSignSecret(); + + /** + * 参数排序 + * @param param + * @return + */ + public static String paramSort(final Map param, String key) { + Set keySet = param.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (StringUtils.isBlank(sb.toString())) { + sb.append(k).append("=").append(param.get(k)); + } else { + sb.append("&").append(k).append("=").append(param.get(k)); + } + } + sb.append(key); + return sb.toString(); + } + + /** + * MD5加密 + * @param data + * @return + * @throws Exception + */ + public static String md5Encode(byte[] data) throws Exception { + // 初始化MessageDigest + MessageDigest md = MessageDigest.getInstance("MD5"); + // 执行摘要信息 + byte[] digest = md.digest(data); + // 将摘要信息转换为32位的十六进制字符串 + return new String(new HexBinaryAdapter().marshal(digest)); + } + +} diff --git a/service/src/main/java/com/hfkj/sysenum/mer/PayPlatformEnum.java b/service/src/main/java/com/hfkj/sysenum/mer/PayPlatformEnum.java index 172b744..2ebfbee 100644 --- a/service/src/main/java/com/hfkj/sysenum/mer/PayPlatformEnum.java +++ b/service/src/main/java/com/hfkj/sysenum/mer/PayPlatformEnum.java @@ -6,14 +6,19 @@ import lombok.Getter; public enum PayPlatformEnum { /** - * 菜单 + * 惠支付 */ type1(1, "惠支付"), /** - * 按钮 + * 工会卡 */ type2(2, "工会卡"), + + /** + * 贵州银行 + */ + type3(3, "贵州银行"), ; private int code; diff --git a/service/src/main/resources/dev/commonConfig.properties b/service/src/main/resources/dev/commonConfig.properties index 27c3704..d1951a0 100644 --- a/service/src/main/resources/dev/commonConfig.properties +++ b/service/src/main/resources/dev/commonConfig.properties @@ -1,4 +1,6 @@ +domainName=https://phgcs.dctpay.com + wechatMpAppid=wxa075e8509802f826 wechatMpSecret=0e606fc1378d35e359fcf3f15570b2c5 @@ -50,3 +52,7 @@ etcPostUrl = https://test.djien-qr.com/ etcChannelCode = GZETCFXQD etcPublicKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMyQb5gR1rweB5oHKqRPJtJjLQKsn5PXOVfaNdGt/2kPkHvRdN3L9zOaAvFEXcEl2V0sg3D8a+2Sfy1YANAZvjscTQYOaoFl+LVyQZvgyyX8RQw+26Jmbqh8DwenUbNf7DFYVSDxIMBLOiWPkGsYGFONjsUVmfykSeVTcEgQB3VwIDAQAB etcPrivateKey = MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAO8+KWh/OmBahFk7TWOEjPl13BT5NdlbGvQ/311Yua6CQqul9w1DIR2TwFUUh/Bko/eVoLROfF2XVjHbw2bImTdJ7y9C3511HI59YPNzqyql0DHjLxbH0VW92eUgk8mG09wtrUMu1ImN0b7aFE3uqAgz6pwh3TUiQWsDWz+l/MG7AgMBAAECgYEA7nYsOd8OpbmzT2m/omEdTwz9993KocKgZDJCBj4InftyTrrXO93cZSm/PE6BjMgTcxUuIGpWpcbRgFLHOmzZ4Qd+k/6Yb1ErMTfdGlgrxv2B+vztWYfjmFzEiXpecFH47ED6iYrrqm14X3InpnBv4rUkGdqqNbyPGgTO2ncs/3kCQQD+xqRAQSb/TROlqJdO91y6z9v0PO2GLmokqYg444rKYZKhDE0tdJeLU/sfK8SMg5+SlwdQm4nlo8EDJ/w2CEn3AkEA8GRqVkKgIuH413/a6+luYDjlf30WY7Mi1sm3QPSZ6+eH35UwsL6mdX6mjRpUN9Hez6FMfE7s3XOldoPVMzR1XQJBAOa2VTkGhtz8HEWQZOySXfuhjSogHmu7Dk2C5CO4Eg/wycpjDGSUR0NZWnfAt60S6GbjszEQmJBGeNt10xPO78MCQQCWXwnRaZ3IFDhXfQfRWFSN5ilQ5UszFGQvnUB/ZkI+ObdZmXY6qRdxGcdPLnAN9r78fDZe7/Pk1qljCDY98IuVAkEAnSeO/221gDhL1wnbUhGuX1yo8f5Eo/wDTW5cBxXFGZeexhB8I4jnEV4E/xmikkb3jDFvmrnFk+XUtDqkrvicRQ== + +huiftReqUrl=https://linktest.huift.com.cn +huiftShopCode=50041b27-f985-dcb0-1cc0-f106b09bf1fe +huiftSignSecret=DB4D8069A9AC6DDF9D75667EE5CF182A diff --git a/service/src/main/resources/prod/commonConfig.properties b/service/src/main/resources/prod/commonConfig.properties index adab6f1..0f8f8fe 100644 --- a/service/src/main/resources/prod/commonConfig.properties +++ b/service/src/main/resources/prod/commonConfig.properties @@ -1,4 +1,6 @@ +domainName=https://phg.dctpay.com + wechatMpAppid=wxa075e8509802f826 wechatMpSecret=0e606fc1378d35e359fcf3f15570b2c5 @@ -49,3 +51,7 @@ etcPostUrl = https://test.djien-qr.com/ etcChannelCode = GZETCFXQD etcPublicKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMyQb5gR1rweB5oHKqRPJtJjLQKsn5PXOVfaNdGt/2kPkHvRdN3L9zOaAvFEXcEl2V0sg3D8a+2Sfy1YANAZvjscTQYOaoFl+LVyQZvgyyX8RQw+26Jmbqh8DwenUbNf7DFYVSDxIMBLOiWPkGsYGFONjsUVmfykSeVTcEgQB3VwIDAQAB etcPrivateKey = MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAO8+KWh/OmBahFk7TWOEjPl13BT5NdlbGvQ/311Yua6CQqul9w1DIR2TwFUUh/Bko/eVoLROfF2XVjHbw2bImTdJ7y9C3511HI59YPNzqyql0DHjLxbH0VW92eUgk8mG09wtrUMu1ImN0b7aFE3uqAgz6pwh3TUiQWsDWz+l/MG7AgMBAAECgYEA7nYsOd8OpbmzT2m/omEdTwz9993KocKgZDJCBj4InftyTrrXO93cZSm/PE6BjMgTcxUuIGpWpcbRgFLHOmzZ4Qd+k/6Yb1ErMTfdGlgrxv2B+vztWYfjmFzEiXpecFH47ED6iYrrqm14X3InpnBv4rUkGdqqNbyPGgTO2ncs/3kCQQD+xqRAQSb/TROlqJdO91y6z9v0PO2GLmokqYg444rKYZKhDE0tdJeLU/sfK8SMg5+SlwdQm4nlo8EDJ/w2CEn3AkEA8GRqVkKgIuH413/a6+luYDjlf30WY7Mi1sm3QPSZ6+eH35UwsL6mdX6mjRpUN9Hez6FMfE7s3XOldoPVMzR1XQJBAOa2VTkGhtz8HEWQZOySXfuhjSogHmu7Dk2C5CO4Eg/wycpjDGSUR0NZWnfAt60S6GbjszEQmJBGeNt10xPO78MCQQCWXwnRaZ3IFDhXfQfRWFSN5ilQ5UszFGQvnUB/ZkI+ObdZmXY6qRdxGcdPLnAN9r78fDZe7/Pk1qljCDY98IuVAkEAnSeO/221gDhL1wnbUhGuX1yo8f5Eo/wDTW5cBxXFGZeexhB8I4jnEV4E/xmikkb3jDFvmrnFk+XUtDqkrvicRQ== + +huiftReqUrl=https://gzyhmp.huift.com.cn +huiftShopCode=20240653-59c4-4181-9157-17fd4b95c3fc +huiftSignSecret=19C17F9E19B8DDDDF2FD2EE4EA9F6C61