diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java index b93cae9f7..d345c25ef 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java @@ -216,10 +216,10 @@ public class EntryManager { String image = WechatEntryManager.uploadImage(null, dto.getUrl()); dto.setWechatId(image); } - if (StrUtil.isBlank(dto.getAlipayId())) { - String image = AlipayEntryManager.uploadImage(null, dto.getUrl()); - dto.setAlipayId(image); - } +// if (StrUtil.isBlank(dto.getAlipayId())) { +// String image = AlipayEntryManager.uploadImage(null, dto.getUrl()); +// dto.setAlipayId(image); +// } } } @@ -370,10 +370,10 @@ public class EntryManager { // uploadParamImage(merchantDto); verifyEntryParam(merchantDto); -// uploadParamImage(merchantDto); + uploadParamImage(merchantDto); // System.out.println(merchantDto); -// entryMerchant(merchantDto, PayCst.Platform.WECHAT); - entryMerchant(merchantDto, PayCst.Platform.ALIPAY); + entryMerchant(merchantDto, PayCst.Platform.WECHAT); +// entryMerchant(merchantDto, PayCst.Platform.ALIPAY); // entryMerchant(merchantDto, PayCst.Platform.WECHAT, PayCst.Platform.ALIPAY); } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java index 606d44dae..c2f825e8f 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java @@ -15,6 +15,11 @@ public interface PayCst { */ String LONG_TERM_DATE = "2099-12-31"; + /** + * 支付宝异常信息获取 key + */ + String ALIPAY_ERROR_MSG_KEY = "message"; + /** * 平台 */ diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/PayManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/PayManager.java new file mode 100644 index 000000000..f08d51c21 --- /dev/null +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/PayManager.java @@ -0,0 +1,47 @@ +package com.czg; + +import com.czg.dto.req.PayParamsDto; +import com.czg.third.alipay.AlipayIsvPayManager; +import com.czg.third.wechat.WechatPayManager; + +/** + * @author yjjie + * @date 2026/1/9 11:24 + */ +public class PayManager { + + public static void jsapiPay(PayParamsDto paramsDto) { + paramsDto.verifyParams(); + + if (PayCst.Platform.WECHAT.equals(paramsDto.getPlatform())) { + WechatPayManager.jsapiPay(null, paramsDto); + } else if (PayCst.Platform.ALIPAY.equals(paramsDto.getPlatform())) { + AlipayIsvPayManager.jsapiPay(null, paramsDto); + } + } + + public static void main(String[] args) { +// jsapiPay(new PayParamsDto() +// .setPlatform(PayCst.Platform.ALIPAY) +// .setAppId("2021004145625815") +// .setOpenId("123123123") +// .setOrderNo("1111231231213") +// .setTitle("1213") +// .setMerchantId("123312321") +// .setBody("1213") +// .setAmount(1000L) +// .setPayParams("{\"app_auth_token\": \"ssss\"}") +// .setNotifyUrl("https://www.baidu.com")); + jsapiPay(new PayParamsDto() + .setPlatform(PayCst.Platform.WECHAT) + .setAppId("2021004145625815") + .setOpenId("123123123") + .setOrderNo("1111231231213") + .setTitle("1213") + .setMerchantId("123312321") + .setBody("1213") + .setAmount(1000L) + .setPayParams("{\"app_auth_token\": \"ssss\"}") + .setNotifyUrl("https://www.baidu.com")); + } +} diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/dto/req/PayParamsDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/dto/req/PayParamsDto.java new file mode 100644 index 000000000..114d45ef2 --- /dev/null +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/dto/req/PayParamsDto.java @@ -0,0 +1,104 @@ +package com.czg.dto.req; + +import com.alibaba.fastjson2.JSONObject; +import com.czg.PayCst; +import com.czg.exception.CzgException; +import com.czg.third.alipay.dto.AlipayAuthInfoDto; +import com.czg.utils.AssertUtil; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 支付参数 + * + * @author yjjie + * @date 2026/1/9 11:12 + */ +@Data +@Accessors(chain = true) +public class PayParamsDto { + + /** + * 【必填】 + * 支付方式 + * {@link com.czg.PayCst.Platform} + */ + private String platform; + + /** + * 【必填】 + * 订单号 + */ + private String orderNo; + + /** + * 【必填】 + * 金额,单位:分 + */ + private Long amount; + + /** + * 【必填】 + * 订单标题 + */ + private String title; + + /** + * 【必填】 + * 回调地址 + */ + private String notifyUrl; + + /** + * 【必填】 + * appId + */ + private String appId; + + /** + * 用户唯一标识 + */ + private String openId; + + /** + * 【微信必填】 + * 商户ID + */ + private String merchantId; + + /** + * 【支付宝必填】 + * 支付参数 + */ + private String payParams; + + /** + * 商品描述 + */ + private String body; + + /** + * 支付宝 授权信息解析,不用传 + */ + private AlipayAuthInfoDto alipayAuthInfo; + + public void verifyParams() { + AssertUtil.isBlank(platform, "请选择支付方式"); + AssertUtil.isBlank(orderNo, "订单号不能为空"); + AssertUtil.isBlank(title, "订单标题不能为空"); + AssertUtil.isBlank(notifyUrl, "回调地址不能为空"); + AssertUtil.isBlank(appId, "appId不能为空"); + AssertUtil.isBlank(openId, "用户唯一标识不能为空"); + + if (PayCst.Platform.WECHAT.equals(platform)) { + AssertUtil.isBlank(merchantId, "商户ID不能为空"); + } else if (PayCst.Platform.ALIPAY.equals(platform)) { + AssertUtil.isBlank(payParams, "支付参数不能为空"); + alipayAuthInfo = JSONObject.parseObject(payParams, AlipayAuthInfoDto.class); + AssertUtil.isNull(alipayAuthInfo, "支付参数错误"); + AssertUtil.isBlank(alipayAuthInfo.getAppAuthToken(), "授权信息错误"); + } else { + throw new CzgException("支付平台错误"); + } + } +} diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java index e3ae2146d..baa87fdba 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java @@ -9,6 +9,7 @@ import com.czg.dto.req.*; import com.czg.dto.resp.EntryThirdRespDto; import com.czg.dto.resp.QueryStatusResp; import com.czg.exception.CzgException; +import com.czg.third.alipay.dto.AlipayAuthInfoDto; import com.czg.third.alipay.dto.config.AlipayConfigDto; import com.czg.utils.UploadFileUtil; import lombok.extern.slf4j.Slf4j; @@ -25,8 +26,6 @@ import java.io.IOException; @Slf4j public class AlipayIsvEntryManager { - private static final String ERR_MESSAGE_KEY = "message"; - public static QueryStatusResp queryMerchantBatchStatus(AlipayConfigDto configDto, String batchNo) { QueryStatusResp respDto = new QueryStatusResp() .setPlatform(PayCst.Platform.ALIPAY); @@ -87,7 +86,7 @@ public class AlipayIsvEntryManager { log.error("支付宝查询进件状态异常: {}", body); JSONObject object = JSONObject.parseObject(body); respDto.setStatus(PayCst.EntryStatus.REJECTED); - respDto.setFailReason(object.getString(ERR_MESSAGE_KEY)); + respDto.setFailReason(object.getString(PayCst.ALIPAY_ERROR_MSG_KEY)); return respDto; } } @@ -131,7 +130,7 @@ public class AlipayIsvEntryManager { log.error("支付宝开启代商户签约,创建应用事务异常: {}", body); JSONObject object = JSONObject.parseObject(body); respDto.setStatus(PayCst.EntryStatus.REJECTED); - respDto.setErrorMsg(object.getString(ERR_MESSAGE_KEY)); + respDto.setErrorMsg(object.getString(PayCst.ALIPAY_ERROR_MSG_KEY)); return respDto; } catch (IOException e) { log.error("上传图片出错", e); @@ -174,7 +173,7 @@ public class AlipayIsvEntryManager { String body = e.getResponseBody(); log.error("支付宝开启代商户签约,开启事务异常: {}", body); JSONObject object = JSONObject.parseObject(body); - throw new CzgException("支付宝开启代商户签约,开启事务异常: " + object.getString(ERR_MESSAGE_KEY)); + throw new CzgException("支付宝开启代商户签约,开启事务异常: " + object.getString(PayCst.ALIPAY_ERROR_MSG_KEY)); } } @@ -189,12 +188,22 @@ public class AlipayIsvEntryManager { try { AlipayOpenAgentConfirmResponseModel response = api.confirm(data); log.info("支付宝开启代商户签约,确认事务: 响应={}", response); - return JSONObject.toJSONString(response); + + AlipayAuthInfoDto authInfoDto = new AlipayAuthInfoDto() + .setUserId(response.getUserId()) + .setOpenId(response.getOpenId()) + .setAuthAppId(response.getAuthAppId()) + .setAppAuthToken(response.getAppAuthToken()) + .setExpiresIn(response.getExpiresIn()) + .setAppRefreshToken(response.getAppRefreshToken()) + .setReExpiresIn(response.getReExpiresIn()) + .setOrderNo(response.getOrderNo()); + return JSONObject.toJSONString(authInfoDto); } catch (ApiException e) { String body = e.getResponseBody(); log.error("支付宝开启代商户签约,确认事务异常: {}", body); JSONObject object = JSONObject.parseObject(body); - throw new CzgException(object.getString(ERR_MESSAGE_KEY)); + throw new CzgException(object.getString(PayCst.ALIPAY_ERROR_MSG_KEY)); } } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvPayManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvPayManager.java index da44f7f4a..50244a798 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvPayManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvPayManager.java @@ -1,24 +1,64 @@ package com.czg.third.alipay; +import com.alibaba.fastjson2.JSONObject; import com.alipay.v3.ApiException; import com.alipay.v3.api.AlipayTradeApi; import com.alipay.v3.model.AlipayTradeCreateModel; +import com.alipay.v3.model.AlipayTradeCreateResponseModel; import com.alipay.v3.model.ExtendParams; import com.alipay.v3.util.model.CustomizedParams; +import com.czg.PayCst; +import com.czg.dto.req.PayParamsDto; +import com.czg.exception.CzgException; +import com.czg.third.alipay.dto.config.AlipayConfigDto; +import lombok.extern.slf4j.Slf4j; + +import java.math.BigDecimal; /** * @author yjjie * @date 2026/1/9 09:30 */ +@Slf4j public class AlipayIsvPayManager { - public static void main(String[] args) throws ApiException { - AlipayTradeApi api = new AlipayTradeApi(); - AlipayTradeCreateModel model = new AlipayTradeCreateModel(); + public static String jsapiPay(AlipayConfigDto configDto, PayParamsDto paramsDto) { + try { + AlipayClient.setApiClient(configDto); + AlipayTradeApi api = new AlipayTradeApi(); + AlipayTradeCreateModel model = new AlipayTradeCreateModel(); + model.setOutTradeNo(paramsDto.getOrderNo()); + model.setProductCode("JSAPI_PAY"); + model.setOpAppId(paramsDto.getAppId()); + model.setOpBuyerOpenId(paramsDto.getOpenId()); + model.setTotalAmount(getYuanAmountByFen(paramsDto.getAmount())); + model.setSubject(paramsDto.getTitle()); + model.setBody(paramsDto.getBody()); + model.setNotifyUrl(paramsDto.getNotifyUrl()); - model.setExtendParams(new ExtendParams()); - CustomizedParams customizedParams = new CustomizedParams(); + model.setExtendParams(new ExtendParams()); + CustomizedParams customizedParams = new CustomizedParams(); + customizedParams.setAppAuthToken(paramsDto.getAlipayAuthInfo().getAppAuthToken()); - api.create(model, customizedParams); + AlipayTradeCreateResponseModel responseModel = api.create(model, customizedParams); + return responseModel.getTradeNo(); + } catch (ApiException e) { + String body = e.getResponseBody(); + log.error("支付宝 H5 api 支付异常: {}", body); + JSONObject object = JSONObject.parseObject(body); + throw new CzgException(object.getString(PayCst.ALIPAY_ERROR_MSG_KEY)); + } catch (Exception e) { + log.error("支付宝 H5支付异常: {}", e.getMessage()); + throw new CzgException(e.getMessage()); + } } + + /** + * 金额转换 + */ + private static String getYuanAmountByFen(Long amount) { + BigDecimal yuanAmount = new BigDecimal(amount).divide(new BigDecimal(100)); + return yuanAmount.toString(); + } + } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/dto/AlipayAuthInfoDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/dto/AlipayAuthInfoDto.java new file mode 100644 index 000000000..873ca6c82 --- /dev/null +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/dto/AlipayAuthInfoDto.java @@ -0,0 +1,63 @@ +package com.czg.third.alipay.dto; + +import com.alibaba.fastjson2.annotation.JSONField; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 支付宝授权信息 + * @author yjjie + * @date 2026/1/9 11:31 + */ +@Data +@Accessors(chain = true) +public class AlipayAuthInfoDto { + + /** + * 授权商户的user_id + */ + @JSONField(name = "user_id") + private String userId; + + /** + * 授权商户的open_id + */ + @JSONField(name = "open_id") + private String openId; + + /** + * 授权商户的appid + */ + @JSONField(name = "auth_app_id") + private String authAppId; + + /** + * 应用授权令牌 + */ + @JSONField(name = "app_auth_token") + private String appAuthToken; + + /** + * 应用授权令牌有效期 + */ + @JSONField(name = "expires_in") + private String expiresIn; + + /** + * 刷新令牌 + */ + @JSONField(name = "app_refresh_token") + private String appRefreshToken; + + /** + * 刷新令牌的有效时间 + */ + @JSONField(name = "re_expires_in") + private String reExpiresIn; + + /** + * 签约单号 + */ + @JSONField(name = "order_no") + private String orderNo; +} diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java index a656b42f8..cecb71d38 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java @@ -15,6 +15,7 @@ import com.czg.third.wechat.dto.req.entry.business.WechatEntryLicenseReqDto; import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryMiniProgramReqDto; import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntrySalesInfoReqDto; import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryStoreInfoReqDto; +import com.czg.third.wechat.dto.req.entry.id.WechatEntryIdCardReqDto; import com.czg.third.wechat.dto.resp.WechatAuditDetail; import com.czg.third.wechat.dto.resp.WechatQueryStateResp; import com.czg.utils.UploadFileUtil; @@ -102,12 +103,12 @@ public class WechatEntryManager { * @param reqDto 请求信息 */ public static EntryThirdRespDto entryMerchant(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) { - WechatEntryReqDto entryReqDto = buildEntryParams(configDto, reqDto); EntryThirdRespDto respDto = new EntryThirdRespDto() .setPlatform(PayCst.Platform.WECHAT); - - log.info("微信进件参数:{}", JSONObject.toJSONString(entryReqDto)); try { + WechatEntryReqDto entryReqDto = buildEntryParams(configDto, reqDto); + log.info("微信进件参数:{}", JSONObject.toJSONString(entryReqDto)); + String params = JSONObject.toJSONString(entryReqDto, JSONWriter.Feature.IgnoreEmpty); String respBody = WechatReqUtils.postReq(configDto, "/v3/applyment4sub/applyment/", params); JSONObject object = JSONObject.parseObject(respBody); @@ -123,7 +124,7 @@ public class WechatEntryManager { respDto.setErrorMsg(object.getString("message")); } } catch (Exception e) { - log.error("微信进件报错:{}", e.getMessage(), e); + log.error("微信进件报错:{}", e.getMessage()); respDto.setStatus(PayCst.EntryStatus.REJECTED); respDto.setEntryId(""); respDto.setErrorMsg(e.getMessage()); @@ -282,6 +283,16 @@ public class WechatEntryManager { subjectInfo.setBusinessLicenseInfo(licenseReqDto); WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto(); identityInfo.setIdHolderType(PayCst.ContactPersonType.LEGAL); + identityInfo.setIdDocType("IDENTIFICATION_TYPE_IDCARD"); + WechatEntryIdCardReqDto idCardInfo = new WechatEntryIdCardReqDto(); + idCardInfo.setIdCardCopy(legalPersonInfo.getIdCardFrontPic().getWechatId()); + idCardInfo.setIdCardNational(legalPersonInfo.getIdCardFrontPic().getWechatId()); + idCardInfo.setIdCardName(encryptor.encrypt(legalPersonInfo.getLegalPersonName())); + idCardInfo.setIdCardNumber(encryptor.encrypt(legalPersonInfo.getLegalPersonId())); + idCardInfo.setIdCardAddress(encryptor.encrypt(legalPersonInfo.getLegalAddress())); + idCardInfo.setCardPeriodBegin(legalPersonInfo.getLegalIdPersonStartDate()); + idCardInfo.setCardPeriodEnd(legalPersonInfo.getLegalPersonIdEndDate()); + identityInfo.setIdCardInfo(idCardInfo); subjectInfo.setIdentityInfo(identityInfo); entryParams.setSubjectInfo(subjectInfo); diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatPayManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatPayManager.java index 1b1d914ad..415edd6d4 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatPayManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatPayManager.java @@ -1,11 +1,44 @@ package com.czg.third.wechat; +import com.alibaba.fastjson2.JSONObject; +import com.czg.dto.req.PayParamsDto; +import com.czg.third.wechat.dto.config.WechatPayConfigDto; +import lombok.extern.slf4j.Slf4j; + /** * @author yjjie * @date 2025/12/26 09:15 */ +@Slf4j public class WechatPayManager { - public static void main(String[] args) { + /** + * jsapi 小程序支付 + * @param configDto 配置 + * @param paramsDto 参数 + */ + public static String jsapiPay(WechatPayConfigDto configDto, PayParamsDto paramsDto) { + if (configDto == null) { + configDto = WechatPayConfigDto.getDefaultConfig(); + } + JSONObject reqData = new JSONObject(); + reqData.put("sp_appid", paramsDto.getAppId()); + reqData.put("sp_mchid", configDto.getMerchantId()); + reqData.put("sub_mchid", paramsDto.getMerchantId()); + reqData.put("description", paramsDto.getTitle()); + reqData.put("out_trade_no", paramsDto.getOrderNo()); + reqData.put("notify_url", paramsDto.getNotifyUrl()); + + JSONObject amount = new JSONObject(); + amount.put("total", paramsDto.getAmount()); + reqData.put("amount", amount); + + JSONObject payer = new JSONObject(); + payer.put("sp_openid", paramsDto.getOpenId()); + reqData.put("payer", payer); + + String string = WechatReqUtils.postReq(configDto, "/v3/pay/partner/transactions/jsapi", reqData.toJSONString()); + log.info("微信支付请求结果: orderNo = {}, res = {}", paramsDto.getOrderNo(), string); + return ""; } } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatReqUtils.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatReqUtils.java index 32c95eec2..6c8327684 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatReqUtils.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatReqUtils.java @@ -92,7 +92,7 @@ public class WechatReqUtils { Config config = WechatConfig.getRsaConfig(configDto); Signer signer = config.createSigner(); String signature = signer.sign(encryptStr).getSign(); - log.info("微信签名 encryptStr = {},\nsignature:{}", encryptStr, signature); + log.info("微信签名 encryptStr = \n{} \nsignature:{}", encryptStr, signature); return signature; }