package com.tourguide.modules.order.service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.tourguide.common.exception.BusinessException; import com.tourguide.common.huifu.biz.DouGongPayUtil; import com.tourguide.modules.order.dto.MiniPaymentResponse; import com.tourguide.modules.order.payment.OrderPaymentPreparation; import com.tourguide.modules.user.entity.MiniUser; import com.tourguide.modules.user.service.MiniUserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @Service public class HuifuMiniPaymentService { private static final String SUCCESS_CODE = "00000100"; private static final Logger log = LoggerFactory.getLogger(HuifuMiniPaymentService.class); private final MiniUserService miniUserService; private final TourOrderPaymentService orderPaymentService; private final DouGongPayUtil payUtil; public HuifuMiniPaymentService(MiniUserService miniUserService, TourOrderPaymentService orderPaymentService, DouGongPayUtil payUtil) { this.miniUserService = miniUserService; this.orderPaymentService = orderPaymentService; this.payUtil = payUtil; } public MiniPaymentResponse create(Long visitorId, Long orderId) { MiniUser user = miniUserService.findEnabledById(visitorId); if (!StringUtils.hasText(user.getOpenid())) { throw new BusinessException(409, "当前账号缺少微信 OpenID,请重新登录后支付"); } OrderPaymentPreparation preparation = orderPaymentService.prepare(visitorId, orderId); JSONObject response; try { response = payUtil.wxPayOrder(preparation.getAmount(), user.getOpenid(), preparation.getGoodsDescription(), preparation.getReqSeqId(), preparation.getReqDate()); } catch (IllegalStateException exception) { log.warn("创建汇付支付订单失败,订单ID:{},请求流水号:{},原因:{}", orderId, preparation.getReqSeqId(), exception.getMessage()); throw new BusinessException(503, exception.getMessage()); } catch (Exception exception) { log.error("调用汇付支付服务异常,订单ID:{},请求流水号:{}", orderId, preparation.getReqSeqId(), exception); throw new BusinessException(502, "汇付支付服务暂不可用,请稍后重试"); } JSONObject data = jsonObject(response.get("data")); if (data == null) data = jsonObject(response.get("resp_data")); String responseCode = response.getString("resp_code"); if (!StringUtils.hasText(responseCode) && data != null) responseCode = data.getString("resp_code"); if (!SUCCESS_CODE.equals(responseCode)) { String description = response.getString("resp_desc"); if (!StringUtils.hasText(description) && data != null) description = data.getString("resp_desc"); throw new BusinessException(502, StringUtils.hasText(description) ? description : "创建支付订单失败"); } Object payInfoValue = data == null ? response.get("pay_info") : data.get("pay_info"); JSONObject payInfo = jsonObject(payInfoValue); if (payInfo != null && payInfo.containsKey("wx_data")) payInfo = jsonObject(payInfo.get("wx_data")); if (payInfo == null) throw new BusinessException(502, "汇付响应缺少微信支付参数"); String timeStamp = value(payInfo, "timeStamp", "timestamp", "time_stamp"); String nonceStr = value(payInfo, "nonceStr", "nonce_str", "noncestr"); String packageValue = value(payInfo, "package", "packageValue"); String signType = value(payInfo, "signType", "sign_type"); String paySign = value(payInfo, "paySign", "pay_sign"); if (!StringUtils.hasText(timeStamp) || !StringUtils.hasText(nonceStr) || !StringUtils.hasText(packageValue) || !StringUtils.hasText(paySign)) { throw new BusinessException(502, "汇付响应中的微信支付参数不完整"); } return new MiniPaymentResponse(preparation.getOrderId(), preparation.getReqSeqId(), "wxpay", timeStamp, nonceStr, packageValue, StringUtils.hasText(signType) ? signType : "RSA", paySign); } private JSONObject jsonObject(Object value) { if (value == null) return null; if (value instanceof JSONObject) return (JSONObject) value; if (value instanceof String) { String text = ((String) value).trim(); return text.isEmpty() ? null : JSONObject.parseObject(text); } return JSONObject.parseObject(JSON.toJSONString(value)); } private String value(JSONObject source, String... keys) { for (String key : keys) { String value = source.getString(key); if (StringUtils.hasText(value)) return value; } return null; } }