package com.talentcard.server.business.payment.huifu; import com.alibaba.fastjson.JSON; import com.huifu.bspay.sdk.opps.client.BasePayClient; import com.huifu.bspay.sdk.opps.core.BasePay; import com.huifu.bspay.sdk.opps.core.config.MerConfig; import com.talentcard.server.common.BusinessException; import com.talentcard.server.common.ErrorCode; import java.time.LocalDate; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.LinkedHashMap; import java.util.Map; import java.util.UUID; import org.springframework.stereotype.Service; /** External boundary for manual recovery of an existing Huifu merchant. */ @Service public class HuifuOnboardingProgressGateway { private final HuifuPaymentProperties properties; public HuifuOnboardingProgressGateway(HuifuPaymentProperties properties) { this.properties = properties; } public Map queryApplication(String huifuId, String applyNo) { Map request = queryRequest(huifuId); request.put("apply_no", applyNo); return send("v2.merchant.basicdata.status.query", request); } public Map queryCapabilities(String huifuId) { return send("v2.merchant.basicdata.query", queryRequest(huifuId)); } public Map queryWechatConfig(String huifuId) { return send("v2.merchant.busi.config.query", queryRequest(huifuId)); } public Map queryRealname(String huifuId) { Map request = queryRequest(huifuId); // 这里的 pay_scene 是「微信业务开通类型」(线下 02 / 线上 01),不是支付场景(1/2/3 或 4/5/12)。 request.put("pay_scene", properties.getMerchantWechatFeeType()); return send("v2.merchant.busi.realname.query", request); } public Map configureDelay(String huifuId, String requestNo, String requestDate) { Map request = new LinkedHashMap<>(Map.of("huifu_id",huifuId,"req_seq_id",requestNo,"req_date",requestDate, "delay_flag","Y","forced_delay_flag","N")); if (!properties.getMerchantBusinessOpenNotifyUrl().isBlank()) request.put("async_return_url",properties.getMerchantBusinessOpenNotifyUrl()); return send("v2.merchant.busi.modify", request); } protected Map send(String function, Map request) { if (!properties.isEnabled()) throw new BusinessException(ErrorCode.CONFLICT, "Huifu payment is disabled"); try { synchronized (BasePay.class) { BasePay.debug = false; BasePay.prodMode = "prod".equalsIgnoreCase(properties.getEnvironment()) ? BasePay.MODE_PROD : BasePay.MODE_TEST; MerConfig config = new MerConfig(); config.setSysId(properties.getSystemId()); config.setProductId(properties.getProductId()); config.setRsaPrivateKey(properties.getPrivateKey()); config.setRsaPublicKey(properties.getPlatformPublicKey()); BasePay.initWithMerConfig(config); return data(BasePayClient.request(request, function, false)); } } catch (BusinessException exception) { throw exception; } catch (Exception exception) { throw new HuifuPaymentGatewayException("Huifu request outcome is unknown", true, exception); } } static Map queryRequest(String huifuId) { Map request = new LinkedHashMap<>(); request.put("req_seq_id", UUID.randomUUID().toString().replace("-", "")); request.put("req_date", LocalDate.now(ZoneId.of("Asia/Shanghai")).format(DateTimeFormatter.BASIC_ISO_DATE)); request.put("huifu_id", huifuId); return request; } @SuppressWarnings("unchecked") public static Map data(Map response) { if (response == null) throw new IllegalArgumentException("Empty Huifu response"); Object nested = response.get("data"); if (nested instanceof Map value) return (Map) value; if (nested instanceof String value && !value.isBlank()) return JSON.parseObject(value, Map.class); return response; } }