package com.kk.api.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.google.common.base.CaseFormat; import com.google.gson.GsonBuilder; import com.kk.api.request.PayQueryRequest; import com.kk.api.request.PayRequest; import com.kk.api.response.PayNotifyResponse; import com.kk.api.response.PayQueryResponse; import com.kk.api.response.PayResponse; import com.kk.api.response.PaySynResponse; import com.kk.platform.enums.PayException; import com.kk.platform.enums.PayStatus; import com.kk.platform.enums.PayTypeCode; import com.kk.platform.enums.ResultCode; import com.kk.platform.model.PayChannel; import com.kk.platform.model.PayMerchant; import com.kk.platform.model.PayMerchantChannel; import com.kk.platform.model.PayOrder; import com.kk.platform.service.PayOrderService; import com.kk.util.DateUtil; import com.kk.utils.HttpClientUtil; import com.kk.utils.LocalIPUtil; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.List; import java.util.Map; @Service public class PayService extends AbstractPayService { private Log logger = LogFactory.getLog(this.getClass()); @Autowired private PayOrderService payOrderService; @Autowired private Map<String, InternalPayService> payServices; /** * 统一下单 * * @param request * @return */ public PayResponse request(PayRequest request) { PayMerchant merchant = payMerchantService.getPayMerchant(request.getMerchantId()); // 校验参数 PayResponse response = (PayResponse) validate(merchant, request, PayResponse.class); if (response != null) { return response; } // 支付类型校验 if (request.getPayType() == null || request.getTradeType() == null) { throw new PayException("支付类型不支持"); } PayTypeCode payType = request.getPayType(); // 查看该商户是否有此支付类型权限 PayMerchantChannel merchantChannel = payMerchantChannelService.getPayMerchantChannel(merchant.getId(), payType.getId(), request.getTradeType()); if (merchantChannel == null) { throw new PayException("支付类型不支持"); } PayChannel payChannel = merchantChannel.getPayChannel(); if (payChannel == null) { throw new PayException("此商户支付类型配置有误"); } // 业务方 交易流水号 String voucherId = request.getTradePayNo(); // 重复下单校验 List<PayOrder> payOrders = payOrderService.getPayOrders(request.getMerchantId(), request.getTradePayNo()); if (payOrders.size() > 0) { for (PayOrder order : payOrders) { if (order.getStatus() == PayStatus.PAY_SUCCESS.getValue() || order.getStatus() == PayStatus.REFUND_PART.getValue() || order.getStatus() == PayStatus.REFUND_SUCCESS.getValue() ) { throw new PayException("订单已支付,请勿重新支付"); } } for (PayOrder order : payOrders) { if (order.getStatus() == PayStatus.CREATE_PAYMENT_SUCCESS.getValue()) { if (order.getPayTypeCode().equals(request.getPayType()) && order.getExpireTime().after(new Date())) { return getPayResponse(merchant, payChannel, order); } else { // 支付请求过期 continue; } } if (order.getStatus() == PayStatus.CREATE_PAYMENT.getValue()) { return getPayResponse(merchant, payChannel, order); } } } // 下单 PayOrder order = new PayOrder(); order.setNotifyUrl(request.getNotifyUrl()); order.setDetail(request.getDetail()); order.setSubject(request.getSubject()); order.setUserIp(request.getClientIp()); order.setTradeType(request.getTradeType().toString()); order.setPayTypeCode(request.getPayType().toString()); order.setExtra(request.getExtra()); order.setReturnUrl(request.getReturnUrl()); order.setStatus(PayStatus.CREATE_PAYMENT.getValue()); if (StringUtils.isBlank(request.getClientIp())) { order.setUserIp(LocalIPUtil.getLocalAddr()); } DateTime now = DateTime.now(); order.setStartTime(now.toDate()); order.setExpireTime(now.plusHours(2).toDate()); order.setTradePayNo(request.getTradePayNo()); order.setPayAmount(request.getPayAmount()); order.setMerchantId(request.getMerchantId()); order.setOpenId(request.getOpenId()); payOrderService.createPayOrder(order); return getPayResponse(merchant, payChannel, order); } private PayResponse getPayResponse(PayMerchant merchant, PayChannel payChannel, PayOrder order) { PayResponse response = new PayResponse(); // 统一下单接口,获取支付凭据 response.setCredential(getService(order.getPayTypeCodeEnum()).pay(payChannel, order)); // 基本参数 response.setMerchantId(merchant.getMerchantId()); response.setCode(ResultCode.SUCCESS.getValue()); response.setMsg(ResultCode.SUCCESS.getValue()); response.setTradePayNo(order.getTradePayNo()); response.setPayOrderNo(order.getPayOrderNo()); response.setPayType(order.getPayTypeCodeEnum()); response.setTradeType(order.getTradeTypeCodeEnum()); response.setSign(sign(response, merchant.getApiKey())); return response; } // payType:WECHAT_PAY private InternalPayService getService(PayTypeCode payType) { // key:wechatPayService String key = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, payType.toString()) + "Service"; InternalPayService service = payServices.get(key); if (service == null) { throw new PayException("支付方式不存在"); } return service; } /** * 支付成功回调,设置订单状态,同时回调业务方。 * * @param payType 支付类型:微信,支付宝等 * @param payNotify * @return */ public boolean handlePayNotify(PayTypeCode payType, String payNotify) { if (StringUtils.isBlank(payNotify)) { return false; } String orderNo = getService(payType).getOutTradeNo(payNotify); if (StringUtils.isBlank(orderNo)) { return false; } PayOrder order = payOrderService.getPayOrder(orderNo); if (order == null) { return false; } // 如果已经回调成功 if (order.getStatus() == PayStatus.PAY_SUCCESS.getValue()) { return false; } PayMerchantChannel channel = payMerchantChannelService.getPayMerchantChannel(order.getMerchantId(), order.getPayTypeCodeEnum(), order.getTradeTypeCodeEnum()); PayNotifyResponse notifyResponse = getService(payType).parse(channel.getPayChannel(), order, payNotify); notifyResponse.setPayType(order.getPayTypeCodeEnum()); notifyResponse.setSign(sign(notifyResponse, channel.getPayMerchant().getApiKey())); if (ResultCode.SUCCESS.getValue().equals(notifyResponse.getStatus())) { if (StringUtils.isNotBlank(order.getNotifyUrl())) { HttpClientUtil.postData(order.getNotifyUrl(), JSON.toJSONString(notifyResponse, SerializerFeature.WriteDateUseDateFormat)); } return true; } else { return false; } } /** * 优先根据 payOrderNo查询 * 如果根据tradePayNo ,如果只有一条记录,则直接返回; 如果有多条记录,优先返回 成功或失败的记录, 如果找不到则返回最后一条。 * * @param request * @return */ public PayQueryResponse query(PayQueryRequest request) { PayMerchant merchant = payMerchantService.getPayMerchant(request.getMerchantId()); // 校验参数 PayQueryResponse response = (PayQueryResponse) validate(merchant, request, PayQueryResponse.class); if (response != null) { return response; } response = new PayQueryResponse(); if (StringUtils.isBlank(request.getTradePayNo()) && StringUtils.isBlank(request.getPayOrderNo())) { response.setCode(ResultCode.FAIL.getValue()); response.setMsg("订单号不存在"); return response; } PayOrder order = getPayOrder(request); if (order == null) { response.setCode(ResultCode.FAIL.getValue()); response.setMsg("订单不存在"); return response; } response.setTradePayNo(order.getTradePayNo()); response.setPayOrderNo(order.getPayOrderNo()); response.setExt(order.getExtra()); response.setPrePayId(order.getPrePayId()); response.setSubject(order.getSubject()); response.setDetail(order.getDetail()); response.setCodeUrl(order.getCodeUrl()); response.setPayType(order.getPayTypeCode()); response.setTradeType(order.getTradeType()); response.setRefundAmount(order.getRefundAmount()); // 基本参数 response.setMsg(ResultCode.SUCCESS.getValue()); response.setCode(ResultCode.SUCCESS.getValue()); response.setMerchantId(order.getMerchantId()); response.setPayTime(DateUtil.defaultTime(order.getPayTime())); response.setPayAmount(order.getPayAmount()); response.setStatus(order.getStatus() + ""); response.setSign(sign(response, merchant.getApiKey())); return response; } /** * 同步订单状态,与第三方支付的订单状态保持一致 * * @param request * @return */ public PaySynResponse synchronize(PayQueryRequest request) { PayMerchant merchant = payMerchantService.getPayMerchant(request.getMerchantId()); // 校验参数 PaySynResponse response = (PaySynResponse) validate(merchant, request, PaySynResponse.class); if (response != null) { return response; } response = new PaySynResponse(); if (StringUtils.isBlank(request.getTradePayNo()) && StringUtils.isBlank(request.getPayOrderNo())) { response.setCode(ResultCode.FAIL.getValue()); response.setMsg("订单号不存在"); return response; } PayOrder order = getPayOrder(request); if (order == null) { response.setCode(ResultCode.FAIL.getValue()); response.setMsg("订单不存在"); return response; } boolean syn = synchronize(order); if (syn) { response.setStatus(ResultCode.SUCCESS.getValue()); } else { response.setStatus(ResultCode.FAIL.getValue()); } response.setMsg(ResultCode.SUCCESS.getValue()); response.setCode(ResultCode.SUCCESS.getValue()); response.setMerchantId(order.getMerchantId()); response.setSign(sign(response, merchant.getApiKey())); return response; } public boolean synchronize(PayOrder order) { if (order == null) { return false; } PayMerchantChannel channel = payMerchantChannelService.getPayMerchantChannel(order.getMerchantId(), order.getPayTypeCodeEnum(), order.getTradeTypeCodeEnum()); if (PayStatus.CREATE_PAYMENT.getValue() == order.getStatus() || PayStatus.CREATE_PAYMENT_SUCCESS.getValue() == order.getStatus() || PayStatus.PAY_SUCCESS.getValue() == order.getStatus() || PayStatus.PAY_CHECKING.getValue() == order.getStatus()) { return getService(order.getPayTypeCodeEnum()).synchronize(channel.getPayChannel(), order); } return false; } private PayOrder getPayOrder(PayQueryRequest request) { PayOrder order = null; if (StringUtils.isNotBlank(request.getPayOrderNo())) { order = payOrderService.getPayOrder(request.getPayOrderNo()); } if (order == null) { List<PayOrder> orderList = payOrderService.getPayOrders(request.getMerchantId(), request.getTradePayNo()); if (orderList.size() == 1) { order = orderList.get(0); } else { for (PayOrder o : orderList) { if (o.getStatus() != PayStatus.CREATE_PAYMENT.getValue() && o.getStatus() != PayStatus.CREATE_PAYMENT_SUCCESS.getValue() && o.getStatus() != PayStatus.CREATE_PAYMENT_FAIL.getValue()) { order = o; break; } } if (order == null) { if (orderList.size() > 0) { order = orderList.get(orderList.size() - 1); } } } } if (order != null) { if (!order.getMerchantId().equals(request.getMerchantId())) { logger.error(String.format("order can not match merchantId:order.id=%s,req.mchId=%s", order.getId(), request.getMerchantId())); return null; } } return order; } }