package com.oying.modules.hwc.service.impl; import com.alibaba.fastjson2.JSONObject; import com.oying.exception.BadRequestException; import com.oying.modules.hwc.domain.HwcResponse; import com.oying.modules.hwc.service.SwiftPassService; import com.oying.modules.hwc.utils.SignUtil; import com.oying.modules.hwc.utils.SignUtils; import com.oying.modules.hwc.utils.XmlUtils; import com.oying.modules.security.config.SwiftPassProperties; import com.oying.modules.security.config.WeiXinProperties; import com.oying.utils.CloseUtil; import com.oying.utils.enums.PayTypeEnum; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * @author xin * @description * @date 2025/1/23 下午4:01 */ @SuppressWarnings({"unchecked", "all"}) @Slf4j @Service @RequiredArgsConstructor public class SwiftPassServiceImpl implements SwiftPassService { private final static String version = "2.0"; private final static String charset = "UTF-8"; private final static String service_pay = "pay.weixin.jspay"; private final static String service_query = "unified.trade.query"; private final static String service_refund = "unified.trade.refund"; private final static String service_close = "unified.trade.close"; private final SwiftPassProperties properties; private final WeiXinProperties weiXinProperties; @Override @Transactional(rollbackFor = Exception.class) public HwcResponse pay(String ip, String total, String timeExpire, String description, String openId, String orderNum, PayTypeEnum status) { SortedMap map = new TreeMap<>(); map.put("service", service_pay); map.put("version", version); map.put("charset", charset); map.put("sign_type", properties.getSignType()); map.put("is_raw", properties.getIsRaw()); map.put("is_minipg", properties.getIsMinipg()); map.put("out_trade_no", orderNum); map.put("body", description); map.put("sub_openid", openId); map.put("sub_appid", weiXinProperties.getAppId()); map.put("total_fee", total); map.put("mch_create_ip", ip); map.put("notify_url", properties.getNotifyUrl()); map.put("time_expire", timeExpire); map.put("nonce_str", String.valueOf(new Date().getTime())); switch (status) { case HWC: map.put("mch_id", properties.getMchId()); break; case HWC2: map.put("mch_id", properties.getMchId2()); break; default: throw new BadRequestException("汇旺财类型错误"); } Map params = SignUtils.paraFilter(map); StringBuilder buf = new StringBuilder((params.size() + 1) * 10); SignUtils.buildPayParams(buf, params, false); String preStr = buf.toString(); String sign_type = map.get("sign_type"); map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status)); String reqUrl = properties.getReqUrl(); CloseableHttpResponse response = null; CloseableHttpClient client = null; Map resultMap = new HashMap<>(); try { HttpPost httpPost = new HttpPost(reqUrl); StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8"); httpPost.setEntity(entityParams); httpPost.setHeader("Content-Type", "text/xml;utf-8"); client = HttpClients.createDefault(); response = client.execute(httpPost); if (response != null && response.getEntity() != null) { resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8"); String reSign = resultMap.get("sign"); sign_type = resultMap.get("sign_type"); if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) { throw new BadRequestException("验证签名错误"); } else { if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) { return JSONObject.parseObject(resultMap.get("pay_info"), HwcResponse.class); } else { throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" + resultMap.get("status") + " : " + resultMap.get("message")); } } } else { throw new BadRequestException("操作失败"); } } catch (Exception e) { log.error("汇旺财下单错误请求参数:{}", params); log.error("汇旺财下单错误返回参数:{}", resultMap); throw new BadRequestException("汇旺财下单错误:" + e.getMessage()); } finally { if (response != null) { CloseUtil.close(response); } if (client != null) { CloseUtil.close(client); } } } @Override public JSONObject query(String orderNum, PayTypeEnum status) { // 参数 SortedMap map = new TreeMap<>(); map.put("service", service_query); map.put("version", version); map.put("charset", charset); map.put("out_trade_no", orderNum); map.put("sign_type", properties.getSignType()); switch (status) { case HWC: map.put("mch_id", properties.getMchId()); break; case HWC2: map.put("mch_id", properties.getMchId2()); break; default: throw new BadRequestException("汇旺财类型错误"); } map.put("nonce_str", String.valueOf(new Date().getTime())); // 签名 Map params = SignUtils.paraFilter(map); StringBuilder buf = new StringBuilder((params.size() + 1) * 10); SignUtils.buildPayParams(buf, params, false); String preStr = buf.toString(); String sign_type = map.get("sign_type"); map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status)); // 请求 CloseableHttpResponse response = null; CloseableHttpClient client = null; Map resultMap = new HashMap<>(); try { HttpPost httpPost = new HttpPost(properties.getReqUrl()); StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8"); httpPost.setEntity(entityParams); httpPost.setHeader("Content-Type", "text/xml;utf-8"); client = HttpClients.createDefault(); response = client.execute(httpPost); if (response != null && response.getEntity() != null) { resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8"); String reSign = resultMap.get("sign"); sign_type = resultMap.get("sign_type"); if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) { throw new BadRequestException("验证签名错误"); } else { if ("0".equals(resultMap.get("status"))) { return JSONObject.parseObject(JSONObject.toJSONString(resultMap)); } else { throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" + resultMap.get("status") + " : " + resultMap.get("message")); } } } else { throw new BadRequestException("操作失败!"); } } catch (Exception e) { log.error("请求参数:{}", params); log.error("返回参数:{}", resultMap); throw new BadRequestException("操作失败,原因:" + e.getMessage()); } finally { if (response != null) { CloseUtil.close(response); } if (client != null) { CloseUtil.close(client); } } } @Override public void closeOrder(String outTradeNo, PayTypeEnum status) { // 参数 SortedMap map = new TreeMap<>(); map.put("service", service_close); map.put("version", version); map.put("charset", charset); map.put("out_trade_no", outTradeNo); map.put("sign_type", properties.getSignType()); switch (status) { case HWC: map.put("mch_id", properties.getMchId()); break; case HWC2: map.put("mch_id", properties.getMchId2()); break; default: throw new BadRequestException("汇旺财类型错误"); } map.put("nonce_str", String.valueOf(new Date().getTime())); // 签名 Map params = SignUtils.paraFilter(map); StringBuilder buf = new StringBuilder((params.size() + 1) * 10); SignUtils.buildPayParams(buf, params, false); String preStr = buf.toString(); String sign_type = map.get("sign_type"); map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status)); // 请求 CloseableHttpResponse response = null; CloseableHttpClient client = null; Map resultMap = new HashMap<>(); try { HttpPost httpPost = new HttpPost(properties.getReqUrl()); StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8"); httpPost.setEntity(entityParams); httpPost.setHeader("Content-Type", "text/xml;utf-8"); client = HttpClients.createDefault(); response = client.execute(httpPost); if (response != null && response.getEntity() != null) { resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8"); String reSign = resultMap.get("sign"); sign_type = resultMap.get("sign_type"); if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) { throw new BadRequestException("验证签名错误"); } else { if (!("0".equals(resultMap.get("status")))) { throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" + resultMap.get("status") + " : " + resultMap.get("message")); } } } else { throw new BadRequestException("操作失败!"); } } catch (Exception e) { log.error("请求参数:{}", params); log.error("返回参数:{}", resultMap); throw new BadRequestException("操作失败,原因:" + e.getMessage()); } finally { if (response != null) { CloseUtil.close(response); } if (client != null) { CloseUtil.close(client); } } } @Override @Transactional(rollbackFor = Exception.class) public Map refund(String returnNum, String orderNum, String reason, long refund, long total, PayTypeEnum payType) { // 参数 SortedMap map = new TreeMap<>(); map.put("service", service_refund); map.put("version", version); map.put("charset", charset); map.put("sign_type", properties.getSignType()); map.put("out_trade_no", orderNum); map.put("out_refund_no", returnNum); map.put("total_fee", String.valueOf(total)); map.put("refund_fee", String.valueOf(refund)); map.put("nonce_str", String.valueOf(new Date().getTime())); switch (payType) { case HWC: map.put("mch_id", properties.getMchId()); map.put("op_user_id", properties.getMchId()); break; case HWC2: map.put("mch_id", properties.getMchId2()); map.put("op_user_id", properties.getMchId2()); break; default: throw new BadRequestException("汇旺财类型错误"); } // 签名 Map params = SignUtils.paraFilter(map); StringBuilder buf = new StringBuilder((params.size() + 1) * 10); SignUtils.buildPayParams(buf, params, false); String preStr = buf.toString(); String sign_type = map.get("sign_type"); map.put("sign", SignUtil.getSign(sign_type, preStr, properties, payType)); // 参数 CloseableHttpResponse response = null; CloseableHttpClient client = null; Map resultMap = new HashMap<>(); try { HttpPost httpPost = new HttpPost(properties.getReqUrl()); StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8"); httpPost.setEntity(entityParams); httpPost.setHeader("Content-Type", "text/xml;utf-8"); client = HttpClients.createDefault(); response = client.execute(httpPost); if (response != null && response.getEntity() != null) { resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8"); if (resultMap.containsKey("sign") && SignUtil.verifySign(resultMap.get("sign"), resultMap.get("sign_type"), resultMap, properties, payType)) { throw new BadRequestException("验证签名错误"); } else { if ("0".equals(resultMap.get("status"))) { return resultMap; } else { throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" + resultMap.get("status") + " : " + resultMap.get("message")); } } } else { throw new BadRequestException("操作失败!"); } } catch (Exception e) { log.error("请求参数:{}", params); log.error("返回参数:{}", resultMap); throw new BadRequestException("操作失败,原因:" + e); } finally { if (response != null) { CloseUtil.close(response); } if (client != null) { CloseUtil.close(client); } } } }