Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
193f4d016a | ||
|
|
8501e21cf4 | ||
|
|
6ec6fafc98 | ||
|
|
7efc46126c | ||
|
|
8d9878a316 | ||
|
|
9a1b5b5cae | ||
|
|
484c40cdb5 | ||
|
|
8a8cef3005 | ||
|
|
38ea1478cb | ||
|
|
2046ad2486 | ||
|
|
0cdad226ea | ||
|
|
e179a910ba | ||
|
|
6b5c451f92 | ||
|
|
303db8bc49 |
@@ -0,0 +1,39 @@
|
||||
package com.czg.controller;
|
||||
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.ShopUserFlowService;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.account.service.TestService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author GYJoker
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/notify/test")
|
||||
public class TestController {
|
||||
@Resource
|
||||
private ShopUserFlowService shopUserFlowService;
|
||||
@Resource
|
||||
private ShopInfoService shopInfoService;
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
@Resource
|
||||
private TestService testService;
|
||||
|
||||
@RequestMapping("/hello")
|
||||
public String hello() {
|
||||
shopUserFlowService.list().forEach(item -> {
|
||||
ShopUser shopUserInfo = shopUserService.getShopUserInfo(item.getShopId(), item.getUserId());
|
||||
if (shopUserInfo != null) {
|
||||
item.setShopUserId(shopUserInfo.getId());
|
||||
shopUserFlowService.updateById(item);
|
||||
}
|
||||
});
|
||||
// return testService.insertData();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import com.czg.market.vo.InviteUserVO;
|
||||
import com.czg.market.vo.MkDistributionConfigVO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.task.DistributionTask;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -38,22 +37,6 @@ public class UDistributionController {
|
||||
private MkDistributionWithdrawFlowService withdrawFlowService;
|
||||
@Resource
|
||||
private MkDistributionFlowService distributionFlowService;
|
||||
@Resource
|
||||
private DistributionTask distributionTask;
|
||||
|
||||
/**
|
||||
* 分销员中心-获取配置
|
||||
*/
|
||||
@GetMapping("/task")
|
||||
public CzgResult<String> task(@RequestParam Long shopId) {
|
||||
try {
|
||||
distributionTask.deliver(shopId);
|
||||
} catch (Exception e) {
|
||||
return CzgResult.failure(e.getMessage());
|
||||
}
|
||||
return CzgResult.success("任务执行成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分销员中心-获取配置
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* market服务 任务总调度
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Component
|
||||
@@ -19,9 +18,9 @@ public class AAMarketTasks {
|
||||
|
||||
|
||||
// 分销延时发放
|
||||
@Scheduled(cron = "0 0 0/2 * * ? ")
|
||||
@Scheduled(fixedRate = 30000)
|
||||
public void distributionTask() {
|
||||
distributionTask.deliver(null);
|
||||
distributionTask.deliver();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +29,6 @@ public class AAMarketTasks {
|
||||
public void birthdayGiftTask() {
|
||||
birthdayGiftTask.deliver();
|
||||
}
|
||||
|
||||
//会员生日弹窗提醒重置 每年1月1日
|
||||
@Scheduled(cron = "0 0 0 1 1 ?")
|
||||
public void birthdayGiftRemindTask() {
|
||||
@@ -41,7 +39,6 @@ public class AAMarketTasks {
|
||||
//优惠券 过期
|
||||
@Resource
|
||||
private CouponTask couponTask;
|
||||
|
||||
//每天每小时的30分 0秒 执行
|
||||
@Scheduled(cron = "0 30 * * * ? ")
|
||||
public void couponTask() {
|
||||
@@ -51,7 +48,6 @@ public class AAMarketTasks {
|
||||
//会员奖励发放
|
||||
@Resource
|
||||
private MemberTask memberTask;
|
||||
|
||||
//每天1点 0分 0秒 执行
|
||||
@Scheduled(cron = "0 0 1 * * ? ")
|
||||
public void memberTask() {
|
||||
@@ -61,7 +57,6 @@ public class AAMarketTasks {
|
||||
//满减活动/限时折扣 处理任务状态 定时任务
|
||||
@Resource
|
||||
private ActivityStatusTask activityStatusTask;
|
||||
|
||||
//每天0点 0分 1秒 执行
|
||||
@Scheduled(cron = "1 0 0 * * ? ")
|
||||
public void activityStatusTask() {
|
||||
@@ -72,7 +67,6 @@ public class AAMarketTasks {
|
||||
//月累计 发送条数 累计金额
|
||||
@Resource
|
||||
private SmsShopMoneyTask smsShopMoneyTask;
|
||||
|
||||
//每月1号 0点 0分 1秒 执行
|
||||
@Scheduled(cron = "1 0 0 1 * ?")
|
||||
public void smsShopMoneyTask() {
|
||||
|
||||
@@ -2,13 +2,10 @@ package com.czg.task;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.constant.TableValueConstant;
|
||||
import com.czg.constants.SystemConstants;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.entity.MkDistributionFlow;
|
||||
import com.czg.market.service.MkDistributionFlowService;
|
||||
import com.czg.market.service.MkDistributionUserService;
|
||||
@@ -21,7 +18,6 @@ import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -44,6 +40,8 @@ public class DistributionTask {
|
||||
private OrderInfoService orderInfoService;
|
||||
@DubboReference
|
||||
private ShopInfoService shopInfoService;
|
||||
@DubboReference
|
||||
private ShopUserService shopUserService;
|
||||
|
||||
List<String> list = List.of(OrderStatusEnums.REFUND.getCode(), OrderStatusEnums.PART_REFUND.getCode());
|
||||
|
||||
@@ -53,55 +51,44 @@ public class DistributionTask {
|
||||
*/
|
||||
// @Scheduled(cron = "0 0 0 * * ?")
|
||||
// @Scheduled(fixedRate = 30000)
|
||||
public void deliver(Long shopId) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<ShopInfo> shopInfos = shopInfoService.list(QueryWrapper.create()
|
||||
.eq(ShopInfo::getIsDeleted, SystemConstants.OneZero.ZERO)
|
||||
.isNotNull(ShopInfo::getExpireTime)
|
||||
.lt(ShopInfo::getExpireTime, now)
|
||||
.gt(ShopInfo::getAmount, BigDecimal.ZERO)
|
||||
.eq(ShopInfo::getId, shopId)
|
||||
);
|
||||
if (CollUtil.isEmpty(shopInfos)) {
|
||||
log.info("分销延时分账 无符合条件的店铺,无需处理分账");
|
||||
return;
|
||||
}
|
||||
for (ShopInfo shopInfo : shopInfos) {
|
||||
boolean breakCurrentShopFlow = false;
|
||||
List<MkDistributionFlow> flowList = distributionFlowService.list(new QueryWrapper()
|
||||
.eq(MkDistributionFlow::getShopId, shopInfo.getId())
|
||||
.eq(MkDistributionFlow::getStatus, TableValueConstant.DistributionFlow.Status.PENDING.getCode())
|
||||
.le(MkDistributionFlow::getDeliverTime, now)
|
||||
.orderBy(MkDistributionFlow::getId, true)
|
||||
);
|
||||
for (MkDistributionFlow item : flowList) {
|
||||
if (breakCurrentShopFlow) {
|
||||
break;
|
||||
public void deliver() {
|
||||
// 1. 订单完成支付时(判断是否分销)产生流水记录。
|
||||
// 2. 判断入账时间。
|
||||
// 3. 如果是 0 天,再去判断商户余额是否足够。够则入账,不足则不管。
|
||||
// 4. 流水增加应该入账的时间(订单产生时带入)
|
||||
// 5. 定时任务 应该是一天执行一次。查询待入账状态和应入账时间小于当前时间的记录,循环处理:并且判断商户余额是否足够,余额不足忽略处理;余额足够变为已入账并扣除商户余额。
|
||||
// 6. 订单产生退款时,去流水表查询该订单的流水记录,如果未入账改为已入账,并插入一条退款扣钱的流水。
|
||||
|
||||
// shopInfo 查余额>0
|
||||
// 循环 shopId 查询 如果金额不足 终止
|
||||
//
|
||||
LocalDateTime localDateTime = DateUtil.date().toLocalDateTime();
|
||||
distributionFlowService.list(new QueryWrapper()
|
||||
.eq(MkDistributionFlow::getStatus, TableValueConstant.DistributionFlow.Status.PENDING.getCode()).le(MkDistributionFlow::getDeliverTime, localDateTime)).forEach(item -> {
|
||||
FunUtils.safeRunVoid(() -> {
|
||||
log.info("开始处理延时分账, id: {}, orderNo: {}, 类型: {}", item.getId(), item.getOrderNo(), item.getType());
|
||||
|
||||
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getOrderNo, item.getOrderNo()));
|
||||
if (orderInfo == null) {
|
||||
item.setStatus(TableValueConstant.DistributionFlow.Status.FAIL.getCode());
|
||||
distributionFlowService.updateById(item);
|
||||
log.warn("订单不存在, 订单号: {}", item.getOrderNo());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
log.info("分销延时分账, id: {}, orderNo: {}, 类型: {}", item.getId(), item.getOrderNo(), item.getType());
|
||||
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getOrderNo, item.getOrderNo()));
|
||||
if (orderInfo == null) {
|
||||
item.setStatus(TableValueConstant.DistributionFlow.Status.FAIL.getCode());
|
||||
distributionFlowService.updateById(item);
|
||||
log.warn("分销延时分账。订单不存在, 订单号: {}", item.getOrderNo());
|
||||
continue;
|
||||
}
|
||||
if (list.contains(orderInfo.getStatus())) {
|
||||
log.warn("分销延时分账。订单已退款, 订单号: {}", item.getOrderNo());
|
||||
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
||||
} else {
|
||||
item.setStatus(TableValueConstant.DistributionFlow.Status.SUCCESS.getCode());
|
||||
distributionUserService.distributionUserAmount(item, orderInfo);
|
||||
}
|
||||
} catch (CzgException e) {
|
||||
log.error("店铺{}:{}分销延时分账异常:{}", shopInfo.getId(), shopInfo.getShopName(), e.getMessage());
|
||||
breakCurrentShopFlow = true;
|
||||
} catch (Exception e) {
|
||||
log.error("店铺{}:{}分销延时分账异常", shopInfo.getId(), shopInfo.getShopName(), e);
|
||||
breakCurrentShopFlow = true;
|
||||
if (list.contains(orderInfo.getStatus())) {
|
||||
log.warn("订单已退款, 订单号: {}", item.getOrderNo());
|
||||
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
||||
} else {
|
||||
item.setStatus(TableValueConstant.DistributionFlow.Status.SUCCESS.getCode());
|
||||
ShopUser shopUser = shopUserService.getById(item.getDistributionUserId());
|
||||
distributionUserService.updateShopInfoAmount(orderInfo.getShopId(), item.getRewardAmount().negate(), orderInfo.getId(), TableValueConstant.DistributionAmountFlow.Type.SUB, "分销扣减");
|
||||
distributionUserService.updateIncome(item.getRewardAmount().negate(), item.getRewardAmount(), BigDecimal.ZERO,
|
||||
item.getDistributionUserId(), shopUser.getUserId(), item.getShopUserId(), item.getShopId(), item.getLevel());
|
||||
distributionFlowService.updateById(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ public class NotifyController {
|
||||
@Resource
|
||||
private MkShopConsumeDiscountRecordService consumeDiscountRecordService;
|
||||
|
||||
|
||||
//新客立减清除数据 测试用
|
||||
@RequestMapping("clear")
|
||||
public String clear(@RequestParam Integer shopId) {
|
||||
consumeDiscountRecordService.remove(new QueryWrapper().eq(MkShopConsumeDiscountRecord::getShopId, shopId));
|
||||
|
||||
@@ -21,7 +21,7 @@ public class StatisticTaskController {
|
||||
private StatisticTask statisticTask;
|
||||
|
||||
/**
|
||||
* 基础统计 预留重置统计
|
||||
* 基础统计
|
||||
*
|
||||
* @param date 日期yyyy-MM-dd
|
||||
*/
|
||||
|
||||
@@ -48,9 +48,6 @@ public class OrderMqListener {
|
||||
orderInfoCustomService.updateOrderDetailStatus(Long.valueOf(finalInfo));
|
||||
|
||||
});
|
||||
info = info.replace("UP_ORDER_DETAIL:", "");
|
||||
System.out.println(info);
|
||||
|
||||
}
|
||||
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_STOCK_QUEUE})
|
||||
|
||||
@@ -39,7 +39,7 @@ public class OTimeTask {
|
||||
@Resource
|
||||
private CashierCartService cartService;
|
||||
@Resource
|
||||
private OrderPaymentService paymentService;
|
||||
private OrderPaymentService orderPaymentService;
|
||||
@Resource
|
||||
private GbOrderService gbOrderService;
|
||||
@Resource
|
||||
@@ -117,7 +117,7 @@ public class OTimeTask {
|
||||
|
||||
LocalDateTime tenMinutesAgo = LocalDateTime.now().minusMinutes(10);
|
||||
LocalDateTime thirdDayAgo = LocalDateTime.now().minusDays(3);
|
||||
List<OrderPayment> list = paymentService.list(QueryWrapper.create()
|
||||
List<OrderPayment> list = orderPaymentService.list(QueryWrapper.create()
|
||||
.gt(OrderPayment::getUpdateTime, thirdDayAgo)
|
||||
.lt(OrderPayment::getUpdateTime, tenMinutesAgo)
|
||||
.in(OrderPayment::getSourceType, ware)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.czg.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.mybatisflex.core.audit.AuditManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -18,24 +17,8 @@ public class MybatisFlexConfig {
|
||||
//设置 SQL 审计收集器
|
||||
AuditManager.setMessageCollector(auditMessage ->
|
||||
log.info("[sql] time: {}, size: {}, sql:\n{}",
|
||||
auditMessage.getElapsedTime(), auditMessage.getQueryCount(), compressSql(auditMessage.getFullSql())));
|
||||
auditMessage.getElapsedTime(), auditMessage.getQueryCount(), auditMessage.getFullSql())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 精简SQL:去除多余换行、制表符、连续空格,保留语法必需空格
|
||||
*
|
||||
* @param originalSql 原始带换行/空格的SQL
|
||||
* @return 精简后的SQL
|
||||
*/
|
||||
public static String compressSql(String originalSql) {
|
||||
if (StrUtil.isBlank(originalSql)) {
|
||||
return "";
|
||||
}
|
||||
// 1. 替换所有换行、制表符为单个空格
|
||||
String tempSql = originalSql.replaceAll("\\r\\n|\\r|\\n|\\t", " ");
|
||||
// 2. 替换多个连续空格为单个空格
|
||||
tempSql = tempSql.replaceAll("\\s+", " ");
|
||||
// 3. 去除首尾空格
|
||||
return tempSql.trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,10 @@ import com.czg.exception.CzgException;
|
||||
import com.czg.market.dto.MkDistributionUserDTO;
|
||||
import com.czg.market.dto.MkDistributionWithdrawFlowDTO;
|
||||
import com.czg.market.entity.MkDistributionConfig;
|
||||
import com.czg.market.entity.MkDistributionFlow;
|
||||
import com.czg.market.entity.MkDistributionUser;
|
||||
import com.czg.market.vo.DistributionCenterShopVO;
|
||||
import com.czg.market.vo.InviteUserVO;
|
||||
import com.czg.order.dto.MkDistributionPayDTO;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
@@ -125,8 +123,6 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
|
||||
void refund(Long orderId, String orderNo);
|
||||
|
||||
void distributionUserAmount(MkDistributionFlow item, OrderInfo orderInfo);
|
||||
|
||||
/**
|
||||
* 发放分销奖励
|
||||
*
|
||||
|
||||
@@ -41,7 +41,6 @@ public class OrderDetailSmallVO implements Serializable {
|
||||
private LocalDateTime startOrderTime;
|
||||
private LocalDateTime dishOutTime;
|
||||
private LocalDateTime foodServeTime;
|
||||
private Integer isTemporary;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
<pinyin.version>2.5.1</pinyin.version>
|
||||
<IJPay.version>2.9.10</IJPay.version>
|
||||
<netty.version>4.1.128.Final</netty.version>
|
||||
<wechatpay.version>0.2.17</wechatpay.version>
|
||||
<apipay-v3.version>3.1.65.ALL</apipay-v3.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -268,6 +270,18 @@
|
||||
<artifactId>netty-codec-mqtt</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
<version>${wechatpay.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java-v3</artifactId>
|
||||
<version>${apipay-v3.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
35
cash-sdk/aggregation-pay/pom.xml
Normal file
35
cash-sdk/aggregation-pay/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-sdk</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>aggregation-pay</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>聚合支付</name>
|
||||
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java-v3</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
312
cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java
Normal file
312
cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java
Normal file
@@ -0,0 +1,312 @@
|
||||
package com.czg;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.dto.req.*;
|
||||
import com.czg.dto.resp.BankBranchDto;
|
||||
import com.czg.dto.resp.EntryRespDto;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.AlipayEntryManager;
|
||||
import com.czg.third.wechat.WechatEntryManager;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.AsyncTaskExecutor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 进件管理
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 13:56
|
||||
*/
|
||||
public class EntryManager {
|
||||
|
||||
/**
|
||||
* 查询银行支行列表
|
||||
*
|
||||
* @param province 省份 陕西省
|
||||
* @param city 城市 西安市
|
||||
* @param instId 顶级机构ID CMB
|
||||
*/
|
||||
public static List<BankBranchDto> queryBankBranchList(String province, String city, String instId) {
|
||||
return AlipayEntryManager.queryBankBranchList(instId, province, city);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进件
|
||||
* 请先执行:
|
||||
* 1. {@link com.czg.EntryManager#verifyEntryParam(AggregateMerchantDto)} 验证进件参数
|
||||
* 2. {@link com.czg.EntryManager#uploadParamImage(AggregateMerchantDto)} 上传图片至第三方
|
||||
*
|
||||
* @param reqDto 进件参数
|
||||
*/
|
||||
public static EntryRespDto entryMerchant(AggregateMerchantDto reqDto) {
|
||||
List<Supplier<EntryRespDto>> tasks = new ArrayList<>();
|
||||
tasks.add(() -> WechatEntryManager.entryMerchant(null, reqDto));
|
||||
tasks.add(() -> AlipayEntryManager.entryMerchant(null, reqDto));
|
||||
|
||||
// 执行所有任务
|
||||
List<AsyncTaskExecutor.TaskResult<EntryRespDto>> results = AsyncTaskExecutor.executeAll(tasks);
|
||||
for (AsyncTaskExecutor.TaskResult<EntryRespDto> result : results) {
|
||||
// 合并两个进件结果
|
||||
}
|
||||
|
||||
return new EntryRespDto();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片至第三方
|
||||
* 请先执行 {@link com.czg.EntryManager#verifyEntryParam(AggregateMerchantDto)} 验证进件参数
|
||||
*
|
||||
* @param reqDto 进件参数
|
||||
*/
|
||||
public static void uploadParamImage(AggregateMerchantDto reqDto) {
|
||||
List<Supplier<Void>> tasks = new ArrayList<>();
|
||||
|
||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
||||
// 联系人身份证反面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(baseInfo.getContactIdCardBackPic());
|
||||
return null;
|
||||
});
|
||||
// 联系人身份证正面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(baseInfo.getContactIdCardFrontPic());
|
||||
return null;
|
||||
});
|
||||
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
// 法人身份证反面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(legalPersonInfo.getIdCardBackPic());
|
||||
return null;
|
||||
});
|
||||
// 法人身份证正面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(legalPersonInfo.getIdCardFrontPic());
|
||||
return null;
|
||||
});
|
||||
// 法人手持身份证
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(legalPersonInfo.getIdCardHandPic());
|
||||
return null;
|
||||
});
|
||||
|
||||
BusinessLicenceInfoDto businessLicenceInfo = reqDto.getBusinessLicenceInfo();
|
||||
// 营业执照
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(businessLicenceInfo.getLicensePic());
|
||||
return null;
|
||||
});
|
||||
|
||||
SettlementInfoDto settlementInfo = reqDto.getSettlementInfo();
|
||||
// 银行卡背面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getBankCardBackPic());
|
||||
return null;
|
||||
});
|
||||
// 银行卡正面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getBankCardFrontPic());
|
||||
return null;
|
||||
});
|
||||
// 开户许可证
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getOpenAccountLicencePic());
|
||||
return null;
|
||||
});
|
||||
// 非法人手持授权函
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getNoLegalHandSettleAuthPic());
|
||||
return null;
|
||||
});
|
||||
// 非法人授权函
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getNoLegalSettleAuthPic());
|
||||
return null;
|
||||
});
|
||||
// 非法人身份证反面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getNoLegalIdCardBackPic());
|
||||
return null;
|
||||
});
|
||||
// 非法人身份证正面
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(settlementInfo.getNoLegalIdCardFrontPic());
|
||||
return null;
|
||||
});
|
||||
|
||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
||||
// 店内图片
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(storeInfo.getInsidePic());
|
||||
return null;
|
||||
});
|
||||
// 门店门头图片
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(storeInfo.getDoorPic());
|
||||
return null;
|
||||
});
|
||||
// 收银台图片
|
||||
tasks.add(() -> {
|
||||
uploadImageToThird(storeInfo.getCashierDeskPic());
|
||||
return null;
|
||||
});
|
||||
|
||||
// 执行所有任务
|
||||
AsyncTaskExecutor.executeAll(tasks);
|
||||
}
|
||||
|
||||
private static void uploadImageToThird(ImageDto dto) {
|
||||
if (dto != null && StrUtil.isNotBlank(dto.getUrl())) {
|
||||
if (StrUtil.isBlank(dto.getWechatId())) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证进件参数
|
||||
*
|
||||
* @param reqDto 进件参数
|
||||
*/
|
||||
public static void verifyEntryParam(AggregateMerchantDto reqDto) {
|
||||
AssertUtil.isBlank(reqDto.getMerchantCode(), "商户编号不能为空");
|
||||
|
||||
AssertUtil.isNull(reqDto.getMerchantBaseInfo(), "商户基础信息不能为空");
|
||||
|
||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
||||
AssertUtil.isBlank(baseInfo.getUserType(), "商户类型不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getShortName(), "商户简称不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getCertType(), "证件类型不能为空");
|
||||
if (!"0".equals(baseInfo.getCertType())) {
|
||||
throw new CzgException("证件类型错误");
|
||||
}
|
||||
AssertUtil.isBlank(baseInfo.getMccCode(), "商户行业编码不能为空");
|
||||
if ("SUPER".equals(baseInfo.getContactPersonType())) {
|
||||
AssertUtil.isBlank(baseInfo.getContactName(), "联系人姓名不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPersonId(), "联系人身份证号不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPhone(), "联系人电话不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactAddr(), "联系人地址不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactEmail(), "联系人邮箱不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactIdStartDate(), "联系人身份证开始日期不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPersonIdEndDate(), "联系人身份证到期日期不能为空");
|
||||
AssertUtil.isNull(baseInfo.getContactIdCardBackPic(), "联系人身份证反面不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactIdCardBackPic().getUrl(), "联系人身份证反面不能为空");
|
||||
AssertUtil.isNull(baseInfo.getContactIdCardFrontPic(), "联系人身份证正面不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactIdCardFrontPic().getUrl(), "联系人身份证正面不能为空");
|
||||
}
|
||||
AssertUtil.isBlank(baseInfo.getCompanyChildType(), "商户类型不能为空");
|
||||
if ("0".equals(baseInfo.getUserType())) {
|
||||
// 个体商户, 暂无其他校验
|
||||
} else if ("1".equals(baseInfo.getUserType())) {
|
||||
if (!"1".equals(baseInfo.getCompanyChildType()) && !"2".equals(baseInfo.getCompanyChildType()) && !"3".equals(baseInfo.getCompanyChildType())) {
|
||||
throw new CzgException("商户类型错误");
|
||||
}
|
||||
} else {
|
||||
throw new CzgException("商户类型错误");
|
||||
}
|
||||
|
||||
AssertUtil.isNull(reqDto.getBusinessLicenceInfo(), "营业执照信息不能为空");
|
||||
BusinessLicenceInfoDto businessLicenceInfo = reqDto.getBusinessLicenceInfo();
|
||||
AssertUtil.isBlank(businessLicenceInfo.getLicenceNo(), "营业执照编号不能为空");
|
||||
AssertUtil.isBlank(businessLicenceInfo.getLicenceName(), "营业执照名称不能为空");
|
||||
AssertUtil.isBlank(businessLicenceInfo.getRegisteredAddress(), "营业执照注册地址不能为空");
|
||||
AssertUtil.isBlank(businessLicenceInfo.getLicenceStartDate(), "营业执照开始日期不能为空");
|
||||
AssertUtil.isBlank(businessLicenceInfo.getLicenceEndDate(), "营业执照到期日期不能为空");
|
||||
AssertUtil.isNull(businessLicenceInfo.getLicensePic(), "营业执照名称不能为空");
|
||||
AssertUtil.isBlank(businessLicenceInfo.getLicensePic().getUrl(), "营业执照名称不能为空");
|
||||
|
||||
|
||||
AssertUtil.isNull(reqDto.getLegalPersonInfo(), "法人信息不能为空");
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonName(), "法人姓名不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonId(), "法人身份证号不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalIdStartDate(), "法人身份证开始日期不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonIdEndDate(), "法人身份证到期日期不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonPhone(), "法人电话不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalGender(), "法人性别不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalAddress(), "法人地址不能为空");
|
||||
AssertUtil.isNull(legalPersonInfo.getIdCardHandPic(), "法人身份证手持不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getIdCardHandPic().getUrl(), "法人身份证手持不能为空");
|
||||
AssertUtil.isNull(legalPersonInfo.getIdCardFrontPic(), "法人身份证正面不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getIdCardFrontPic().getUrl(), "法人身份证正面不能为空");
|
||||
AssertUtil.isNull(legalPersonInfo.getIdCardBackPic(), "法人身份证反面不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getIdCardBackPic().getUrl(), "法人身份证反面不能为空");
|
||||
|
||||
AssertUtil.isNull(reqDto.getStoreInfo(), "门店信息不能为空");
|
||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
||||
AssertUtil.isBlank(storeInfo.getMercProvId(), "门店省ID不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercCityId(), "门店市ID不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercAreaId(), "门店区ID不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercProv(), "门店省不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercCity(), "门店市不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercArea(), "门店区不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getBusinessAddress(), "门店营业地址不能为空");
|
||||
AssertUtil.isNull(storeInfo.getInsidePic(), "门店营业地址不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getInsidePic().getUrl(), "门店营业地址不能为空");
|
||||
AssertUtil.isNull(storeInfo.getDoorPic(), "门店门头照不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getDoorPic().getUrl(), "门店门头照不能为空");
|
||||
AssertUtil.isNull(storeInfo.getCashierDeskPic(), "门店收银台照不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getCashierDeskPic().getUrl(), "门店收银台照不能为空");
|
||||
|
||||
|
||||
AssertUtil.isNull(reqDto.getSettlementInfo(), "结算信息不能为空");
|
||||
SettlementInfoDto settlementInfo = reqDto.getSettlementInfo();
|
||||
AssertUtil.isBlank(settlementInfo.getSettlementCardNo(), "结算卡号不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getSettlementName(), "结算账户户名不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getBankMobile(), "结算银行预留手机号不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getSettlementCardType(), "结算卡类型不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccProvinceId(), "结算开户行省ID不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccCityId(), "结算开户行市ID不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccAreaId(), "结算开户行区ID不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccProvince(), "结算开户行省不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccCity(), "结算开户行市不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccArea(), "结算开户行区不能为空");
|
||||
if ("11".equals(settlementInfo.getSettlementCardType())) {
|
||||
// 11 对私借记卡(结算卡正面照、结算卡反面照图片必传)
|
||||
AssertUtil.isNull(settlementInfo.getBankCardFrontPic(), "结算卡正面照不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getBankCardFrontPic().getUrl(), "结算卡正面照不能为空");
|
||||
AssertUtil.isNull(settlementInfo.getBankCardBackPic(), "结算卡反面照不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getBankCardBackPic().getUrl(), "结算卡反面照不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getSettlementType(), "结算类型不能为空");
|
||||
if ("0".equals(settlementInfo.getSettlementType())) {
|
||||
// 非法人结算
|
||||
AssertUtil.isBlank(settlementInfo.getNoLegalName(), "非法人姓名不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getNoLegalId(), "非法人身份证号不能为空");
|
||||
AssertUtil.isNull(settlementInfo.getNoLegalIdCardFrontPic(), "非法人身份证正面不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getNoLegalIdCardFrontPic().getUrl(), "非法人身份证正面不能为空");
|
||||
AssertUtil.isNull(settlementInfo.getNoLegalIdCardBackPic(), "非法人身份证反面不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getNoLegalIdCardBackPic().getUrl(), "非法人身份证反面不能为空");
|
||||
AssertUtil.isNull(settlementInfo.getNoLegalSettleAuthPic(), "非法人结算授权书不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getNoLegalSettleAuthPic().getUrl(), "非法人结算授权书不能为空");
|
||||
} else if ("1".equals(settlementInfo.getSettlementType())) {
|
||||
// 法人结算 暂无处理
|
||||
} else {
|
||||
throw new CzgException("结算类型错误");
|
||||
}
|
||||
} else if ("21".equals(settlementInfo.getSettlementCardType())) {
|
||||
// 21 对公借记卡(只须结算卡正面照片)
|
||||
AssertUtil.isNull(settlementInfo.getOpenAccountLicencePic(), "开户许可证不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getOpenAccountLicencePic().getUrl(), "开户许可证不能为空");
|
||||
} else {
|
||||
throw new CzgException("结算卡类型错误");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
AggregateMerchantDto merchantDto = new AggregateMerchantDto();
|
||||
merchantDto.setMerchantCode("20220106000000000001");
|
||||
|
||||
// verifyEntryParam(merchantDto);
|
||||
uploadParamImage(merchantDto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 统一进件
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:02
|
||||
*/
|
||||
@Data
|
||||
public class AggregateMerchantDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户编号(在当前系统唯一)
|
||||
*/
|
||||
private String merchantCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户基础信息
|
||||
*/
|
||||
private MerchantBaseInfoDto merchantBaseInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人信息
|
||||
*/
|
||||
private LegalPersonInfoDto legalPersonInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 营业执照信息
|
||||
*/
|
||||
private BusinessLicenceInfoDto businessLicenceInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 门店信息
|
||||
*/
|
||||
private StoreInfoDto storeInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 结算信息
|
||||
*/
|
||||
private SettlementInfoDto settlementInfo;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 营业执照信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:17
|
||||
*/
|
||||
@Data
|
||||
public class BusinessLicenceInfoDto {
|
||||
|
||||
/**
|
||||
* 营业执照全称--非小微必填
|
||||
*/
|
||||
private String licenceName;
|
||||
|
||||
/**
|
||||
* 营业执照号码--非小微必填
|
||||
*/
|
||||
private String licenceNo;
|
||||
|
||||
/**
|
||||
* 营业执照开始日期--非小微必填
|
||||
*/
|
||||
private String licenceStartDate;
|
||||
|
||||
/**
|
||||
* 营业执照结束日期--非小微必填
|
||||
*/
|
||||
private String licenceEndDate;
|
||||
|
||||
/**
|
||||
* 营业执照注册地址--非小微必填
|
||||
*/
|
||||
private String registeredAddress;
|
||||
|
||||
/**
|
||||
* 营业执照
|
||||
*/
|
||||
private ImageDto licensePic;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 16:53
|
||||
*/
|
||||
@Data
|
||||
public class ImageDto {
|
||||
|
||||
/**
|
||||
* 图片 url
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 微信 图片 mediaId
|
||||
*/
|
||||
private String wechatId;
|
||||
|
||||
/**
|
||||
* 支付宝 图片 mediaId
|
||||
*/
|
||||
private String alipayId;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 法人信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:13
|
||||
*/
|
||||
@Data
|
||||
public class LegalPersonInfoDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人姓名
|
||||
*/
|
||||
private String legalPersonName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人身份证号
|
||||
*/
|
||||
private String legalPersonId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人身份证开始日期
|
||||
*/
|
||||
private String legalIdStartDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人身份证到期日期
|
||||
*/
|
||||
private String legalPersonIdEndDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人电话
|
||||
*/
|
||||
private String legalPersonPhone;
|
||||
|
||||
/**
|
||||
* 法人性别(0男 1女)
|
||||
*/
|
||||
private String legalGender;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人地址
|
||||
*/
|
||||
private String legalAddress;
|
||||
|
||||
/**
|
||||
* 身份证手持 图片
|
||||
*/
|
||||
private ImageDto idCardHandPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证正面
|
||||
*/
|
||||
private ImageDto idCardFrontPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证反面
|
||||
*/
|
||||
private ImageDto idCardBackPic;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商户基础信息
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:09
|
||||
*/
|
||||
@Data
|
||||
public class MerchantBaseInfoDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户类型
|
||||
* 0: 个体商户;
|
||||
* 1: 企业商户;
|
||||
* 3: 小微商户
|
||||
*/
|
||||
private String userType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户简称--企业、个体必填
|
||||
*/
|
||||
private String shortName;
|
||||
|
||||
/**
|
||||
* 证件类型
|
||||
* 目前只支持身份证 传值:0
|
||||
*/
|
||||
private String certType = "0";
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 行业编码
|
||||
*/
|
||||
private String mccCode;
|
||||
|
||||
/**
|
||||
* 联系人类型
|
||||
* LEGAL: 经营者/法定代表人
|
||||
* SUPER: 经办人
|
||||
*/
|
||||
private String contactPersonType = "LEGAL";
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人姓名
|
||||
*/
|
||||
private String contactName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人身份证号
|
||||
*/
|
||||
private String contactPersonId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人身份证开始日期
|
||||
*/
|
||||
private String contactIdStartDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人身份证到期日期
|
||||
*/
|
||||
private String contactPersonIdEndDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人身份证背面
|
||||
*/
|
||||
private ImageDto contactIdCardBackPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人身份证正面
|
||||
*/
|
||||
private ImageDto contactIdCardFrontPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人电话
|
||||
*/
|
||||
private String contactPhone;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人通讯地址
|
||||
*/
|
||||
private String contactAddr;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人邮箱
|
||||
*/
|
||||
private String contactEmail;
|
||||
|
||||
/**
|
||||
* 企业类型,1:普通企业,2:事业单位,3:其他组织
|
||||
*/
|
||||
private String companyChildType = "1";
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 结算信息
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:22
|
||||
*/
|
||||
@Data
|
||||
public class SettlementInfoDto {
|
||||
|
||||
/**
|
||||
* 结算类型 0:非法人结算, 1:法人结算
|
||||
*/
|
||||
private String settlementType;
|
||||
|
||||
/**
|
||||
* 非法人姓名
|
||||
*/
|
||||
private String noLegalName;
|
||||
|
||||
/**
|
||||
* 非法人身份证号码
|
||||
*/
|
||||
private String noLegalId;
|
||||
|
||||
/**
|
||||
* 结算卡类型 必填 11 对私借记卡(结算卡正面照、结算卡反面照图片必传) 21 对公借记卡(只须结算卡正面照片)
|
||||
*/
|
||||
private String settlementCardType;
|
||||
|
||||
/**
|
||||
* 结算账户卡号
|
||||
*/
|
||||
private String settlementCardNo;
|
||||
|
||||
/**
|
||||
* 结算账户户名
|
||||
*/
|
||||
private String settlementName;
|
||||
|
||||
/**
|
||||
* 结算银行预留手机号
|
||||
*/
|
||||
private String bankMobile;
|
||||
|
||||
/**
|
||||
* 开户行省ID
|
||||
*/
|
||||
private String openAccProvinceId;
|
||||
|
||||
/**
|
||||
* 开户行市ID
|
||||
*/
|
||||
private String openAccCityId;
|
||||
|
||||
/**
|
||||
* 开户行区ID
|
||||
*/
|
||||
private String openAccAreaId;
|
||||
|
||||
/**
|
||||
* 开户行省
|
||||
*/
|
||||
private String openAccProvince;
|
||||
|
||||
/**
|
||||
* 开户行市
|
||||
*/
|
||||
private String openAccCity;
|
||||
|
||||
/**
|
||||
* 开户行区
|
||||
*/
|
||||
private String openAccArea;
|
||||
|
||||
/**
|
||||
* 开户行行别名称
|
||||
*/
|
||||
private String bankName;
|
||||
|
||||
/**
|
||||
* 开户行编号
|
||||
*/
|
||||
private String bankType;
|
||||
|
||||
/**
|
||||
* 支行开户行行别名称
|
||||
*/
|
||||
private String bankBranchName;
|
||||
|
||||
/**
|
||||
* 支行开户行编号
|
||||
*/
|
||||
private String bankBranchCode;
|
||||
|
||||
/**
|
||||
* 银行卡正面
|
||||
*/
|
||||
private ImageDto bankCardFrontPic;
|
||||
|
||||
/**
|
||||
* 银行卡反面
|
||||
*/
|
||||
private ImageDto bankCardBackPic;
|
||||
|
||||
/**
|
||||
* 开户许可证
|
||||
*/
|
||||
private ImageDto openAccountLicencePic;
|
||||
|
||||
/**
|
||||
* 非法人手持结算授权书
|
||||
*/
|
||||
private ImageDto noLegalHandSettleAuthPic;
|
||||
|
||||
/**
|
||||
* 非法人结算授权书
|
||||
*/
|
||||
private ImageDto noLegalSettleAuthPic;
|
||||
|
||||
/**
|
||||
* 非法人身份证正面
|
||||
*/
|
||||
private ImageDto noLegalIdCardFrontPic;
|
||||
|
||||
/**
|
||||
* 非法人身份证反面
|
||||
*/
|
||||
private ImageDto noLegalIdCardBackPic;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 门店信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:19
|
||||
*/
|
||||
@Data
|
||||
public class StoreInfoDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属省id
|
||||
*/
|
||||
private String mercProvId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属市id
|
||||
*/
|
||||
private String mercCityId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属区id
|
||||
*/
|
||||
private String mercAreaId;
|
||||
|
||||
/**
|
||||
* 商户归属省
|
||||
*/
|
||||
private String mercProv;
|
||||
|
||||
/**
|
||||
* 商户归属市
|
||||
*/
|
||||
private String mercCity;
|
||||
|
||||
/**
|
||||
* 商户归属区
|
||||
*/
|
||||
private String mercArea;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 营业地址
|
||||
*/
|
||||
private String businessAddress;
|
||||
|
||||
/**
|
||||
* 经营场所内设照片
|
||||
*/
|
||||
private ImageDto insidePic;
|
||||
|
||||
/**
|
||||
* 门头照
|
||||
*/
|
||||
private ImageDto doorPic;
|
||||
|
||||
/**
|
||||
* 收银台照片
|
||||
*/
|
||||
private ImageDto cashierDeskPic;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.czg.dto.resp;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 银行支行信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 15:37
|
||||
*/
|
||||
@Data
|
||||
public class BankBranchDto {
|
||||
/**
|
||||
* 机构ID
|
||||
*/
|
||||
private String instId;
|
||||
|
||||
/**
|
||||
* 银行代码
|
||||
*/
|
||||
private String bankCode;
|
||||
|
||||
/**
|
||||
* 城市
|
||||
*/
|
||||
private String city;
|
||||
|
||||
/**
|
||||
* 银行简称
|
||||
*/
|
||||
private String simpleName;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
@JSONField(name = "provice")
|
||||
private String province;
|
||||
|
||||
/**
|
||||
* IBPS代码
|
||||
*/
|
||||
private String ibpsCode;
|
||||
|
||||
/**
|
||||
* 承担机构
|
||||
*/
|
||||
private String undertakeInst;
|
||||
|
||||
/**
|
||||
* 分支机构名称
|
||||
*/
|
||||
private String branchName;
|
||||
|
||||
/**
|
||||
* 机构全称
|
||||
*/
|
||||
private String instName;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.czg.dto.resp;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 进件相应结果
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 18:15
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class EntryRespDto {
|
||||
|
||||
/**
|
||||
* 微信申请 Id
|
||||
*/
|
||||
private String wechatApplyId;
|
||||
|
||||
/**
|
||||
* 微信状态
|
||||
*/
|
||||
private String wechatStatus;
|
||||
|
||||
/**
|
||||
* 支付宝订单 Id
|
||||
*/
|
||||
private String alipayOrderId;
|
||||
|
||||
/**
|
||||
* 支付宝状态
|
||||
*/
|
||||
private String alipayStatus;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.czg.third.alipay;
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConfig;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.v3.ApiClient;
|
||||
import com.alipay.v3.Configuration;
|
||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 13:48
|
||||
*/
|
||||
@Slf4j
|
||||
public class AlipayClient {
|
||||
|
||||
public static DefaultAlipayClient getDefaultClient(AlipayConfigDto configDto) {
|
||||
try {
|
||||
return new DefaultAlipayClient(getAlipayConfig(configDto));
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("创建支付宝客户端失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ApiClient getApiClient(AlipayConfigDto configDto) {
|
||||
try {
|
||||
ApiClient defaultClient = Configuration.getDefaultApiClient();
|
||||
// 初始化alipay参数(全局设置一次)
|
||||
com.alipay.v3.util.model.AlipayConfig alipayConfig = new com.alipay.v3.util.model.AlipayConfig();
|
||||
alipayConfig.setServerUrl(configDto.getDomain());
|
||||
alipayConfig.setAppId(configDto.getAppId());
|
||||
alipayConfig.setAlipayPublicKey(configDto.getAlipayPublicKey());
|
||||
alipayConfig.setPrivateKey(configDto.getPrivateKey());
|
||||
defaultClient.setAlipayConfig(alipayConfig);
|
||||
return defaultClient;
|
||||
} catch (Exception e) {
|
||||
log.error("创建支付宝客户端失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static AlipayConfig getAlipayConfig(AlipayConfigDto configDto) {
|
||||
if (configDto == null) {
|
||||
configDto = AlipayConfigDto.getDefaultConfig();
|
||||
}
|
||||
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
alipayConfig.setServerUrl(configDto.getDomain());
|
||||
alipayConfig.setAppId(configDto.getAppId());
|
||||
alipayConfig.setPrivateKey(configDto.getPrivateKey());
|
||||
alipayConfig.setFormat("json");
|
||||
alipayConfig.setAlipayPublicKey(configDto.getAlipayPublicKey());
|
||||
alipayConfig.setCharset("UTF-8");
|
||||
alipayConfig.setSignType("RSA2");
|
||||
|
||||
return alipayConfig;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.czg.third.alipay;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayFinancialnetAuthPbcnameQueryModel;
|
||||
import com.alipay.api.request.AlipayFinancialnetAuthPbcnameQueryRequest;
|
||||
import com.alipay.api.response.AlipayFinancialnetAuthPbcnameQueryResponse;
|
||||
import com.alipay.v3.ApiClient;
|
||||
import com.alipay.v3.ApiException;
|
||||
import com.alipay.v3.Configuration;
|
||||
import com.alipay.v3.api.AlipayOpenAgentApi;
|
||||
import com.alipay.v3.api.AntMerchantExpandIndirectImageApi;
|
||||
import com.alipay.v3.model.*;
|
||||
import com.alipay.v3.util.model.AlipayConfig;
|
||||
import com.czg.dto.req.AggregateMerchantDto;
|
||||
import com.czg.dto.resp.BankBranchDto;
|
||||
import com.czg.dto.resp.EntryRespDto;
|
||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
||||
import com.czg.utils.UploadFileUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付宝进件管理
|
||||
*
|
||||
* <a href="https://opendocs.alipay.com/solution/9434dd99_ant.merchant.expand.indirect.zft.simplecreate?scene=bf5951260023430e944c2e9afdf7f9e2&pathHash=d3136936">...</a>
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/29 14:11
|
||||
*/
|
||||
@Slf4j
|
||||
public class AlipayEntryManager {
|
||||
|
||||
/**
|
||||
* 进件商户
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param reqDto 请求信息
|
||||
*/
|
||||
public static EntryRespDto entryMerchant(AlipayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
return new EntryRespDto();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param url 图片地址
|
||||
* @return 图片ID
|
||||
*/
|
||||
public static String uploadImage(AlipayConfigDto configDto, String url) {
|
||||
if (configDto == null) {
|
||||
configDto = AlipayConfigDto.getDefaultConfig();
|
||||
}
|
||||
try {
|
||||
byte[] bytes = UploadFileUtil.downloadImage(url);
|
||||
|
||||
Path tempFile = Files.createTempFile("image_", ".png");
|
||||
|
||||
// 写入数据
|
||||
Files.write(tempFile, bytes);
|
||||
|
||||
File file = tempFile.toFile();
|
||||
|
||||
AntMerchantExpandIndirectImageApi imageApi = new AntMerchantExpandIndirectImageApi();
|
||||
imageApi.setApiClient(AlipayClient.getApiClient(configDto));
|
||||
AntMerchantExpandIndirectImageUploadModel model = new AntMerchantExpandIndirectImageUploadModel();
|
||||
// 从 url 中获取图片 后缀
|
||||
model.setImageType(UploadFileUtil.extractImageExtension(url));
|
||||
AntMerchantExpandIndirectImageUploadResponseModel upload = imageApi.upload(model, file);
|
||||
return upload.getImageId();
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝上传图片报错,URL:{},错误信息:{}", "url", e.getMessage(), e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支行
|
||||
*
|
||||
* @param instId 顶级机构ID CMB
|
||||
* @param province 省份 陕西省
|
||||
* @param city 城市 西安市
|
||||
*/
|
||||
public static List<BankBranchDto> queryBankBranchList(String instId, String province, String city) {
|
||||
try {
|
||||
AlipayFinancialnetAuthPbcnameQueryRequest request = new AlipayFinancialnetAuthPbcnameQueryRequest();
|
||||
|
||||
AlipayFinancialnetAuthPbcnameQueryModel model = new AlipayFinancialnetAuthPbcnameQueryModel();
|
||||
model.setInstId(instId);
|
||||
model.setProvice(province);
|
||||
model.setCity(city);
|
||||
|
||||
request.setBizModel(model);
|
||||
DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(null);
|
||||
AlipayFinancialnetAuthPbcnameQueryResponse response = defaultAlipayClient.execute(request);
|
||||
|
||||
String data = response.getPbcQueryResult();
|
||||
return JSONArray.parseArray(data, BankBranchDto.class);
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝查询支行报错,错误信息:{}", e.getMessage(), e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
queryBankBranchList("CMB", "西安市", "陕西省");
|
||||
|
||||
}
|
||||
|
||||
// https://opendocs.alipay.com/solution/0dec7x?pathHash=caec4753 直付通
|
||||
public static void test() throws ApiException {
|
||||
ApiClient defaultClient = Configuration.getDefaultApiClient();
|
||||
// 初始化alipay参数(全局设置一次)
|
||||
AlipayConfig alipayConfig = new AlipayConfig();
|
||||
alipayConfig.setServerUrl("https://openapi.alipay.com");
|
||||
alipayConfig.setAppId("2021006121646825");
|
||||
alipayConfig.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB");
|
||||
alipayConfig.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz3FkdffxZibdwis9W7eOW1dEjGAbSvRDL2ikfeCIW5KZNoIjUqxI0mIoUlLRRKO71QLHZS1Vb2aJp8jeOAqIPa8e76HTneQEzk3FGA8gpraSGvbadHWzvxnmYKsts1TBiEZQL82ySJXhQTJvZ6jyDM7s6wHHUnrH+Qi29QpppQ1sxsoJeCtajUgRg3btD6XbBcyFAX3pzM56Kw9eaIjZoD8WToZOM/Y3sqNL2uo8lLqcIpTrI7Pq5ZOspmBQ+t8v3rS9IdDZZMvd0trzS67AXwHz8rKPBT/lL1A4iHnXCHUvktusX1fPs3/RGY/a7PIddaBLnfY0GcueE16K7QcrXAgMBAAECggEAbSdT2eckp75BWoaTcGEs1tRqeM7TDT/6moyKmnOQ1K3tE31SrSYpBUxxuC3LBNo/sw2RIZtrcTOyMnPyLTgB3DP/4lUf5X51MTTQ8LnI1ypvh+pIki9Sdm3QS33lOOZk149tdpdDk6ozyx/DEcvq74EMpoo2SuAIi5LkKVDrXuehvGA/WeXtpmuPgqRFdIA+JBlA3knHk5XEQY/k2Y31gq5oCwNL9iT9OAZqVkukE6EnvCXE9t2rAV4/snYilaf/UaO+ktgEwSbPBQ8YKlovDAarMBbGtgr6E174A9djlPyR+W/fgx8rlTwSWtieb9MkO8LN3KSxgVs0kY5U8OHg8QKBgQDljJq9kTFHare+W/fAXdUy3tJprfNQCAii6s+GuDfTQiviVQDtWmdtHAN+xU3to7MepvVhwHsqtQnZXKTtZuwwxn82FNl7A5RYD3GVFW+wG6AsGLIdESrWxySoL6Kx8QmNpMEVg8acT/ywzW/RnUXS5vU7GIi8GA0vtyBo24R9KQKBgQDIlf/R9+iNk9oXlbB/k4um9eVvBBS7l5cx4E5Id5Dpp4kGZfPZEa7oDsEUstZZM9mgQLJK/noNWbcf0+BohCR5ux7SC12qIoxwN3k4BzTDqrS8BzFuVVp5PELUsf/uCbRn05iMzpiDUhj3Vde04wvjHYIobfKlZO2HeSWXCpUH/wKBgQC8wSuU6ck90pEY5QMKmZ3wYK1g3PsQOirv3Gmde+nbu7PePsuuYQJfBAQTwCZeXJezgtKP+PjOm2Nn6vhrhpB9YxvD2s0ijET1TG23i5L1myHQYNZFdJJnXgXUjqcX7v5ODMYA7QTqEBPXRnbGRK7fx66rU3dMQ/LD46+wyaFeUQKBgA4QTk53dkuu6SSsLyLSwoDjTsHY5Gc+urAZjQORtoxbXcUgEtfOYJgOqMT9wP+iHgkZYCbX7tDO0IMfxOUvFqueTgvmFhwergAUM6CVCMMLTf689l9JBr3nVrw4+rvC3G5HLLP6rEDQ2cVFtIkPPj8fS4fwJYopKGpOOS9843QbAoGBAMoHH8LqoZ50FLsospx/hJe24Cd8wCgQTXSa/hMqNZ1999JDhftMt7R0ZdB1he2LReACe0K9ntBU4H4u225zZ3wZlyOfoyerAHuLK/ysNlgIIzblZlOxbBJ64Kul8leXzlYy3tOZuZ997KqBcWPCE3LUBBNvM6E3blJUnlmJAVoi");
|
||||
defaultClient.setAlipayConfig(alipayConfig);
|
||||
AlipayOpenAgentApi api = new AlipayOpenAgentApi();
|
||||
AlipayOpenAgentCreateModel data = new AlipayOpenAgentCreateModel();
|
||||
ContactModel contactInfo = new ContactModel();
|
||||
contactInfo.setContactEmail("zhangsan@alipy.com");
|
||||
contactInfo.setContactName("张三");
|
||||
contactInfo.setContactMobile("18866668888");
|
||||
data.setContactInfo(contactInfo);
|
||||
// data.setOrderTicket("00ee2d475f374ad097ee0f1ac223fX00");
|
||||
data.setAccount("1157756119@qq.com");
|
||||
try {
|
||||
AlipayOpenAgentCreateResponseModel response = api.create(data);
|
||||
System.out.println(response);
|
||||
} catch (ApiException e) {
|
||||
AlipayOpenAgentCreateDefaultResponse errorObject = (AlipayOpenAgentCreateDefaultResponse) e.getErrorObject();
|
||||
System.out.println("调用失败:" + errorObject);
|
||||
System.out.println("调用失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.czg.third.alipay;
|
||||
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConfig;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.AntMerchantExpandIndirectZftSimplecreateRequest;
|
||||
import com.alipay.api.response.AntMerchantExpandIndirectZftSimplecreateResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/5 13:46
|
||||
*/
|
||||
public class AlipayReqUtils {
|
||||
public static void main(String[] args) throws AlipayApiException {
|
||||
DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(null);
|
||||
|
||||
// 构造请求参数以调用接口
|
||||
AntMerchantExpandIndirectZftSimplecreateRequest request = new AntMerchantExpandIndirectZftSimplecreateRequest();
|
||||
AntMerchantExpandIndirectZftSimplecreateModel model = new AntMerchantExpandIndirectZftSimplecreateModel();
|
||||
|
||||
// 设置商户编号
|
||||
model.setExternalId("1052900599901941");
|
||||
|
||||
// 设置签约支付宝账户
|
||||
model.setBindingAlipayLogonId("18434286340");
|
||||
|
||||
// 设置商户别名
|
||||
model.setAliasName("一点点");
|
||||
|
||||
// 设置商户客服电话
|
||||
// model.setServicePhone("0571-85022088");
|
||||
|
||||
// 设置商户联系人信息
|
||||
ContactInfo contactInfos = new ContactInfo();
|
||||
contactInfos.setIdCardNo("142725199902176419");
|
||||
// contactInfos.setPhone("0571-85022088");
|
||||
contactInfos.setName("王伟");
|
||||
contactInfos.setMobile("18434286340");
|
||||
contactInfos.setEmail("18434286340");
|
||||
model.setContactInfos(contactInfos);
|
||||
|
||||
// 设置进件的二级商户名称
|
||||
model.setName("王伟");
|
||||
|
||||
// 设置默认结算规则
|
||||
DefaultSettleRule defaultSettleRule = new DefaultSettleRule();
|
||||
defaultSettleRule.setDefaultSettleType("alipayAccount");
|
||||
defaultSettleRule.setDefaultSettleTarget("18434286340");
|
||||
model.setDefaultSettleRule(defaultSettleRule);
|
||||
|
||||
// 设置结算支付宝账号
|
||||
model.setAlipayLogonId("18434286340");
|
||||
|
||||
// 设置结算银行卡信息
|
||||
SettleCardInfo bizCards = new SettleCardInfo();
|
||||
bizCards.setAccountInstName("招商银行");
|
||||
bizCards.setBankCode("103290003044");
|
||||
bizCards.setAccountType("DC");
|
||||
bizCards.setUsageType("01");
|
||||
bizCards.setAccountHolderName("王伟");
|
||||
bizCards.setAccountInstCity("杭州市");
|
||||
bizCards.setAccountInstId("CMB");
|
||||
bizCards.setAccountNo("6214831259609102");
|
||||
bizCards.setAccountBranchName("招商银行杭州高新支行");
|
||||
bizCards.setAccountInstProvince("浙江省");
|
||||
model.setBizCards(bizCards);
|
||||
|
||||
// 设置授权函
|
||||
model.setLicenseAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
|
||||
// 设置开票资料信息
|
||||
// MerchantInvoiceInfo invoiceInfo = new MerchantInvoiceInfo();
|
||||
// invoiceInfo.setMailTelephone("057162288888");
|
||||
// invoiceInfo.setTaxPayerQualification("01");
|
||||
// invoiceInfo.setAddress("浙江省杭州市西湖区西溪路蚂蚁金服");
|
||||
// invoiceInfo.setAcceptElectronic(false);
|
||||
// invoiceInfo.setTelephone("057162288888");
|
||||
// invoiceInfo.setTitle("蚂蚁金服(杭州)信息技术有限公司");
|
||||
// invoiceInfo.setMailName("张三");
|
||||
// invoiceInfo.setAutoInvoice(true);
|
||||
// invoiceInfo.setTaxPayerValid("19981011");
|
||||
// invoiceInfo.setTaxNo("51010482542598631219");
|
||||
// invoiceInfo.setBankName("中国银行");
|
||||
// AddressInfo mailAddress = new AddressInfo();
|
||||
// mailAddress.setAddress("万塘路18号黄龙时代广场B座");
|
||||
// mailAddress.setDistrictCode("371002");
|
||||
// mailAddress.setLatitude("60.270001");
|
||||
// mailAddress.setCityCode("371000");
|
||||
// mailAddress.setPoiid("B0FFIVU189");
|
||||
// mailAddress.setProvinceCode("370000");
|
||||
// mailAddress.setLongitude("120.760001");
|
||||
// invoiceInfo.setMailAddress(mailAddress);
|
||||
// invoiceInfo.setBankAccount("1234567812345678123");
|
||||
// model.setInvoiceInfo(invoiceInfo);
|
||||
|
||||
// 设置商户使用服务
|
||||
List<String> service = new ArrayList<String>();
|
||||
service.add("当面付");
|
||||
model.setService(service);
|
||||
|
||||
// 设置经营地址
|
||||
AddressInfo businessAddress = new AddressInfo();
|
||||
businessAddress.setAddress("万塘路18号黄龙时代广场B座");
|
||||
businessAddress.setDistrictCode("371002");
|
||||
businessAddress.setLatitude("60.270001");
|
||||
businessAddress.setCityCode("371000");
|
||||
businessAddress.setPoiid("B0FFIVU189");
|
||||
businessAddress.setProvinceCode("370000");
|
||||
businessAddress.setType("BUSINESS_ADDRESS");
|
||||
businessAddress.setLongitude("120.760001");
|
||||
model.setBusinessAddress(businessAddress);
|
||||
|
||||
// 设置门头照
|
||||
model.setOutDoorImages("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
|
||||
// 设置内景照
|
||||
model.setInDoorImages("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
|
||||
// 设置商户站点信息
|
||||
// SiteInfo sites = new SiteInfo();
|
||||
// sites.setIcpOrgName("支付宝(中国)网络技术有限公司");
|
||||
// sites.setSiteType("01");
|
||||
// sites.setSiteDomain("www.alipay.com");
|
||||
// sites.setScreenshotImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
// sites.setRemark("备注说明");
|
||||
// sites.setAuthLetterImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
// sites.setSiteName("XXX网站");
|
||||
// sites.setMarket("豌豆荚");
|
||||
// sites.setPassword("测试密码");
|
||||
// sites.setDownload("https://itunes.apple.com/cn/app/id333206289?mt=8");
|
||||
// sites.setTinyAppId("2021004105652035");
|
||||
// sites.setSiteUrl("https://open.alipay.com");
|
||||
// sites.setIcpServiceName("支付宝");
|
||||
// sites.setRemarkImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
// sites.setAccount("测试账号");
|
||||
// sites.setIcpNo("沪ICP备15027489号-2");
|
||||
// sites.setStatus("ONLINE");
|
||||
// model.setSites(sites);
|
||||
|
||||
// 设置商户类别码 mcc
|
||||
model.setMcc("B0007");
|
||||
|
||||
// 设置商户行业资质图片
|
||||
List<IndustryQualificationInfo> qualifications = new ArrayList<IndustryQualificationInfo>();
|
||||
IndustryQualificationInfo qualifications0 = new IndustryQualificationInfo();
|
||||
qualifications0.setIndustryQualificationImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
qualifications0.setIndustryQualificationType("323");
|
||||
qualifications.add(qualifications0);
|
||||
model.setQualifications(qualifications);
|
||||
|
||||
// 设置补充证件号
|
||||
model.setAdditionalCertNo("9133010608210550XR");
|
||||
|
||||
// 设置补充证件类型
|
||||
model.setAdditionalCertType("201");
|
||||
|
||||
// 设置补充证件图片
|
||||
model.setAdditionalCertImage("c6c0c7a1-b9d5-4e5d-b9d4-9eed39f00e65.jpg");
|
||||
|
||||
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
|
||||
// model.setInfoSourceUid("2088111122223333");
|
||||
|
||||
// 设置(平替原来的info_source_uid字段
|
||||
// model.setInfoSourceOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
|
||||
|
||||
// uid参数未来计划废弃,存量商户可继续使用,新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
|
||||
// model.setOverseaSettleAccount("2088111122223333");
|
||||
|
||||
// 设置(平替原来的oversea_settle_open_id字段
|
||||
// model.setOverseaSettleOpenId("074a1CcTG1LelxKe4xQC0zgNdId0nxi95b5lsNpazWYoCo5");
|
||||
|
||||
// 设置二级商户与服务商的签约时间
|
||||
model.setSignTimeWithIsv("2015-04-15");
|
||||
|
||||
// 设置代扣产品信息
|
||||
ZFTWithholdingInfo zftWithholdingInfo = new ZFTWithholdingInfo();
|
||||
zftWithholdingInfo.setWithholdingServiceFeatureName("GENERAL_WITHHOLDING_P");
|
||||
zftWithholdingInfo.setSignScene("DEFAULT");
|
||||
model.setZftWithholdingInfo(zftWithholdingInfo);
|
||||
|
||||
// 设置交易场景
|
||||
List<String> tradeScene = new ArrayList<String>();
|
||||
tradeScene.add("TINY_APP");
|
||||
model.setTradeScene(tradeScene);
|
||||
|
||||
request.setBizModel(model);
|
||||
// 第三方代调用模式下请设置app_auth_token
|
||||
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
|
||||
|
||||
AntMerchantExpandIndirectZftSimplecreateResponse response = defaultAlipayClient.execute(request);
|
||||
System.out.println(response.getBody());
|
||||
|
||||
if (response.isSuccess()) {
|
||||
System.out.println("调用成功");
|
||||
} else {
|
||||
System.out.println("调用失败");
|
||||
// sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
|
||||
// String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
|
||||
// System.out.println(diagnosisUrl);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.czg.third.alipay.dto.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 13:49
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AlipayConfigDto {
|
||||
|
||||
/**
|
||||
* 支付宝 AppId
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 商户私钥
|
||||
*/
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* 支付宝公钥
|
||||
*/
|
||||
private String alipayPublicKey;
|
||||
|
||||
/**
|
||||
* 支付宝支付域名
|
||||
* <a href="https://openapi.alipay.com/gateway.do"></a>
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
public static AlipayConfigDto getDefaultConfig() {
|
||||
return new AlipayConfigDto()
|
||||
.setAppId("2021004174605036")
|
||||
.setPrivateKey("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==")
|
||||
.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
||||
.setDomain("https://openapi.alipay.com/gateway.do");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 经营地址
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:20
|
||||
*/
|
||||
@Data
|
||||
public class AlipayAddressReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 城市编码
|
||||
* 蚂蚁店铺请按照蚂蚁店铺地区码 表格中填写。
|
||||
* 直付通商户请按照直付通商户地区码 表格中内容填写。
|
||||
*/
|
||||
@JSONField(name = "city_code")
|
||||
private String cityCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 区县编码
|
||||
*/
|
||||
@JSONField(name = "district_code")
|
||||
private String districtCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 详细地址
|
||||
*/
|
||||
@JSONField(name = "address")
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 省份编码
|
||||
*/
|
||||
@JSONField(name = "province_code")
|
||||
private String provinceCode;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 结算银行卡信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:14
|
||||
*/
|
||||
@Data
|
||||
public class AlipayBizCardsReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户支行名
|
||||
*/
|
||||
@JSONField(name = "account_branch_name")
|
||||
private String accountBranchName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 卡户名
|
||||
*/
|
||||
@JSONField(name = "account_holder_name")
|
||||
private String accountHolderName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户行所在地-省
|
||||
*/
|
||||
@JSONField(name = "account_inst_province")
|
||||
private String accountInstProvince;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户行所在地-市
|
||||
*/
|
||||
@JSONField(name = "account_inst_city")
|
||||
private String accountInstCity;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户行简称缩写
|
||||
*/
|
||||
@JSONField(name = "account_inst_id")
|
||||
private String accountInstId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 银行名称
|
||||
*/
|
||||
@JSONField(name = "account_inst_name")
|
||||
private String accountInstName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 银行卡号
|
||||
*/
|
||||
@JSONField(name = "account_no")
|
||||
private String accountNo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 银行卡类型
|
||||
* 【枚举值】
|
||||
* 借记卡: DC
|
||||
* 信用卡: CC
|
||||
*/
|
||||
@JSONField(name = "account_type")
|
||||
private String accountType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 账号使用类型
|
||||
* 【枚举值】
|
||||
* 对公: 01
|
||||
* 对私: 02
|
||||
*/
|
||||
@JSONField(name = "usage_type")
|
||||
private String usageType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 联行号
|
||||
*/
|
||||
@JSONField(name = "bank_code")
|
||||
private String bankCode;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商户联系人信息
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:02
|
||||
*/
|
||||
@Data
|
||||
public class AlipayContactInfoReqDto {
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系人名字
|
||||
*/
|
||||
@JSONField(name = "name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* email | mobile | phone 三选一
|
||||
* 电子邮箱
|
||||
*/
|
||||
@JSONField(name = "email")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* email | mobile | phone 三选一
|
||||
* 手机号码
|
||||
*/
|
||||
@JSONField(name = "mobile")
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* email | mobile | phone 三选一
|
||||
* 电话
|
||||
*/
|
||||
@JSONField(name = "phone")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证号
|
||||
*/
|
||||
@JSONField(name = "id_card_no")
|
||||
private String idCardNo;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 平台商提交二级商户资料进行进件,完成二级商户入驻
|
||||
* <a href="https://opendocs.alipay.com/solution/9434dd99_ant.merchant.expand.indirect.zft.simplecreate?scene=bf5951260023430e944c2e9afdf7f9e2&pathHash=d3136936">...</a>
|
||||
* @author yjjie
|
||||
* @date 2025/12/29 14:19
|
||||
*/
|
||||
@Data
|
||||
public class AlipayEntryReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户编号,由一级商户定义,保证在一级商户下唯一即可
|
||||
*/
|
||||
@JSONField(name = "external_id")
|
||||
private String externalId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户别名。支付宝收银台及账单中的商户名称会展示此处设置的别名。如果涉及支付宝APP内的支付,支付结果页也会展示该别名;如果涉及线下当面付场景,请填写线下店铺名称
|
||||
*/
|
||||
@JSONField(name = "alias_name")
|
||||
private String aliasName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户联系人信息。在本业务中,ContactInfo对象中联系人姓名、手机号必填,其他选填
|
||||
*/
|
||||
@JSONField(name = "contact_infos")
|
||||
private AlipayContactInfoReqDto contactInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 默认结算规则。当调用收单接口,settle_info中设置默认结算规则(defaultSettle)时,交易资金将结算至此处设置的默认结算目标账户中。其详细描述及收单接口传参示例参考功能包文档
|
||||
*/
|
||||
@JSONField(name = "default_settle_rule")
|
||||
private AlipaySettleRuleReqDto defaultSettleRule;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户使用服务
|
||||
* 可选值有:当面付、jsapi支付、app支付、wap支付、电脑支付、预授权支付、商户代扣、小程序支付、订单码支付。其值会影响其他字段必填性,详见其他字段描述
|
||||
* 当面付: 当面付
|
||||
* jsapi支付: jsapi支付
|
||||
* app支付: app支付
|
||||
* wap支付: wap支付
|
||||
* 电脑支付: 电脑支付
|
||||
* 预授权支付: 预授权支付
|
||||
* 商户代扣: 商户代扣
|
||||
* 小程序支付: 小程序支付
|
||||
* 订单码支付: 订单码支付
|
||||
*/
|
||||
@JSONField(name = "service")
|
||||
private List<String> service;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户证件编号
|
||||
* 按商户类型merchant_type的说明提供对应的证件编号
|
||||
*/
|
||||
@JSONField(name = "cert_no")
|
||||
private String certNo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户类别码 mcc
|
||||
* <a href="https://mdn.alipayobjects.com/huamei_fctrxv/afts/file/A*3TMHRZ8ppa4AAAAAAAAAAAAADs2DAQ/%E8%BF%9B%E4%BB%B6MCC%E4%B8%8E%E8%B5%84%E8%B4%A8%E8%A6%81%E6%B1%82202212.xlsx">...</a>
|
||||
* 可查看 进件MCC与资质要求 202212.xlsx,特殊行业要按照MCC说明中的资质一栏上传辅助资质,辅助资质要在 qualifications 中上传,会有人工审核。
|
||||
* 【示例值】B0007
|
||||
*/
|
||||
@JSONField(name = "mcc")
|
||||
private String mcc;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 结算支付宝账号
|
||||
* 结算账号使用支付宝账号时必填,本字段指定交易资金结算的具体支付宝账号,与binding_alipay_logon_id同主体的支付宝账号即可
|
||||
*/
|
||||
@JSONField(name = "alipay_logon_id")
|
||||
private String alipayLogonId;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法人名称
|
||||
* 非个人商户类型必填
|
||||
*/
|
||||
@JSONField(name = "legal_name")
|
||||
private String legalName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法人证件编号
|
||||
* 法人证件编号,非个人商户类型必填
|
||||
*/
|
||||
@JSONField(name = "legal_cert_no")
|
||||
private String legalCertNo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户证件图
|
||||
* 目前只有当商户类型是个人商户且使用当面付服务时才需填写
|
||||
*/
|
||||
@JSONField(name = "cert_image_back")
|
||||
private String certImageBack;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户证件图片
|
||||
* 本业务接口中,如果是特殊行业必填;使用当面付服务时,非个人必填,个人结算到卡时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。
|
||||
*/
|
||||
@JSONField(name = "cert_image")
|
||||
private String certImage;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 进件的二级商户名称
|
||||
* 一般情况下要与证件的名称相同。个体工商户类型可以放宽到法人名称
|
||||
*/
|
||||
@JSONField(name = "name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法人证件类型
|
||||
* 默认可不填,认为legal_cert_no是大陆身份证。类型包括:100 大陆身份证;105 港澳居民往来内地通行证;106 台湾同胞往来大陆通行证;108 外国人居留证
|
||||
* 【枚举值】
|
||||
* 大陆身份证: 100
|
||||
* 港澳居民往来内地通行证: 105
|
||||
* 台湾同胞往来大陆通行证: 106
|
||||
* 外国人居留证: 108
|
||||
*/
|
||||
@JSONField(name = "legal_cert_type")
|
||||
private String legalCertType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户类型
|
||||
* 01:企业;cert_type填写201(营业执照);cert_no填写营业执照号;
|
||||
* 02:事业单位:cert_type填写218(事业单位法人证书);cert_no填写事业单位法人证书编号;
|
||||
* 03:民办非企业组织:cert_type填写204(民办非企业登记证书);cert_no填写民办非企业登记证书编号;
|
||||
* 04:社会团体:cert_type填写206(社会团体法人登记证书);cert_no填写社会团体法人登记证书编号;
|
||||
* 05:党政及国家机关:cert_type填写219(党政机关批准设立文件/行政执法主体资格证);cert_no填写党政机关批准设立文件/行政执法主体资格证编号;
|
||||
* 06:个人商户:cert_type填写100(个人身份证);cert_no填写个人身份证号码;
|
||||
* 07:个体工商户:cert_type填写201(营业执照);cert_no填写营业执照编号;
|
||||
*/
|
||||
@JSONField(name = "merchant_type")
|
||||
private String merchantType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户证件类型
|
||||
* 按商户类型merchant_type的说明提供对应的证件类型。
|
||||
* 营业执照: 201
|
||||
* 事业单位法人证书: 218
|
||||
* 民办非企业登记证书: 204
|
||||
* 社会团体法人登记证书: 206
|
||||
* 党政机关批准设立文件/行政执法主体资格证: 219
|
||||
* 个人身份证: 100
|
||||
*/
|
||||
@JSONField(name = "cert_type")
|
||||
private String certType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件名称
|
||||
* 目前只有个体工商户商户类型要求填入本字段,填写值为个体工商户营业执照上的名称
|
||||
*/
|
||||
@JSONField(name = "cert_name")
|
||||
private String certName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 结算银行卡信息
|
||||
* 结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
|
||||
* 【必选条件】结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
|
||||
*/
|
||||
@JSONField(name = "biz_cards")
|
||||
private AlipayBizCardsReqDto bizCards;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 经营地址
|
||||
* 使用当面付服务时必填。地址对象中省、市、区、地址必填,其余选填
|
||||
*/
|
||||
@JSONField(name = "business_address")
|
||||
private AlipayAddressReqDto businessAddress;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 门头照
|
||||
* 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
|
||||
*/
|
||||
@JSONField(name = "out_door_images")
|
||||
private String outDoorImages;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 内景照
|
||||
* 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
|
||||
*/
|
||||
@JSONField(name = "in_door_images")
|
||||
private String inDoorImages;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 授权函
|
||||
* <a href="https://opendocs.alipay.com/open/direct-payment/cg5mkp#%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99">《说明函》模板参考</a>
|
||||
* 当商户名与结算卡户名不一致。《说明函》模板参考。涉及外籍法人(这种情况上传任意能证明身份的图片)时必填,
|
||||
* 其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。(商户类型为个体工商户时,本字段仅需上传营业执照非授权函)
|
||||
*/
|
||||
@JSONField(name = "license_auth_letter_image")
|
||||
private String licenseAuthLetterImage;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户站点信息
|
||||
* 包括网站、app、小程序。商户使用服务包含电脑支付、wap支付时,必须填充一个类型为01(网站)的SiteInfo对象,site_type/site_url/site_name必填;
|
||||
* 当包含app支付时,必须至少填充类型为02(APP)或06(支付宝小程序)中一种类型的SiteInfo对象,site_type/site_name必填;当包含jsapi支付时,必须填充一个类型为06(支付宝小程序)的SiteInfo对象;
|
||||
*/
|
||||
@JSONField(name = "sites")
|
||||
private AlipaySitesReqDto sites;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商户行业资质图片
|
||||
* 当商户的经营类目选择了特殊行业时该字段必填,需要特殊行业资质文件。每项行业资质信息中,industry_qualification_type和industry_qualification_image均必填。
|
||||
*/
|
||||
@JSONField(name = "qualifications")
|
||||
private List<AlipayQualificationsReqDto> qualifications;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 交易场景
|
||||
* 【枚举值】
|
||||
* 小程序支付场景: TINY_APP
|
||||
* H5场景: WAP
|
||||
* 线下当面付场景: OFFLINE
|
||||
* APP支付场景: APP
|
||||
* 网站支付场景: PC
|
||||
*/
|
||||
@JSONField(name = "trade_scene")
|
||||
private List<String> tradeScene;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 图片上传
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 13:46
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AlipayImageUploadReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 图片格式
|
||||
* 支持格式:bmp、jpg、jpeg、png、gif.
|
||||
*/
|
||||
@JSONField(name = "image_type")
|
||||
private String imageType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 图片二进制字节流
|
||||
* 最大为10M
|
||||
*/
|
||||
@JSONField(name = "image_content")
|
||||
private byte[] imageContent;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商户行业资质
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:40
|
||||
*/
|
||||
@Data
|
||||
public class AlipayQualificationsReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户行业资质类型 具体选值参见 <a href="https://gw.alipayobjects.com/os/bmw-prod/7aa3a36b-2bc2-4d57-815f-08edd55ef67e.xlsx">文档</a>
|
||||
* 【枚举值】
|
||||
* 金融许可证: 323
|
||||
* 【示例值】323
|
||||
*/
|
||||
@JSONField(name = "industry_qualification_type")
|
||||
private String industryQualificationType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户行业资质图片
|
||||
*/
|
||||
@JSONField(name = "industry_qualification_image")
|
||||
private String industryQualificationImage;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 结算规则
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:06
|
||||
*/
|
||||
@Data
|
||||
public class AlipaySettleRuleReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 默认结算类型
|
||||
* 可选值有bankCard/alipayAccount。bankCard表示结算到银行卡;alipayAccount表示结算到支付宝账号
|
||||
*/
|
||||
@JSONField(name = "default_settle_type")
|
||||
private String defaultSettleType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 默认结算目标
|
||||
* 当默认结算类型为bankCard时填写银行卡卡号,其值需在进件填写的结算银行卡范围内;当默认结算类型为alipayAccount时填写支付宝账号登录号,其值需在进件填写的结算支付宝账号范围内。
|
||||
*/
|
||||
@JSONField(name = "default_settle_target")
|
||||
private String defaultSettleTarget;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.czg.third.alipay.dto.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 11:31
|
||||
*/
|
||||
@Data
|
||||
public class AlipaySitesReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 网站类型
|
||||
* 【枚举值】
|
||||
* 网站: 01
|
||||
* APP: 02
|
||||
* 服务窗: 03
|
||||
* 公众号: 04
|
||||
* 其他: 05
|
||||
* 支付宝小程序: 06
|
||||
* 手机网站/H5: 07
|
||||
*/
|
||||
@JSONField(name = "site_type")
|
||||
private String siteType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 站点地址
|
||||
* 当传入service,且包含jsapi支付时,sites的site_type=06, site_url必填
|
||||
*/
|
||||
@JSONField(name = "site_url")
|
||||
private String siteUrl;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 站点名称
|
||||
* 当传入service,且包含jsapi支付、小程序支付时,sites的site_type=06, site_name必填
|
||||
*/
|
||||
@JSONField(name = "site_name")
|
||||
private String siteName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 截图照片
|
||||
* 当传入交易场景trade_scene,且当传入trade_scene=WAP、trade_scene=APP、trade_scene=PC时该参数必传
|
||||
*/
|
||||
@JSONField(name = "screenshot_image")
|
||||
private String screenshotImage;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 小程序appId
|
||||
* 当传入service,且包含jsapi支付时,sites的site_type=06, tiny_app_id必填。
|
||||
*/
|
||||
@JSONField(name = "tiny_app_id")
|
||||
private String tinyAppId;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 测试账号
|
||||
*/
|
||||
@JSONField(name = "account")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 测试账号密码
|
||||
*/
|
||||
@JSONField(name = "password")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 上架状态
|
||||
* 【枚举值】
|
||||
* 已上线: ONLINE
|
||||
* 已上线-内部: ONLINE_INNER
|
||||
* 未上线: OFFLINE
|
||||
*/
|
||||
@JSONField(name = "status")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 授权函照片
|
||||
*/
|
||||
@JSONField(name = "auth_letter_image")
|
||||
private String authLetterImage;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 备注说明
|
||||
*/
|
||||
@JSONField(name = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 备注说明图片
|
||||
*/
|
||||
@JSONField(name = "remark_image")
|
||||
private String remarkImage;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 网站域名
|
||||
*/
|
||||
@JSONField(name = "site_domain")
|
||||
private String siteDomain;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* ICP备案主体信息服务名称
|
||||
*/
|
||||
@JSONField(name = "icp_service_name")
|
||||
private String icpServiceName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* ICP备案/许可证号
|
||||
*/
|
||||
@JSONField(name = "icp_no")
|
||||
private String icpNo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* ICP备案主体主办单位名称
|
||||
*/
|
||||
@JSONField(name = "icp_org_name")
|
||||
private String icpOrgName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 下载地址
|
||||
*/
|
||||
@JSONField(name = "download")
|
||||
private String download;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 应用市场
|
||||
* 【示例值】豌豆荚
|
||||
*/
|
||||
@JSONField(name = "market")
|
||||
private String market;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAPublicKeyConfig;
|
||||
import com.wechat.pay.java.service.file.FileUploadService;
|
||||
|
||||
/**
|
||||
* 微信支付 配置
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 09:33
|
||||
*/
|
||||
public class WechatConfig {
|
||||
|
||||
/**
|
||||
* 获取微信支付配置
|
||||
* @param dto 微信支付配置
|
||||
* @return 微信支付配置
|
||||
*/
|
||||
public static Config getRsaConfig(WechatPayConfigDto dto) {
|
||||
if (dto == null) {
|
||||
dto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
return new RSAPublicKeyConfig.Builder()
|
||||
.merchantId(dto.getMerchantId())
|
||||
.privateKey(dto.getPrivateKey())
|
||||
.publicKey(dto.getPublicKey())
|
||||
.publicKeyId(dto.getPublicKeyId())
|
||||
.merchantSerialNumber(dto.getSerialNumber())
|
||||
.apiV3Key(dto.getApiV3Key())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static FileUploadService getFileUploadServiceByConfig(Config config) {
|
||||
return new FileUploadService.Builder()
|
||||
.config(config)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件上传服务
|
||||
* @param dto 微信支付配置
|
||||
* @return 文件上传服务
|
||||
*/
|
||||
public static FileUploadService getFileUploadService(WechatPayConfigDto dto) {
|
||||
return getFileUploadServiceByConfig(getRsaConfig(dto));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 微信支付加解密
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 10:58
|
||||
*/
|
||||
@Slf4j
|
||||
public class WechatEncrypt {
|
||||
|
||||
public static String rsaEncryptOaep(String message, PublicKey publicKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] data = message.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] cipherData = cipher.doFinal(data);
|
||||
return Base64.getEncoder().encodeToString(cipherData);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
log.error("当前Java环境不支持RSA v1.5/OAEP");
|
||||
} catch (InvalidKeyException e) {
|
||||
log.error("无效的证书");
|
||||
} catch (IllegalBlockSizeException | BadPaddingException e) {
|
||||
log.error("加密原串的长度不能超过214字节");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String getFileBytesSha256(byte[] input) throws NoSuchAlgorithmException {
|
||||
return bytesToHex(calculateSha256(input));
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心方法:计算字节数组的 SHA-256 哈希值
|
||||
* @param input 待计算的字节数组
|
||||
* @return SHA-256 哈希值(32 字节的字节数组)
|
||||
*/
|
||||
private static byte[] calculateSha256(byte[] input) throws NoSuchAlgorithmException {
|
||||
// 获取 SHA-256 消息摘要实例(Java 21 完全兼容)
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
// 计算哈希值
|
||||
return digest.digest(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助方法:将字节数组转换为十六进制字符串(SHA-256 结果常用格式)
|
||||
* @param bytes 待转换的字节数组
|
||||
* @return 十六进制字符串(SHA-256 对应 64 位字符串)
|
||||
*/
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
// Java 21 可使用 var 简化声明
|
||||
for (var b : bytes) {
|
||||
// 将字节转换为两位十六进制数,不足补 0
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.czg.dto.req.AggregateMerchantDto;
|
||||
import com.czg.dto.resp.EntryRespDto;
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.czg.third.wechat.dto.req.entry.WechatEntryReqDto;
|
||||
import com.czg.utils.UploadFileUtil;
|
||||
import com.wechat.pay.java.service.file.FileUploadService;
|
||||
import com.wechat.pay.java.service.file.model.FileUploadResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信支付进件 管理
|
||||
* 参考地址 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012719997">...</a>
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 10:57
|
||||
*/
|
||||
@Slf4j
|
||||
public class WechatEntryManager {
|
||||
|
||||
/**
|
||||
* 进件商户
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param reqDto 请求信息
|
||||
*/
|
||||
public static EntryRespDto entryMerchant(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
return new EntryRespDto();
|
||||
}
|
||||
|
||||
public static JSONObject queryBankList(WechatPayConfigDto configDto, Integer offset, Integer limit) {
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/banks/corporate-banking", Map.of("offset", offset, "limit", limit));
|
||||
log.info("查询银行列表:{}", resp);
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
public static JSONObject queryBankBranchList(WechatPayConfigDto configDto, String bankAliceCode, String cityCode, Integer offset, Integer limit) {
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/banks/" + bankAliceCode + "/branches", Map.of("city_code", cityCode, "offset", offset, "limit", limit));
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
public static JSONObject queryProvinceList(WechatPayConfigDto configDto) {
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/areas/provinces", Map.of());
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
public static JSONObject queryCityList(WechatPayConfigDto configDto, String provinceCode) {
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/areas/provinces/" + provinceCode + "/cities", Map.of());
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户进件
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param reqDto 请求参数
|
||||
*/
|
||||
public static void entryMerchant(WechatPayConfigDto configDto, WechatEntryReqDto reqDto) {
|
||||
String params = JSONObject.toJSONString(reqDto, JSONWriter.Feature.IgnoreEmpty);
|
||||
|
||||
// String string = WechatReqUtils.encryptReqParam(configDto, "/v3/applyment4sub/applyment/", params);
|
||||
|
||||
WechatReqUtils.postReq(configDto, "/v3/applyment4sub/applyment/", params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @param url 图片URL
|
||||
* @return 图片ID
|
||||
*/
|
||||
public static String uploadImage(WechatPayConfigDto configDto, String url) {
|
||||
if (configDto == null) {
|
||||
configDto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
// 校验入参
|
||||
if (url == null || url.trim().isEmpty()) {
|
||||
log.error("上传图片失败:URL参数为空");
|
||||
return "";
|
||||
}
|
||||
|
||||
FileUploadService service = WechatConfig.getFileUploadService(configDto);
|
||||
|
||||
try {
|
||||
// 获取图片字节数组
|
||||
byte[] bytes = UploadFileUtil.downloadImage(url);
|
||||
if (bytes.length == 0) {
|
||||
log.error("下载的图片内容为空,URL:{}", url);
|
||||
return "";
|
||||
}
|
||||
|
||||
// 2. 计算SHA256
|
||||
String sha256Hex = WechatEncrypt.getFileBytesSha256(bytes);
|
||||
|
||||
// 3. 构造元数据(从URL提取文件名,或自定义)
|
||||
JSONObject meta = new JSONObject();
|
||||
meta.put("sha256", sha256Hex);
|
||||
// 从URL提取文件名,若提取失败则使用默认名
|
||||
String fileName = UploadFileUtil.extractFileNameFromUrl(url);
|
||||
meta.put("filename", fileName);
|
||||
|
||||
// 4. 上传图片到微信接口
|
||||
FileUploadResponse uploadResponse = service.uploadImage(
|
||||
configDto.getDomain() + "/v3/merchant/media/upload",
|
||||
meta.toJSONString(),
|
||||
fileName,
|
||||
bytes
|
||||
);
|
||||
|
||||
return uploadResponse.getMediaId();
|
||||
} catch (Exception e) {
|
||||
log.error("微信上传图片报错,URL:{},错误信息:{}", url, e.getMessage(), e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
WechatPayConfigDto dto = new WechatPayConfigDto()
|
||||
.setMerchantId("1643779408")
|
||||
.setApiV3Key("a92baac5eb7a36ed8ec198113e769a03")
|
||||
.setSerialNumber("4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4")
|
||||
.setPublicKey("""
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbeWXEEjBaYtw2OyM+SC
|
||||
aCEMbryRXi4duKxx3vYG4rUVix+d5/Jz7Khev4Upml9zC+Xxvv/G9bHWAUyolzqD
|
||||
wefahGurIxr43r4GJVnQ4i5G6BbBVw5d4Vuz0y/9Zd14zmc/EmBpT0Ml26H7tOZl
|
||||
n1LSbQ4xNFkrRKrNEcExBLxkCd+K5K2TREZznywIi0izbHImvuzM8IneuR51FiqK
|
||||
pdFnAjTwb126EIj6ECkL6KLCl8RWqpfiX8SFiolSQLs1/w79O0sIUk96X2zWpnoW
|
||||
rTDFatPif/VEKl3y2dTlxxDxoZtVi48yTDW00OMzVl5D67oX3FVK0KsjHJSCfGlZ
|
||||
6wIDAQAB
|
||||
-----END PUBLIC KEY-----""")
|
||||
.setPrivateKey("""
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDqnAZhTxT572fo
|
||||
6wvSr8Rt0vRXg+EFKC6UvUiNE24oocQU5fjedX9KL/+fmoqay/xqIxvxvCNFTs4J
|
||||
zlMqavSl6bMWCpjvf/Ry82JmN1v2kJEO4lgP8BsEiqlUpObCH8BMAVUOn1j+9q4Q
|
||||
uZJJcbtRvec2fNweDM8EJp4B7RlUdDbHm86lfcDVp8iini7VjDp6D7aHT+C8A8OT
|
||||
ugxQIquDec778wVd9r2Sv3+t6rAzFs+n+Zu++2xtFEPhO5N0wjrLHaukl+9crU+1
|
||||
lktjDzcPd07SwGZ+A+3BTmW3UCramI3506e/3MWBECB7ge+gM4URAV0nJJCLH/Im
|
||||
WgEvPMr5AgMBAAECggEBAKv+wraoMWqiVv1tA/froAgbtcJLDranJK8qrXuvmPz0
|
||||
yzm+91qvrSgIVFEADUk67swo/R2Vng37nhWWS2Y3jy/rSr2H+2Lp3Z5ATA0/3I3A
|
||||
onfU/FaC4mvL9CP32KzMdj/CYkccDzSsSCQ+x75MQNXGcTGDDCSDo2kZnpEu73j3
|
||||
aqvO1jbqTGWigRfjOIaIhStjQIT8nEm/3mJ4f5dM9M6FMz33mhax8EahSgvdahYB
|
||||
t45iaGOWw81OJhmry47EvpwjXBl7jtO2HX3LiLbq5Ebcwu1zqDz5NM7ttnnGAqWC
|
||||
6y7JN5Vt4wPYrCydiUDe7dj0looffr2yw6MkNfYjLGECgYEA+FAvbEInQEi9YguS
|
||||
CQtLHngqvYeai66tvyykog9o38KHnPGx2Myf+rn/Hcp7KNRfjd5G34CCNg7KLnrx
|
||||
YIYh6+2bY3jirzdYUxuNKGbvM4gky/6M/P9zHF/uALKOE02yArdqemf4UxUvrYCc
|
||||
JdXsAMqvbpdvW1aGgNRB32YCkG0CgYEA8d89vawsCjNCEUh0VWTMoBLFoex3qBMZ
|
||||
rfzYQeBo6bDCRlAlUVzl+ouBUxSYxP/U8rzeNaRzGUwRLmlGMjyIr58FBlHsg2cR
|
||||
DlsX3HVCUjpS6sgPXOqakdiLfhMcHZAspislSyVfeS3TbUWiA45+5PuNUq+EZYwl
|
||||
ESsB1+yfRT0CgYEA0Ct49ksnWM8iZbXJgeeD3FFlk2rBd2TDqEem5W4Bv8T3p+0/
|
||||
6b7yR2HyrGj5gys3yFmWFP1JLESN3xWWkhMhEQcrg+LuN3Iwi8vHNR3GXu892f7W
|
||||
96q4OAt8Hf2S+j/igkB99YyANDbIt63gOh/zMF67X/14j5wkOpC3gK+maqkCgYEA
|
||||
s7nIrPoUt3ejLiiCmTmPe5q3VDzcJP4cZNau8zSHgK6hjZHcSPsYwPWMoWl6o1fe
|
||||
qoiBLacHB9MoKS58xLOKdcVZ/Ho/ntylJd+2eVCAeY1xM5h5IfgJ5znbXVFh4O3S
|
||||
357L1Wzt5qOQqW/GlZH65LevKbPWU4axvHISqpnfN5kCgYEAqiqLuAPu84VSsqsE
|
||||
GFh25t+1f0JY1sNfilE3/t9AdQeeCFv/5z9KB1kMt3a5ZFeVonsFIvCyaOJjhSkj
|
||||
4HCB94vWS7NuN5G9r874lMaPbZYQGwrcVaf265tN7cYYr3gUx1qB6+u+fh/kcft1
|
||||
BBmTzhb0zp5k8ngwAkA1g/LK204=
|
||||
-----END PRIVATE KEY-----""")
|
||||
.setPublicKeyId("PUB_KEY_ID_0116437794082025111000382377001000")
|
||||
.setDomain("https://api.mch.weixin.qq.com");
|
||||
|
||||
int offset = 0;
|
||||
Integer limit = 100;
|
||||
// JSONObject resp = queryBankList(dto, offset, limit);
|
||||
|
||||
// queryBankBranchList(dto, "1000009561", "110000", offset, limit);
|
||||
queryBankBranchList(dto, "1000009561", "29", offset, limit);
|
||||
|
||||
// queryProvinceList(dto);
|
||||
// queryCityList(dto, "28");
|
||||
|
||||
|
||||
// String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
|
||||
// log.info("图片上传成功:{}", string);
|
||||
|
||||
// Config config = WechatConfig.getRsaConfig(dto);
|
||||
// PrivacyEncryptor encryptor = config.createEncryptor();
|
||||
//
|
||||
// WechatEntryReqDto reqDto = new WechatEntryReqDto()
|
||||
// .setBusinessCode("MER_20231025110010000010000000000001");
|
||||
//
|
||||
// WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto()
|
||||
// .setContactType("LEGAL")
|
||||
// .setContactName(encryptor.encrypt("张三"))
|
||||
// .setContactIdType("IDCARD")
|
||||
// .setContactIdNumber(encryptor.encrypt("110101199001011234"))
|
||||
// .setContactIdDocCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
|
||||
// .setContactIdDocCopyBack("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
|
||||
// .setContactPeriodBegin("2023-10-25")
|
||||
// .setContactPeriodEnd("2024-10-25")
|
||||
// .setMobilePhone(encryptor.encrypt("13888888888"))
|
||||
// .setContactEmail(encryptor.encrypt("123456@qq.com"));
|
||||
//
|
||||
// reqDto.setContactInfo(contactInfo);
|
||||
//
|
||||
// WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto()
|
||||
// .setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
|
||||
//
|
||||
// WechatEntryLicenseReqDto licenseInfo = new WechatEntryLicenseReqDto()
|
||||
// .setLicenseCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
|
||||
// .setLicenseNumber("110101199001011234")
|
||||
// .setMerchantName("张三商行")
|
||||
// .setLegalPerson(encryptor.encrypt("张三"))
|
||||
// .setLicenseAddress("北京")
|
||||
// .setPeriodBegin("2023-10-25")
|
||||
// .setPeriodEnd("2024-10-25");
|
||||
// subjectInfo.setBusinessLicenseInfo(licenseInfo);
|
||||
//
|
||||
// WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto()
|
||||
// .setIdHolderType("LEGAL");
|
||||
// subjectInfo.setIdentityInfo(identityInfo);
|
||||
//
|
||||
// reqDto.setSubjectInfo(subjectInfo);
|
||||
//
|
||||
// WechatEntryBusinessReqDto businessInfo = new WechatEntryBusinessReqDto()
|
||||
// .setMerchantShortname("张三商行")
|
||||
// .setServicePhone("13888888888");
|
||||
// WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto()
|
||||
// .setSalesScenesType(List.of("SALES_SCENES_STORE"));
|
||||
// WechatEntryStoreInfoReqDto storeInfo = new WechatEntryStoreInfoReqDto()
|
||||
// .setBizStoreName("张三商行")
|
||||
// .setBizAddressCode("110101")
|
||||
// .setBizStoreAddress("北京")
|
||||
// .setStoreEntrancePic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"))
|
||||
// .setIndoorPic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"));
|
||||
// salesInfo.setBizStoreInfo(storeInfo);
|
||||
// businessInfo.setSalesInfo(salesInfo);
|
||||
//
|
||||
// reqDto.setBusinessInfo(businessInfo);
|
||||
//
|
||||
// WechatEntrySettleReqDto settleInfo = new WechatEntrySettleReqDto()
|
||||
// .setSettlementId("719")
|
||||
// .setQualificationType("IDCARD")
|
||||
// .setQualifications(List.of("110101199001011234"))
|
||||
// .setActivitiesId("20191030111cff5b5e");
|
||||
//
|
||||
// reqDto.setSettlementInfo(settleInfo);
|
||||
//
|
||||
// WechatEntryBankAccountReqDto bankAccountInfo = new WechatEntryBankAccountReqDto()
|
||||
// .setBankAccountType("BANK_ACCOUNT_TYPE_CORPORATE")
|
||||
// .setAccountBank("ICBC")
|
||||
// .setBankName("中国工商银行")
|
||||
// .setAccountName(encryptor.encrypt("张三"))
|
||||
// .setAccountNumber(encryptor.encrypt("110101199001011234"));
|
||||
//
|
||||
// reqDto.setBankAccountInfo(bankAccountInfo);
|
||||
|
||||
// entryMerchant(dto, reqDto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 09:15
|
||||
*/
|
||||
public class WechatPayManager {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.cipher.Signer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 微信请求工具类
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/29 10:02
|
||||
*/
|
||||
@Slf4j
|
||||
public class WechatReqUtils {
|
||||
|
||||
public static String postReq(WechatPayConfigDto configDto, String url, String body) {
|
||||
return req(configDto, url, "POST", body);
|
||||
}
|
||||
|
||||
public static String getReq(WechatPayConfigDto configDto, String url, Map<String, Object> params) {
|
||||
url = Arrays.stream(params.entrySet().toArray(new Map.Entry[0]))
|
||||
.map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8))
|
||||
.collect(Collectors.joining("&", url + "?", ""));
|
||||
|
||||
// 如果最后没有参数,则去掉多余的 "?"
|
||||
url = url.endsWith("?") ? url.substring(0, url.length() - 1) : url;
|
||||
|
||||
return req(configDto, url, "GET", "");
|
||||
}
|
||||
|
||||
private static String req(WechatPayConfigDto configDto, String url, String method, String body) {
|
||||
long timestamp = getTimestamp();
|
||||
String nonce = getNonceStr();
|
||||
String signature = encryptReqParam(configDto, method, url, body, timestamp, nonce);
|
||||
String authorization = String.format("WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\",timestamp=\"%d\",serial_no=\"%s\"",
|
||||
configDto.getMerchantId(), nonce, signature, timestamp, configDto.getSerialNumber());
|
||||
|
||||
HttpRequest request = switch (method) {
|
||||
case "POST" -> HttpUtil.createPost(configDto.getDomain() + url)
|
||||
.header("Authorization", authorization)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Wechatpay-Serial", configDto.getPublicKeyId())
|
||||
.body(body);
|
||||
|
||||
case "GET" -> HttpUtil.createGet(configDto.getDomain() + url)
|
||||
.header("Authorization", authorization)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Wechatpay-Serial", configDto.getPublicKeyId());
|
||||
default -> throw new CzgException("不支持的请求方法");
|
||||
};
|
||||
String s = request.execute().body();
|
||||
log.info("微信支付请求:url = {}, method: {}, body: {}, resp: {}", url, method, body, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密请求参数
|
||||
*
|
||||
* @param configDto 配置
|
||||
* @param method 请求方法
|
||||
* @param url 请求地址
|
||||
* @param body 请求报文主体
|
||||
* @return 加密后的报文
|
||||
* <p>
|
||||
* 签名方法
|
||||
* HTTP请求方法\n
|
||||
* URL\n
|
||||
* 请求时间戳\n
|
||||
* 请求随机串\n
|
||||
* 请求报文主体\n
|
||||
*/
|
||||
public static String encryptReqParam(WechatPayConfigDto configDto, String method, String url, String body, long timestamp, String nonce) {
|
||||
String encryptStr = String.format("%s\n%s\n%d\n%s\n%s\n",
|
||||
method, url, timestamp, nonce, body);
|
||||
log.info("encryptStr = {}", encryptStr);
|
||||
|
||||
Config config = WechatConfig.getRsaConfig(configDto);
|
||||
Signer signer = config.createSigner();
|
||||
String signature = signer.sign(encryptStr).getSign();
|
||||
log.info("签名 signature:{}", signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机串
|
||||
*/
|
||||
private static String getNonceStr() {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳
|
||||
*/
|
||||
private static long getTimestamp() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.czg.third.wechat.dto.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 09:21
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatPayConfigDto {
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
private String merchantId;
|
||||
|
||||
/**
|
||||
* Api V3密钥
|
||||
*/
|
||||
private String apiV3Key;
|
||||
|
||||
/**
|
||||
* 商户证书序列号
|
||||
*/
|
||||
private String serialNumber;
|
||||
|
||||
/**
|
||||
* 商户私钥
|
||||
*/
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* 商户公钥
|
||||
*/
|
||||
private String publicKey;
|
||||
|
||||
/**
|
||||
* 商户公钥 ID
|
||||
*/
|
||||
private String publicKeyId;
|
||||
|
||||
/**
|
||||
* 微信支付域名
|
||||
* <a href="https://api.mch.weixin.qq.com"></a>
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
public static WechatPayConfigDto getDefaultConfig() {
|
||||
return new WechatPayConfigDto()
|
||||
.setMerchantId("1643779408")
|
||||
.setApiV3Key("a92baac5eb7a36ed8ec198113e769a03")
|
||||
.setSerialNumber("4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4")
|
||||
.setPublicKey("""
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbeWXEEjBaYtw2OyM+SC
|
||||
aCEMbryRXi4duKxx3vYG4rUVix+d5/Jz7Khev4Upml9zC+Xxvv/G9bHWAUyolzqD
|
||||
wefahGurIxr43r4GJVnQ4i5G6BbBVw5d4Vuz0y/9Zd14zmc/EmBpT0Ml26H7tOZl
|
||||
n1LSbQ4xNFkrRKrNEcExBLxkCd+K5K2TREZznywIi0izbHImvuzM8IneuR51FiqK
|
||||
pdFnAjTwb126EIj6ECkL6KLCl8RWqpfiX8SFiolSQLs1/w79O0sIUk96X2zWpnoW
|
||||
rTDFatPif/VEKl3y2dTlxxDxoZtVi48yTDW00OMzVl5D67oX3FVK0KsjHJSCfGlZ
|
||||
6wIDAQAB
|
||||
-----END PUBLIC KEY-----""")
|
||||
.setPrivateKey("""
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDqnAZhTxT572fo
|
||||
6wvSr8Rt0vRXg+EFKC6UvUiNE24oocQU5fjedX9KL/+fmoqay/xqIxvxvCNFTs4J
|
||||
zlMqavSl6bMWCpjvf/Ry82JmN1v2kJEO4lgP8BsEiqlUpObCH8BMAVUOn1j+9q4Q
|
||||
uZJJcbtRvec2fNweDM8EJp4B7RlUdDbHm86lfcDVp8iini7VjDp6D7aHT+C8A8OT
|
||||
ugxQIquDec778wVd9r2Sv3+t6rAzFs+n+Zu++2xtFEPhO5N0wjrLHaukl+9crU+1
|
||||
lktjDzcPd07SwGZ+A+3BTmW3UCramI3506e/3MWBECB7ge+gM4URAV0nJJCLH/Im
|
||||
WgEvPMr5AgMBAAECggEBAKv+wraoMWqiVv1tA/froAgbtcJLDranJK8qrXuvmPz0
|
||||
yzm+91qvrSgIVFEADUk67swo/R2Vng37nhWWS2Y3jy/rSr2H+2Lp3Z5ATA0/3I3A
|
||||
onfU/FaC4mvL9CP32KzMdj/CYkccDzSsSCQ+x75MQNXGcTGDDCSDo2kZnpEu73j3
|
||||
aqvO1jbqTGWigRfjOIaIhStjQIT8nEm/3mJ4f5dM9M6FMz33mhax8EahSgvdahYB
|
||||
t45iaGOWw81OJhmry47EvpwjXBl7jtO2HX3LiLbq5Ebcwu1zqDz5NM7ttnnGAqWC
|
||||
6y7JN5Vt4wPYrCydiUDe7dj0looffr2yw6MkNfYjLGECgYEA+FAvbEInQEi9YguS
|
||||
CQtLHngqvYeai66tvyykog9o38KHnPGx2Myf+rn/Hcp7KNRfjd5G34CCNg7KLnrx
|
||||
YIYh6+2bY3jirzdYUxuNKGbvM4gky/6M/P9zHF/uALKOE02yArdqemf4UxUvrYCc
|
||||
JdXsAMqvbpdvW1aGgNRB32YCkG0CgYEA8d89vawsCjNCEUh0VWTMoBLFoex3qBMZ
|
||||
rfzYQeBo6bDCRlAlUVzl+ouBUxSYxP/U8rzeNaRzGUwRLmlGMjyIr58FBlHsg2cR
|
||||
DlsX3HVCUjpS6sgPXOqakdiLfhMcHZAspislSyVfeS3TbUWiA45+5PuNUq+EZYwl
|
||||
ESsB1+yfRT0CgYEA0Ct49ksnWM8iZbXJgeeD3FFlk2rBd2TDqEem5W4Bv8T3p+0/
|
||||
6b7yR2HyrGj5gys3yFmWFP1JLESN3xWWkhMhEQcrg+LuN3Iwi8vHNR3GXu892f7W
|
||||
96q4OAt8Hf2S+j/igkB99YyANDbIt63gOh/zMF67X/14j5wkOpC3gK+maqkCgYEA
|
||||
s7nIrPoUt3ejLiiCmTmPe5q3VDzcJP4cZNau8zSHgK6hjZHcSPsYwPWMoWl6o1fe
|
||||
qoiBLacHB9MoKS58xLOKdcVZ/Ho/ntylJd+2eVCAeY1xM5h5IfgJ5znbXVFh4O3S
|
||||
357L1Wzt5qOQqW/GlZH65LevKbPWU4axvHISqpnfN5kCgYEAqiqLuAPu84VSsqsE
|
||||
GFh25t+1f0JY1sNfilE3/t9AdQeeCFv/5z9KB1kMt3a5ZFeVonsFIvCyaOJjhSkj
|
||||
4HCB94vWS7NuN5G9r874lMaPbZYQGwrcVaf265tN7cYYr3gUx1qB6+u+fh/kcft1
|
||||
BBmTzhb0zp5k8ngwAkA1g/LK204=
|
||||
-----END PRIVATE KEY-----""")
|
||||
.setPublicKeyId("PUB_KEY_ID_0116437794082025111000382377001000")
|
||||
.setDomain("https://api.mch.weixin.qq.com");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 微信进件-补充信息
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:43
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryAdditionReqDto {
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法定代表人开户承诺函
|
||||
* 模板下载地址 <a href="https://kf.qq.com/faq/191018yUFjEj191018Vfmaei.html">...</a>
|
||||
* 通过图片上传完成后 MediaID
|
||||
*/
|
||||
@JSONField(name = "legal_person_commitment")
|
||||
private String legalPersonCommitment;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法定代表人开户意愿视频
|
||||
* 通过视频上传完成后 MediaID
|
||||
*/
|
||||
@JSONField(name = "legal_person_video")
|
||||
private String legalPersonVideo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 补充材料
|
||||
* 最多可上传5张照片
|
||||
* 通过图片上传完成后 MediaID
|
||||
*/
|
||||
@JSONField(name = "business_addition_pics")
|
||||
private List<String> businessAdditionPics;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 补充说明 512字以内
|
||||
*/
|
||||
@JSONField(name = "business_addition_msg")
|
||||
private String businessAdditionMsg;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 微信进件-银行账号
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:42
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryBankAccountReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 账户类型
|
||||
* 1、若主体为企业/政府机关/事业单位/社会组织,可填写:对公银行账户;
|
||||
* 2、若主体为个体户,可选择填写:对公银行账户或经营者个人银行卡
|
||||
* 可选取值 BANK_ACCOUNT_TYPE_CORPORATE: 对公银行账户 BANK_ACCOUNT_TYPE_PERSONAL: 经营者个人银行卡
|
||||
*/
|
||||
@JSONField(name = "bank_account_type")
|
||||
private String bankAccountType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户名称
|
||||
* 1、选择“经营者个人银行卡”时,开户名称必须与“经营者证件姓名”一致;
|
||||
* 2、选择“对公银行账户”时,开户名称必须与营业执照上的“商户名称”一致;
|
||||
* 3、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4013059044">...</a>
|
||||
*/
|
||||
@JSONField(name = "account_name")
|
||||
private String accountName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户银行
|
||||
* 对私银行调用:查询支持个人业务的银行列表API
|
||||
* 对公银行调用:查询支持对公业务的银行列表API
|
||||
*/
|
||||
@JSONField(name = "account_bank")
|
||||
private String accountBank;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 开户银行银行号
|
||||
* 1、根据开户银行查询接口中的“是否需要填写支行”判断是否需要填写。如为其他银行,开户银行全称(含支行)和开户银行联行号二选一;
|
||||
* 2、详细需调用查询支行列表API查看查询结果。 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012697673">...</a>
|
||||
*/
|
||||
@JSONField(name = "bank_branch_id")
|
||||
private String bankBranchId;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 开户银行全称(含支行)
|
||||
* 1、根据开户银行查询接口中的“是否需要填写支行”判断是否需要填写。如为其他银行,开户银行全称(含支行)和开户银行联行号二选一;
|
||||
* 2、详细需调用查询支行列表API查看查询结果。 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012697673">...</a>
|
||||
*/
|
||||
@JSONField(name = "bank_name")
|
||||
private String bankName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 开户银行账号
|
||||
* 1、选择“经营者个人银行卡”时,开户账号为经营者个人银行卡号;
|
||||
* 2、选择“对公银行账户”时,开户账号为对公银行账号;
|
||||
* 3、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4013059044">...</a>
|
||||
*/
|
||||
@JSONField(name = "account_number")
|
||||
private String accountNumber;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 进件 联系人信息
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:38
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryContactReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 超级管理员类型
|
||||
* 主体为“个体工商户/企业/政府机关/事业单位/社会组织”,可选择:LEGAL:经营者/法定代表人,SUPER:经办人 。(经办人:经商户授权办理微信支付业务的人员)。
|
||||
* 可选取值
|
||||
* LEGAL: 经营者/法定代表人
|
||||
* SUPER: 经办人
|
||||
*/
|
||||
@JSONField(name = "contact_type")
|
||||
private String contactType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 超级管理员姓名
|
||||
* 1、长度为2-100个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符。
|
||||
* 该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "contact_name")
|
||||
private String contactName;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员证件类型 当超级管理员类型是经办人时,请上传超级管理员证件类型。
|
||||
* 可选取值
|
||||
* IDENTIFICATION_TYPE_IDCARD: 中国大陆居民-身份证
|
||||
* IDENTIFICATION_TYPE_OVERSEA_PASSPORT: 其他国家或地区居民-护照
|
||||
* IDENTIFICATION_TYPE_HONGKONG_PASSPORT: 中国香港居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_MACAO_PASSPORT: 中国澳门居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_PASSPORT: 中国台湾居民-来往大陆通行证
|
||||
* IDENTIFICATION_TYPE_FOREIGN_RESIDENT: 外国人居留证
|
||||
* IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT: 港澳居民居住证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_RESIDENT: 台湾居民居住证
|
||||
*/
|
||||
@JSONField(name = "contact_id_type")
|
||||
private String contactIdType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员身份证件号码
|
||||
* 1、当超级管理员类型是经办人时,请上传超级管理员证件号码;
|
||||
* 2、可传身份证、来往内地通行证、来往大陆通行证、护照等证件号码,号码规范如下:
|
||||
* 身份证(限中国大陆居民):17位数字+1位数字|X;
|
||||
* 护照(限境外人士):4-15位 数字|字母|连字符;
|
||||
* 中国香港居民--来往内地通行证:H/h开头+8或10位数字/字母;
|
||||
* 中国澳门居民--来往内地通行证:M/m开头+8或10位数字/字母;
|
||||
* 中国台湾居民--来往大陆通行证:8位数字或10位数字;
|
||||
* 外国人居留证:15位 数字|字母;
|
||||
* 台湾居民居住证/港澳居民居住证:17位数字+1位数字|X;
|
||||
* 3、超级管理员签约时,校验微信号绑定的银行卡实名信息,是否与该证件号码一致;
|
||||
* 4、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "contact_id_number")
|
||||
private String contactIdNumber;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员证件正面照片
|
||||
* 1、当超级管理员类型是经办人时,请上传超级管理员证件的正面照片;
|
||||
* 2、若证件类型为身份证,请上传人像面照片;
|
||||
* 3、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 4、请上传彩色照片或彩色扫描件或复印件(需加盖公章鲜章),可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 5、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "contact_id_doc_copy")
|
||||
private String contactIdDocCopy;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员证件反面照片
|
||||
* 1、当超级管理员类型是经办人时,请上传超级管理员证件的反面照片;
|
||||
* 2、若证件类型为护照,无需上传反面照片;
|
||||
* 3、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 4、请上传彩色照片或彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 5、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "contact_id_doc_copy_back")
|
||||
private String contactIdDocCopyBack;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员证件有效期开始时间
|
||||
* 1、当超级管理员类型是经办人时,请上传证件有效期开始时间;
|
||||
* 2、请按照示例值填写,日期格式应满足合法的YYYY-MM-DD格式;
|
||||
* 3、开始时间不能小于1900-01-01,开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "contact_period_begin")
|
||||
private String contactPeriodBegin;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 超级管理员证件有效期截止时间
|
||||
* 1、当超级管理员类型是经办人时,请上传证件有效期结束时间;
|
||||
* 2、请按照示例值填写,日期格式应满足合法的YYYY-MM-DD格式,若证件有效期为长期,请填写:长期;
|
||||
* 3、结束时间大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "contact_period_end")
|
||||
private String contactPeriodEnd;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系手机
|
||||
* 1、前后不能有空格、制表符、换行符;
|
||||
* 2、需满足以下任一条件:
|
||||
* 11位数字的手机号码;
|
||||
* 5-20位数字、连字符“-”、加号“+”;
|
||||
* 3、用于接收微信支付的重要管理信息及日常操作验证码;
|
||||
* 4、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "mobile_phone")
|
||||
private String mobilePhone;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 联系邮箱
|
||||
* 1、用于接收微信支付的开户邮件及日常业务通知;
|
||||
* 2、需要带@,遵循邮箱格式校验 ,该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "contact_email")
|
||||
private String contactEmail;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.third.wechat.dto.req.entry.business.WechatEntryBusinessReqDto;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 微信进件请求参数
|
||||
* 参考地址 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012719997">...</a>
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:36
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 业务申请编号
|
||||
*/
|
||||
@JSONField(name = "business_code")
|
||||
private String businessCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 超级管理员信息
|
||||
*/
|
||||
@JSONField(name = "contact_info")
|
||||
private WechatEntryContactReqDto contactInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 主体资料
|
||||
*/
|
||||
@JSONField(name = "subject_info")
|
||||
private WechatEntrySubjectReqDto subjectInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 经营资料
|
||||
* 商家的经营业务信息、售卖商品/提供服务场景信息
|
||||
*/
|
||||
@JSONField(name = "business_info")
|
||||
private WechatEntryBusinessReqDto businessInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 结算规则
|
||||
* 请填写商家的结算费率规则、特殊资质等信息
|
||||
*/
|
||||
@JSONField(name = "settlement_info")
|
||||
private WechatEntrySettleReqDto settlementInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 结算银行账户
|
||||
*/
|
||||
@JSONField(name = "bank_account_info")
|
||||
private WechatEntryBankAccountReqDto bankAccountInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 补充材料
|
||||
* 根据实际审核情况,会额外要求商家提供指定的补充资料
|
||||
*/
|
||||
@JSONField(name = "addition_info")
|
||||
private WechatEntryAdditionReqDto additionInfo;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件 结算信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:38
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntrySettleReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 入驻结算规则ID
|
||||
* 请选择结算规则ID,详细参见费率结算规则对照表
|
||||
* <a href="https://kf.qq.com/faq/220228IJb2UV220228uEjU3Q.html">...</a>
|
||||
*/
|
||||
@JSONField(name = "settlement_id")
|
||||
private String settlementId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 所属行业
|
||||
* <a href="https://kf.qq.com/faq/220228IJb2UV220228uEjU3Q.html">...</a>
|
||||
*/
|
||||
@JSONField(name = "qualification_type")
|
||||
private String qualificationType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 特殊资质图片
|
||||
* 1、仅当商户选择了必需提交特殊资质的行业时,需要提供该项资料;若商户选择了无需特殊资质的行业,或未选择行业时,无需提交该项资料,详情查看《费率结算规则对照表》;
|
||||
* 2、最多可上传5张照片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "qualifications")
|
||||
private List<String> qualifications;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 优惠费率活动ID
|
||||
* 如果商户有意向报名优惠费率活动,该字段【必填】。详细参见《优惠费率活动对照表》
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4012082816">...</a>
|
||||
*/
|
||||
@JSONField(name = "activities_id")
|
||||
private String activitiesId;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 优惠费率活动值
|
||||
* 根据优惠费率活动规则,由合作伙伴自定义填写,支持两个小数点,需在优惠费率活动ID指定费率范围内
|
||||
* (1)2023年7月17日-9月17日,各合作伙伴平台可选择只传入“活动费率值”,或分别传入“信用卡优惠活动费率值” 与 “非信用卡优惠活动费率值”,只传入“活动费率值”的情况下,平台将协助将申请单中的 “优惠活动费率值” 回填入新增的 “信用卡优惠活动费率值” 与 “非信用卡优惠活动费率值”中 ;
|
||||
* (2)2023年9月18日起,平台将不再提供如上兼容能力,届时仅能分别传入“信用卡优惠活动费率值” 与 “非信用卡优惠活动费率值”,否则接口将会报错。为避免影响正常进件,请在兼容期间完成相关调整。
|
||||
*/
|
||||
@JSONField(name = "activities_rate")
|
||||
private String activitiesRate;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 优惠费率活动补充材料
|
||||
* 1、根据所选优惠费率活动,提供相关材料,详细参见《优惠费率活动对照表》;<a href="https://pay.weixin.qq.com/doc/v3/partner/4012082816">...</a>
|
||||
* 2、最多可上传5张照片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "activities_additions")
|
||||
private List<String> activitiesAdditions;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 非信用卡活动费率值
|
||||
* 用户支付方式为借记卡时收取的手续费费率:
|
||||
* 1、若填写了优惠费率活动ID,则该字段【必填】;
|
||||
* 2、仅能填入2位以内小数,且在优惠费率活动ID指定费率范围内。
|
||||
*/
|
||||
@JSONField(name = "debit_activities_rate")
|
||||
private String debitActivitiesRate;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 信用卡活动费率值
|
||||
* 用户支付方式为信用卡时收取的手续费费率:
|
||||
* 1、若填写了优惠费率活动ID,则该字段【必填】;
|
||||
* 2、仅能填入2位以内小数,且在优惠费率活动ID指定费率范围内。
|
||||
*/
|
||||
@JSONField(name = "credit_activities_rate")
|
||||
private String creditActivitiesRate;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.czg.third.wechat.dto.req.entry;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.third.wechat.dto.req.entry.business.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件 主体资料
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:40
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntrySubjectReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 主体类型 主体类型需与营业执照/登记证书上一致,可参考选择主体指引。<a href="https://kf.qq.com/faq/180910IBZVnQ180910naQ77b.html">...</a>
|
||||
* 可选取值
|
||||
* SUBJECT_TYPE_INDIVIDUAL: (个体户)营业执照上的主体类型一般为个体户、个体工商户、个体经营
|
||||
* SUBJECT_TYPE_ENTERPRISE: (企业)营业执照上的主体类型一般为有限公司、有限责任公司
|
||||
* SUBJECT_TYPE_GOVERNMENT: (政府机关)包括各级、各类政府机关,如机关党委、税务、民政、人社、工商、商务、市监等
|
||||
* SUBJECT_TYPE_INSTITUTIONS: (事业单位)包括国内各类事业单位,如:医疗、教育、学校等单位
|
||||
* SUBJECT_TYPE_OTHERS:(社会组织) 包括社会团体、民办非企业、基金会、基层群众性自治组织、农村集体经济组织等组织
|
||||
*/
|
||||
@JSONField(name = "subject_type")
|
||||
private String subjectType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 是否是金融机构
|
||||
* 【是否是金融机构】 【选填】,请根据申请主体的实际情况填写,可参考选择金融机构指引:
|
||||
* 1、若商户主体是金融机构,则填写:true;
|
||||
* 2、若商户主体不是金融机构,则填写:false。
|
||||
* 若未传入将默认填写:false。
|
||||
*/
|
||||
@JSONField(name = "finance_institution")
|
||||
private Boolean financeInstitution;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 营业执照 当前不允许小微注册,所以【必填】
|
||||
* 1、主体为个体户/企业,【必填】;
|
||||
* 2、请上传“营业执照”,需年检章齐全,当年注册除外;
|
||||
*/
|
||||
@JSONField(name = "business_license_info")
|
||||
private WechatEntryLicenseReqDto businessLicenseInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 登记证书 主体为政府机关/事业单位/其他组织时,【必填】。
|
||||
*/
|
||||
@JSONField(name = "certificate_info")
|
||||
private WechatEntryCertificateReqDto certificateInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 单位证明函照片
|
||||
* 1、主体类型为政府机关、事业单位选传:
|
||||
* (1)若上传,则审核通过后即可签约,无需汇款验证;
|
||||
* (2)若未上传,则审核通过后,需汇款验证。
|
||||
* 2、主体为个体户、企业、其他组织等,不需要上传本字段;
|
||||
* 3、请参照示例图打印单位证明函,全部信息需打印,不支持手写商户信息,并加盖公章; <a href="https://kf.qq.com/faq/200114u2y2yQ200114uEz26z.html">...</a>
|
||||
* 4、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "certificate_letter_copy")
|
||||
private String certificateLetterCopy;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 金融机构许可证信息 当主体是金融机构时,【必填】。
|
||||
*/
|
||||
@JSONField(name = "finance_institution_info")
|
||||
private WechatEntryFinanceInstitutionReqDto financeInstitutionInfo;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 经营者/法定代表人身份证件
|
||||
* 1、个体户:请上传经营者的身份证件;
|
||||
* 2、企业/社会组织:请上传法定代表人的身份证件;
|
||||
* 3、政府机关/事业单位:请上传法定代表人/经办人的身份证件。
|
||||
*/
|
||||
@JSONField(name = "identity_info")
|
||||
private WechatEntryIdentityReqDto identityInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 最终受益人信息列表(UBO)
|
||||
* 1、主体类型个体户/社会组织/政府机关/事业单位时,无需填写
|
||||
* 2、主体类型为企业时,按照下述要求填写
|
||||
* 1)若经营者/法定代表人不是最终受益所有人,则需提填写受益所有人信息,最多上传4个。
|
||||
* 2)若经营者/法定代表人是最终受益所有人之一,可在此填写其他受益所有人信息,最多上传3个。
|
||||
* 根据国家相关法律法规,需要提供公司受益所有人信息,受益所有人需符合至少以下条件之一:
|
||||
* ▪️直接或者间接拥有超过25%公司股权或者表决权的自然人。
|
||||
* ▪️通过人事、财务等其他方式对公司进行控制的自然人。
|
||||
* ▪️公司的高级管理人员,包括公司的经理、副经理、财务负责人、上市公司董事会秘书和公司章程规定的其他人员。
|
||||
*/
|
||||
@JSONField(name = "ubo_info_list")
|
||||
private List<WechatEntryUboInfoReqDto> uboInfoList;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntrySalesInfoReqDto;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 微信进件 商户信息 经营资料
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 13:41
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryBusinessReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户简称 在支付完成页向买家展示,需与微信经营类目相关
|
||||
* 1、请输入1-64个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式;
|
||||
* 6、简称要求
|
||||
* (1)不支持单纯以人名来命名,若为个体户经营,可用“个体户+经营者名称”或“经营者名称+业务”命名,如“个体户张三”或“张三餐饮店”;
|
||||
* (2)不支持无实际意义的文案,如“XX特约商户”、“800”、“XX客服电话XXX”。
|
||||
*/
|
||||
@JSONField(name = "merchant_shortname")
|
||||
private String merchantShortname;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 客服电话 将在交易记录中向买家展示,请确保电话畅通以便平台回拨确认
|
||||
* 1、前后不能有空格、制表符、换行符;
|
||||
* 2、需满足以下任一条件;
|
||||
* 11位数字的手机号码;
|
||||
* 5-20位数字、连字符“-”、加号“+”。
|
||||
*/
|
||||
@JSONField(name = "service_phone")
|
||||
private String servicePhone;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 经营场景
|
||||
*/
|
||||
@JSONField(name = "sales_info")
|
||||
private WechatEntrySalesInfoReqDto salesInfo;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 登记证书
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:07
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryCertificateReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 登记证书照片
|
||||
* 1、照片应正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 2、上传彩色照片、彩色扫描件,复印件需加盖公章鲜章;
|
||||
* 3、水印仅限于微信支付业务相关;
|
||||
* 4、指引与示例可参考【指引文档】;
|
||||
* 5、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "cert_copy")
|
||||
private String certCopy;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 登记证书类型
|
||||
* 1、主体为“政府机关/事业单位/社会组织”时,请上传登记证书类型;
|
||||
* 2、主体为“个体工商户/企业”时,不填;
|
||||
* 当主体为事业单位时,选择此枚举值:
|
||||
* CERTIFICATE_TYPE_2388:事业单位法人证书
|
||||
* 当主体为政府机关,选择此枚举值:
|
||||
* CERTIFICATE_TYPE_2389:统一社会信用代码证书
|
||||
* 当主体为社会组织,选择以下枚举值之一:
|
||||
* CERTIFICATE_TYPE_2389:统一社会信用代码证书
|
||||
* CERTIFICATE_TYPE_2394:社会团体法人登记证书
|
||||
* CERTIFICATE_TYPE_2395:民办非企业单位登记证书
|
||||
* CERTIFICATE_TYPE_2396:基金会法人登记证书
|
||||
* CERTIFICATE_TYPE_2520:执业许可证/执业证
|
||||
* CERTIFICATE_TYPE_2521:基层群众性自治组织特别法人统一社会信用代码证
|
||||
* CERTIFICATE_TYPE_2522:农村集体经济组织登记证
|
||||
* CERTIFICATE_TYPE_2399:宗教活动场所登记证
|
||||
* CERTIFICATE_TYPE_2400:政府部门下发的其他有效证明文件
|
||||
*/
|
||||
@JSONField(name = "cert_type")
|
||||
private String certType;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 证书号 请输入与所选证书类型相匹配且符合国家标准规范的证书号,其中除政府证明文件外,需满足18位阿拉伯数字或大写英文字母(不得包含英文字母I/O/Z/S/V)
|
||||
*/
|
||||
@JSONField(name = "cert_number")
|
||||
private String certNumber;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户名称 请填写登记证书上的商户名称
|
||||
* 1、长度为2-128个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式。
|
||||
*/
|
||||
@JSONField(name = "merchant_name")
|
||||
private String merchantName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 注册地址 请填写登记证书的注册地址
|
||||
* 1、长度为4-128个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式。
|
||||
*/
|
||||
@JSONField(name = "company_address")
|
||||
private String companyAddress;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法定代表人 请填写登记证书上的法定代表人姓名
|
||||
* 1、长度为2-100个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符。
|
||||
*/
|
||||
@JSONField(name = "legal_person")
|
||||
private String legalPerson;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 有效期限开始日期 建议填写营业执照的有效期限开始时间,若该字段未填写,系统将会查询国家工商信息填入。需注意若工商信息查询不到,则会被审核驳回。
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式;
|
||||
* 2、开始时间不能小于1900-01-01;
|
||||
* 3、开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "period_begin")
|
||||
private String periodBegin;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 营业期限结束日期 建议填写营业执照的有效期限结束时间,若该字段未填写,系统将会查询国家工商信息填入。需注意若工商信息查询不到,则会被审核驳回。
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式或长期;
|
||||
* 2、结束时间需大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "period_end")
|
||||
private String periodEnd;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 金融机构许可证信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:21
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryFinanceInstitutionReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 金融机构类型 金融机构类型需与营业执照/登记证书上一致,可参考选择金融机构指引。
|
||||
* BANK_AGENT:银行业, 适用于商业银行、政策性银行、农村合作银行、村镇银行、开发性金融机构等
|
||||
* PAYMENT_AGENT:支付机构, 适用于非银行类支付机构
|
||||
* INSURANCE:保险业, 适用于保险、保险中介、保险代理、保险经纪等保险类业务
|
||||
* TRADE_AND_SETTLE:交易及结算类金融机构, 适用于交易所、登记结算类机构、银行卡清算机构、资金清算中心等
|
||||
* OTHER:其他金融机构, 适用于财务公司、信托公司、金融资产管理公司、金融租赁公司、汽车金融公司、贷款公司、货币经纪公司、消费金融公司、证券业、金融控股公司、股票、期货、货币兑换、小额贷款公司、金融资产管理、担保公司、商业保理公司、典当行、融资租赁公司、财经咨询等其他金融业务
|
||||
*/
|
||||
@JSONField(name = "finance_type")
|
||||
private String financeType;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 金融机构许可证图片
|
||||
* 1、照片应正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 2、上传彩色照片、彩色扫描件,复印件需加盖公章鲜章;
|
||||
* 3、水印仅限于微信支付业务相关;
|
||||
* 4、根据所属金融机构类型的许可证要求提供,详情查看金融机构指引; <a href="https://kf.qq.com/faq/220215IrMRZ3220215n6buiU.html">...</a>
|
||||
* 5、请提供为“申请商家主体”所属的许可证,可授权使用总公司/分公司的特殊资质;
|
||||
* 6、最多可上传5张照片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "finance_license_pics")
|
||||
private List<String> financeLicensePics;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.third.wechat.dto.req.entry.id.WechatEntryIdCardReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.id.WechatEntryIdDocInfoReqDto;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 经营者/法定代表人身份证件
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:24
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryIdentityReqDto {
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件持有人类型
|
||||
* 1、主体类型为政府机关/事业单位时选传:
|
||||
* (1)若上传的是法定代表人证件,则不需要上传该字段。
|
||||
* (2)若因政策保密等原因,无法提供法定代表人证件时,可上传经办人。 (经办人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。
|
||||
* 2、主体类型为小微/个人卖家/企业/个体户/社会组织时,默认为经营者/法定代表人,不需要上传该字段。
|
||||
* LEGAL: 经营者/法定代表人
|
||||
* SUPER: 经办人
|
||||
*/
|
||||
@JSONField(name = "id_holder_type")
|
||||
private String idHolderType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件类型
|
||||
* 1、当证件持有人类型为法定代表人时,填写。其他情况,无需上传;
|
||||
* 2、个体户/企业/事业单位/社会组织:可选择任一证件类型,政府机关仅支持中国大陆居民-身份证类型。
|
||||
* 可选取值
|
||||
* IDENTIFICATION_TYPE_IDCARD: 中国大陆居民-身份证
|
||||
* IDENTIFICATION_TYPE_OVERSEA_PASSPORT: 其他国家或地区居民-护照
|
||||
* IDENTIFICATION_TYPE_HONGKONG_PASSPORT: 中国香港居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_MACAO_PASSPORT: 中国澳门居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_PASSPORT: 中国台湾居民-来往大陆通行证
|
||||
* IDENTIFICATION_TYPE_FOREIGN_RESIDENT: 外国人居留证
|
||||
* IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT: 港澳居民居住证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_RESIDENT: 台湾居民居住证
|
||||
*/
|
||||
@JSONField(name = "id_doc_type")
|
||||
private String idDocType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 法定代表人说明函
|
||||
* 1、当证件持有人类型为经办人时,必须上传。其他情况,无需上传;
|
||||
* 2、若因特殊情况,无法提供法定代表人证件时,请参照示例图打印法定代表人说明函,全部信息需打印,不支持手写商户信息,并加盖公章; <a href="https://kf.qq.com/faq/220127aUzAju220127UfiuQr.html">...</a>
|
||||
* 3、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "authorize_letter_copy")
|
||||
private String authorizeLetterCopy;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 身份证信息 当证件持有人类型为经营者/法定代表人且证件类型为“身份证”时填写。
|
||||
*/
|
||||
@JSONField(name = "id_card_info")
|
||||
private WechatEntryIdCardReqDto idCardInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 其他类型证件信息 当证件持有人类型为经营者/法定代表人且证件类型不为“身份证”时填写。
|
||||
*/
|
||||
@JSONField(name = "id_doc_info")
|
||||
private WechatEntryIdDocInfoReqDto idDocInfo;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 营业执照信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:59
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryLicenseReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 营业执照照片
|
||||
* 1、照片应正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 2、上传彩色照片、彩色扫描件,复印件需加盖公章鲜章;
|
||||
* 3、水印仅限于微信支付业务相关;
|
||||
* 4、指引与示例可参考【指引文档】;
|
||||
* 5、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "license_copy")
|
||||
private String licenseCopy;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 注册号/统一社会信用代码
|
||||
*/
|
||||
@JSONField(name = "license_number")
|
||||
private String licenseNumber;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户名称
|
||||
* 1、长度为2-128个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式;
|
||||
* 6、个体户证件为以下情况时,按照个体户XXX命名(XXX是营业执照经营人姓名):营业执照登记名称为空、仅含数字、仅含特殊字符、“无”、“无字号”;
|
||||
* 7、个体户不能使用“企业”“公司”或“农民专业合作社”结尾。
|
||||
*/
|
||||
@JSONField(name = "merchant_name")
|
||||
private String merchantName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 个体户经营者/法定代表人姓名 请填写营业执照的经营者/法定代表人姓名
|
||||
* 1、长度为2-100个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符。
|
||||
*/
|
||||
@JSONField(name = "legal_person")
|
||||
private String legalPerson;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 注册地址 建议填写营业执照的注册地址,若该字段未填写,系统将会查询国家工商信息填入。需注意若工商信息查询不到,则会被审核驳回。
|
||||
* 1、长度为4-128个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式。
|
||||
*/
|
||||
@JSONField(name = "license_address")
|
||||
private String licenseAddress;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 有效期限开始日期 建议填写营业执照的有效期限开始时间,若该字段未填写,系统将会查询国家工商信息填入。需注意若工商信息查询不到,则会被审核驳回。
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式;
|
||||
* 2、开始时间不能小于1900-01-01;
|
||||
* 3、开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "period_begin")
|
||||
private String periodBegin;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 营业期限结束日期 建议填写营业执照的有效期限结束时间,若该字段未填写,系统将会查询国家工商信息填入。需注意若工商信息查询不到,则会被审核驳回。
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式或长期;
|
||||
* 2、结束时间需大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "period_end")
|
||||
private String periodEnd;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 最终受益人信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:50
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryUboInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 证件类型 请填写受益人的证件类型。枚举值:
|
||||
* 可选取值
|
||||
* IDENTIFICATION_TYPE_IDCARD: 中国大陆居民-身份证
|
||||
* IDENTIFICATION_TYPE_OVERSEA_PASSPORT: 其他国家或地区居民-护照
|
||||
* IDENTIFICATION_TYPE_HONGKONG_PASSPORT: 中国香港居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_MACAO_PASSPORT: 中国澳门居民-来往内地通行证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_PASSPORT: 中国台湾居民-来往大陆通行证
|
||||
* IDENTIFICATION_TYPE_FOREIGN_RESIDENT: 外国人居留证
|
||||
* IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT: 港澳居民居住证
|
||||
* IDENTIFICATION_TYPE_TAIWAN_RESIDENT: 台湾居民居住证
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_type")
|
||||
private String uboIdDocType;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件正面照片
|
||||
* 1、请上传受益人证件的正面照片;
|
||||
* 2、若证件类型为身份证,请上传人像面照片;
|
||||
* 3、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 4、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 5、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_copy")
|
||||
private String uboIdDocCopy;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件反面照片
|
||||
* 1、请上传受益人证件的反面照片;
|
||||
* 2、若证件类型为身份证,请上传国徽面照片;
|
||||
* 3、若证件类型为护照,无需上传反面照片;
|
||||
* 4、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 5、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 6、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_copy_back")
|
||||
private String uboIdDocCopyBack;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件姓名
|
||||
* 1、长度为2-100个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_name")
|
||||
private String uboIdDocName;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件号码
|
||||
* 1、证件号码为证件正反面中一致的号码;
|
||||
* 2、证件号码为18位或15位,或港澳居民来往内地通行证为9位;
|
||||
* 3、证件号码为英文字母X或x,或港澳居民来往内地通行证为英文字母X或x;
|
||||
* 4、证件号码为英文字母x或X,或港澳居民来往内地通行证为英文字母x或X;
|
||||
* 5、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_number")
|
||||
private String uboIdDocNumber;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件居住地址
|
||||
* 1、请按照身份证住址填写,如广东省深圳市南山区xx路xx号xx室;
|
||||
* 2、长度为4-128个字符;
|
||||
* 3、前后不能有空格、制表符、换行符;
|
||||
* 4、不能仅含数字、特殊字符;
|
||||
* 5、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 6、仅支持utf-8格式;
|
||||
* 7、 该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "ubo_id_doc_address")
|
||||
private String uboIdDocAddress;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件有效期开始时间
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式;
|
||||
* 2、开始时间不能小于1900-01-01;
|
||||
* 3、开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "ubo_period_begin")
|
||||
private String uboPeriodBegin;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件有效期结束时间
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式或长期;
|
||||
* 2、结束时间需大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "ubo_period_end")
|
||||
private String uboPeriodEnd;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-App场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:26
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryAppInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* App截图
|
||||
* 1、请提供APP首页截图、尾页截图、应用内截图、支付页截图各1张;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "app_pics")
|
||||
private List<String> appPics;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商家应用AppID
|
||||
* 1、服务商应用AppID与商家应用AppID,二选一【必填】;
|
||||
* 2、可填写与商家主体一致且已认证的应用AppID,需是已认证的App;
|
||||
* 3、审核通过后,系统将发起特约商家商户号与该AppID的绑定(即配置为sub_appid),服务商随后可在发起支付时选择传入该AppID,以完成支付,并获取sub_openid用于数据统计,营销等业务场景。
|
||||
*/
|
||||
@JSONField(name = "app_sub_appid")
|
||||
private String appSubAppid;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 服务商应用AppID
|
||||
* 1、服务商应用AppID与商家应用AppID,二选一【必填】;
|
||||
* 2、可填写当前服务商商户号已绑定的应用AppID。
|
||||
*/
|
||||
@JSONField(name = "app_appid")
|
||||
private String appAppid;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-小程序场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:23
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryMiniProgramReqDto {
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 服务商小程序AppID
|
||||
* 1、服务商小程序AppID与商家小程序AppID,二选一必填;
|
||||
* 2、可填写当前服务商商户号已绑定的小程序AppID。
|
||||
*/
|
||||
@JSONField(name = "mini_program_appid")
|
||||
private String miniProgramAppid;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商家小程序AppID
|
||||
* 1、服务商小程序AppID与商家小程序AppID,二选一必填;
|
||||
* 2、请填写已认证的小程序AppID;
|
||||
* 3、完成进件后,系统发起特约商户号与该AppID的绑定(即配置为sub_appid可在发起支付时传入)
|
||||
* (1)若AppID主体与商家主体/服务商主体一致,则直接完成绑定;
|
||||
* (2)若AppID主体与商家主体/服务商主体不一致,则商户签约时显示《联合营运承诺函》,并且AppID的管理员需登录公众平台确认绑定意愿。
|
||||
*/
|
||||
@JSONField(name = "mini_program_sub_appid")
|
||||
private String miniProgramSubAppid;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 小程序截图
|
||||
* 1、请提供展示商品/服务的页面截图/设计稿(最多5张),若小程序未建设完善或未上线 请务必提供;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "mini_program_pics")
|
||||
private List<String> miniProgramPics;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-服务号或公众号景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:20
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryMpInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 服务号或公众号页面截图
|
||||
* 1、请提供展示商品/服务的页面截图/设计稿(最多5张),若服务号或公众号未建设完善或未上线请务必提供;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "mp_pics")
|
||||
private List<String> mpPics;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 商家服务号或公众号AppID
|
||||
* 1、服务商服务号或公众号AppID、商家服务号或公众号AppID,二选一【必填】;
|
||||
* 2、可填写与商家主体一致且已认证的服务号或公众号AppID,需是已认证的服务号、政府或媒体类型的公众号;
|
||||
* 3、审核通过后,系统将发起特约商家商户号与该AppID的绑定(即配置为sub_appid),服务商随后可在发起支付时选择传入该appid,以完成支付,并获取sub_openid用于数据统计,营销等业务场景。
|
||||
*/
|
||||
@JSONField(name = "mp_sub_appid")
|
||||
private String mpSubAppid;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 服务商服务号或公众号AppID
|
||||
* 1、服务商服务号或公众号AppID、商家服务号或公众号AppID,二选一【必填】;
|
||||
* 2、可填写当前服务商商户号已绑定的服务号或公众号AppID。
|
||||
*/
|
||||
@JSONField(name = "mp_appid")
|
||||
private String mpAppid;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件-经营场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:07
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntrySalesInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 经营场景类型
|
||||
* 1、请勾选实际售卖商品/提供服务场景(至少一项),以便为你开通需要的支付权限;
|
||||
* 2、建议只勾选目前必须的场景,以便尽快通过入驻审核,其他支付权限可在入驻后再根据实际需要发起申请
|
||||
* 可选取值
|
||||
* SALES_SCENES_STORE: 线下场所
|
||||
* SALES_SCENES_MP: 服务号与公众号
|
||||
* SALES_SCENES_MINI_PROGRAM: 小程序
|
||||
* SALES_SCENES_WEB: 互联网网站
|
||||
* SALES_SCENES_APP: App
|
||||
* SALES_SCENES_WEWORK: 企业微信
|
||||
*/
|
||||
@JSONField(name = "sales_scenes_type")
|
||||
private List<String> salesScenesType;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 线下场所场景
|
||||
* 1、审核通过后,服务商可帮商户发起付款码支付、JSAPI支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_STORE",该场景资料【必填】。
|
||||
*/
|
||||
@JSONField(name = "biz_store_info")
|
||||
private WechatEntryStoreInfoReqDto bizStoreInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 服务号或公众号场景
|
||||
* 1、审核通过后,服务商可帮商家发起JSAPI支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_MP",该场景资料【必填】。
|
||||
*/
|
||||
@JSONField(name = "mp_info")
|
||||
private WechatEntryMpInfoReqDto mpInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 小程序场景
|
||||
* 1、审核通过后,服务商可帮商家发起JSAPI支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_MINI_PROGRAM",该场景资料必填。
|
||||
*/
|
||||
@JSONField(name = "mini_program_info")
|
||||
private WechatEntryMiniProgramReqDto miniProgramInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* App场景
|
||||
* 1、审核通过后,服务商可帮商家发起App支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_APP",该场景资料必填。
|
||||
*/
|
||||
@JSONField(name = "app_info")
|
||||
private WechatEntryAppInfoReqDto appInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 互联网网站场景
|
||||
* 1、审核通过后,服务商可帮商家发起JSAPI支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_WEB",该场景资料必填。
|
||||
*/
|
||||
@JSONField(name = "web_info")
|
||||
private WechatEntryWebInfoReqDto webInfo;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 企业微信场景
|
||||
* 1、审核通过后,服务商可帮商家发起JSAPI支付;
|
||||
* 2、当"经营场景类型"选择"SALES_SCENES_WEWORK",该场景资料必填。
|
||||
*/
|
||||
@JSONField(name = "wework_info")
|
||||
private WechatEntryWeworkInfoReqDto weworkInfo;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-线下场所场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:10
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryStoreInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 线下场所名称 请填写门店名称
|
||||
* 1、长度为1-50个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式。
|
||||
*/
|
||||
@JSONField(name = "biz_store_name")
|
||||
private String bizStoreName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 线下场所省市编码
|
||||
* 1、只能由数字组成;
|
||||
* 2、详细参见微信支付提供的省市对照表。 <a href="https://pay.weixin.qq.com/doc/v3/partner/4012082815">...</a>
|
||||
*/
|
||||
@JSONField(name = "biz_address_code")
|
||||
private String bizAddressCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 线下场所地址 请填写详细的经营场所信息,如有多个场所,选择一个主要场所填写即可。
|
||||
* 1、长度为4-512个字符;
|
||||
* 2、前后不能有空格、制表符、换行符;
|
||||
* 3、不能仅含数字、特殊字符;
|
||||
* 4、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 5、仅支持utf-8格式
|
||||
*/
|
||||
@JSONField(name = "biz_store_address")
|
||||
private String bizStoreAddress;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 线下场所门头照片
|
||||
* 1、请上传门头正面照片(要求门店招牌、门框完整、清晰、可辨识);若为停车场等无固定门头照片的经营场所,可上传岗亭/出入闸口。具体参考【指引文档】;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "store_entrance_pic")
|
||||
private List<String> storeEntrancePic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 线下场所内部照片
|
||||
* 1、请上传门店内部环境照片(可辨识经营内容)。若为停车场等无固定门头的经营场所,可上传停车场内部照片。具体参考【指引文档】;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "indoor_pic")
|
||||
private List<String> indoorPic;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 线下场所对应的商家AppID
|
||||
* 1、可填写与商家主体一致且已认证的服务号或公众号、小程序、APP的AppID,其中服务号或公众号AppID需是已认证的服务号、政府或媒体类型的公众号;
|
||||
* 2、审核通过后,系统将额外为商家开通付款码支付、JSAPI支付的自有交易权限,并完成商家商户号与该AppID的绑定。
|
||||
*/
|
||||
@JSONField(name = "biz_sub_appid")
|
||||
private String bizSubAppid;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-互联网网站场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:29
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryWebInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 互联网网站域名
|
||||
* 1、如为PC端商城、智能终端等场景,可上传官网链接;
|
||||
* 2、网站域名需ICP备案,若备案主体与申请主体不同,请上传加盖公章的网站授权函。
|
||||
*/
|
||||
@JSONField(name = "domain")
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 网站授权函
|
||||
* 1、若备案主体与申请主体不同,请务必上传加盖公章的网站授权函.doc; <a href="https://gtimg.wechatpay.cn/resource/xres/mmpaydoc/static/attachment/bb55b16e3825a5952a531d55fba0f382/%E7%BD%91%E7%AB%99%E6%8E%88%E6%9D%83%E5%87%BD.doc">...</a>
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "web_authorisation")
|
||||
private String webAuthorisation;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 互联网网站对应的商家AppID
|
||||
* 1、可填写已认证的服务号或公众号、小程序、APP的AppID,其中服务号或公众号AppID需是已认证的服务号、政府或媒体类型的公众号;
|
||||
* 2、完成进件后,系统发起特约商户号与该AppID的绑定(即配置为sub_appid,可在发起支付时传入)
|
||||
* (1)若APPID主体与商家主体一致,则直接完成绑定;
|
||||
* (2)若APPID主体与商家主体不一致,则商户签约时显示《联合营运承诺函》,并且 AppID的管理员需登录公众平台确认绑定意愿;( 暂不支持绑定异主体的应用APPID)。
|
||||
*/
|
||||
@JSONField(name = "web_appid")
|
||||
private String webAppid;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.czg.third.wechat.dto.req.entry.business.sales;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 进件-经营资料-经营场景-企业微信场景
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 14:32
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryWeworkInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商家企业微信CorpID
|
||||
* 1、可填写与商家主体一致且已认证的企业微信CorpID;
|
||||
* 2、审核通过后,系统将为商家开通企业微信专区的自有交易权限,并完成商家商户号与该AppID的绑定,商家可自行发起交易。
|
||||
*/
|
||||
@JSONField(name = "sub_corp_id")
|
||||
private String subCorpId;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 企业微信页面截图
|
||||
* 1、最多可上传5张照片;
|
||||
* 2、请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "wework_pics")
|
||||
private String[] weworkPics;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.czg.third.wechat.dto.req.entry.id;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 身份证信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:29
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryIdCardReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证人像面照片
|
||||
* 1、请上传个体户经营者/法定代表人的身份证人像面照片;
|
||||
* 2、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 3、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 4、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "id_card_copy")
|
||||
private String idCardCopy;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证国徽面照片
|
||||
* 、请上传个体户经营者/法定代表人的身份证国徽面照片;
|
||||
* 2、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 3、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 4、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "id_card_national")
|
||||
private String idCardNational;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证姓名
|
||||
* 1、请填写个体户经营者/法定代表人对应身份证的姓名;
|
||||
* 2、长度为2-100个字符;
|
||||
* 3、前后不能有空格、制表符、换行符;
|
||||
* 4、不能仅含数字、特殊字符;
|
||||
* 5、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 6、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4013059044">加密</a>
|
||||
*/
|
||||
@JSONField(name = "id_card_name")
|
||||
private String idCardName;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 身份证号码
|
||||
* 1、请填写个体户经营者/法定代表人对应身份证的号码;
|
||||
* 2、17位数字+1位数字|X ,该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4013059044">加密</a>
|
||||
*/
|
||||
@JSONField(name = "id_card_number")
|
||||
private String idCardNumber;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 身份证居住地址
|
||||
* 1、主体类型为企业时,需要填写。其他主体类型,无需上传;
|
||||
* 2、请按照身份证住址填写,如广东省深圳市南山区xx路xx号xx室;
|
||||
* 3、长度为4-128个字符;
|
||||
* 4、前后不能有空格、制表符、换行符;
|
||||
* 5、不能仅含数字、特殊字符;
|
||||
* 6、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 7、仅支持utf-8格式;
|
||||
* 8、 该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
* <a href="https://pay.weixin.qq.com/doc/v3/partner/4013059044">加密</a>
|
||||
*/
|
||||
@JSONField(name = "id_card_address")
|
||||
private String idCardAddress;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 身份证有效期开始时间
|
||||
* 1、请填写身份证有效期开始时间,格式为yyyy-MM-dd;
|
||||
* 2、开始时间不能小于1900-01-01;
|
||||
* 3、开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "card_period_begin")
|
||||
private String cardPeriodBegin;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 身份证有效期截止时间
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式或长期;
|
||||
* 2、结束时间需大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "card_period_end")
|
||||
private String cardPeriodEnd;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.czg.third.wechat.dto.req.entry.id;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 其他类型证件信息
|
||||
* @author yjjie
|
||||
* @date 2025/12/26 15:42
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatEntryIdDocInfoReqDto {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 证件正面照片
|
||||
* 1、证件类型不为“身份证”时,上传证件正面照片;
|
||||
* 2、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 3、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 4、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "id_doc_copy")
|
||||
private String idDocCopy;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件反面照片
|
||||
* 1、若证件类型为往来通行证、外国人居留证、港澳居民居住证、台湾居民居住证时,上传证件反面照片;
|
||||
* 2、若证件类型为护照,无需上传反面照片;
|
||||
* 3、正面拍摄、清晰、四角完整、无反光或遮挡;不得翻拍、截图、镜像、PS;
|
||||
* 4、请上传彩色照片or彩色扫描件,复印件需加盖公章鲜章,可添加“微信支付”相关水印(如微信支付认证),见【指引文档】;
|
||||
* 5、可上传1张图片,请填写通过图片上传API预先上传图片生成好的MediaID。
|
||||
*/
|
||||
@JSONField(name = "id_doc_copy_back")
|
||||
private String idDocCopyBack;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 证件姓名
|
||||
* 1、请填写经营者/法定代表人的证件姓名;
|
||||
* 2、长度为2-100个字符;
|
||||
* 3、前后不能有空格、制表符、换行符;
|
||||
* 4、不能仅含数字、特殊字符;
|
||||
* 5、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 6、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "id_doc_name")
|
||||
private String idDocName;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 证件号码
|
||||
* 1、请填写经营者/法定代表人的证件号码:
|
||||
* 护照(限境外人士):4-15位 数字|字母|连字符;
|
||||
* 中国香港居民--来往内地通行证:H/h开头+8或10位数字/字母;
|
||||
* 中国澳门居民--来往内地通行证:M/m开头+8或10位数字/字母;
|
||||
* 中国台湾居民--来往大陆通行证:8位数字或10位数字;
|
||||
* 外国人居留证:15位 数字|字母;
|
||||
* 台湾居民居住证/港澳居民居住证:17位数字+1位数字|X;
|
||||
* 2、该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "id_doc_number")
|
||||
private String idDocNumber;
|
||||
|
||||
/**
|
||||
* 【选填】
|
||||
* 证件居住地址
|
||||
* 1、主体类型为企业时,需要填写。其他主体类型,无需上传;
|
||||
* 2、请按照身份证住址填写,如广东省深圳市南山区xx路xx号xx室;
|
||||
* 3、长度为4-128个字符;
|
||||
* 4、前后不能有空格、制表符、换行符;
|
||||
* 5、不能仅含数字、特殊字符;
|
||||
* 6、仅能填写数字、英文字母、汉字及特殊字符;
|
||||
* 7、仅支持utf-8格式;
|
||||
* 8、 该字段需要使用微信支付公钥加密(推荐),请参考获取微信支付公钥ID说明以及微信支付公钥加密敏感信息指引,也可以使用微信支付平台证书公钥加密,参考获取平台证书序列号、平台证书加密敏感信息指引。
|
||||
*/
|
||||
@JSONField(name = "id_doc_address")
|
||||
private String idDocAddress;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件有效期开始时间
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式;
|
||||
* 2、开始时间不能小于1900-01-01;
|
||||
* 3、开始时间不能大于等于当前日期。
|
||||
*/
|
||||
@JSONField(name = "doc_period_begin")
|
||||
private String docPeriodBegin;
|
||||
|
||||
/**
|
||||
* 必填
|
||||
* 证件有效期结束时间
|
||||
* 1、日期格式应满足合法的YYYY-MM-DD格式或长期;
|
||||
* 2、结束时间需大于开始时间。
|
||||
*/
|
||||
@JSONField(name = "doc_period_end")
|
||||
private String docPeriodEnd;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.czg.utils;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Java 21 异步多任务执行工具类
|
||||
* 功能:异步执行多个任务,等待所有任务完成后统一返回结果(包含成功/失败信息)
|
||||
* 特性:基于虚拟线程、支持泛型、完善的异常处理、可自定义线程池
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 18:21
|
||||
*/
|
||||
public class AsyncTaskExecutor {
|
||||
|
||||
// 默认线程池:Java 21 虚拟线程池(轻量级、高并发)
|
||||
private static final ExecutorService DEFAULT_EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();
|
||||
|
||||
/**
|
||||
* 执行多个异步任务,等待所有任务完成后统一返回结果
|
||||
*
|
||||
* @param tasks 任务列表(每个任务是一个 Supplier 函数式接口,封装具体业务逻辑)
|
||||
* @param <T> 任务返回值类型
|
||||
* @return 所有任务的执行结果(包含成功/失败信息)
|
||||
*/
|
||||
public static <T> List<TaskResult<T>> executeAll(List<Supplier<T>> tasks) {
|
||||
return executeAll(tasks, DEFAULT_EXECUTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行多个异步任务(自定义线程池),等待所有任务完成后统一返回结果
|
||||
*
|
||||
* @param tasks 任务列表
|
||||
* @param executor 自定义线程池(如需要使用传统线程池可传入)
|
||||
* @param <T> 任务返回值类型
|
||||
* @return 所有任务的执行结果
|
||||
*/
|
||||
public static <T> List<TaskResult<T>> executeAll(List<Supplier<T>> tasks, ExecutorService executor) {
|
||||
// 校验入参
|
||||
if (tasks == null || tasks.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
if (executor == null) {
|
||||
throw new IllegalArgumentException("线程池不能为null");
|
||||
}
|
||||
|
||||
// 1. 提交所有异步任务,获取CompletableFuture列表
|
||||
List<CompletableFuture<TaskResult<T>>> futureList = tasks.stream()
|
||||
.map(task -> CompletableFuture.supplyAsync(
|
||||
() -> executeSingleTask(task),
|
||||
executor
|
||||
))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 2. 等待所有任务完成(无超时)
|
||||
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
|
||||
futureList.toArray(new CompletableFuture[0])
|
||||
);
|
||||
|
||||
try {
|
||||
// 阻塞等待所有任务完成(可根据业务需求添加超时,如 allFutures.get(10, TimeUnit.SECONDS))
|
||||
allFutures.get();
|
||||
} catch (Exception e) {
|
||||
// 全局等待异常(如超时、中断),标记所有未完成的任务为失败
|
||||
handleGlobalException(futureList, e);
|
||||
}
|
||||
|
||||
// 3. 收集所有任务结果
|
||||
return futureList.stream()
|
||||
// 显式指定泛型类型,让编译器明确知道map的返回类型是TaskResult<T>
|
||||
.<TaskResult<T>>map(future -> {
|
||||
try {
|
||||
// 这里强制指定泛型,避免类型推断模糊
|
||||
return future.get();
|
||||
} catch (Exception e) {
|
||||
// 理论上不会走到这里,因为singleTask已捕获异常,allOf已等待完成
|
||||
return new TaskResult<>(null, false, "结果收集异常:" + e.getMessage());
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行单个任务,捕获任务执行过程中的异常
|
||||
*/
|
||||
private static <T> TaskResult<T> executeSingleTask(Supplier<T> task) {
|
||||
try {
|
||||
T result = task.get();
|
||||
return new TaskResult<>(result, true, null);
|
||||
} catch (Exception e) {
|
||||
// 捕获单个任务的所有异常,封装为失败结果
|
||||
return new TaskResult<>(null, false, "任务执行失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理全局等待过程中的异常(如超时、中断),标记未完成任务为失败
|
||||
*/
|
||||
private static <T> void handleGlobalException(List<CompletableFuture<TaskResult<T>>> futureList, Exception e) {
|
||||
String errorMsg = "全局等待异常:" + e.getMessage();
|
||||
futureList.forEach(future -> {
|
||||
if (!future.isDone()) {
|
||||
// 取消未完成的任务,并标记为失败
|
||||
future.complete(new TaskResult<>(null, false, errorMsg));
|
||||
}
|
||||
});
|
||||
// 恢复线程中断状态(如果是中断异常)
|
||||
if (e instanceof InterruptedException) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务结果封装类
|
||||
* 包含:返回值、是否成功、失败信息
|
||||
*
|
||||
* @param <T> 结果类型
|
||||
* @param result Getter 方法 任务返回值(成功时非null)
|
||||
* @param success 是否执行成功
|
||||
* @param errorMsg 失败信息(失败时非null)
|
||||
*/
|
||||
public record TaskResult<T>(T result, boolean success, String errorMsg) {
|
||||
|
||||
// 重写toString,方便打印结果
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
if (success) {
|
||||
return "TaskResult{success=true, result=" + result + "}";
|
||||
} else {
|
||||
return "TaskResult{success=false, errorMsg='" + errorMsg + "'}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭默认线程池(可选,如应用退出时调用)
|
||||
*/
|
||||
public static void shutdownDefaultExecutor() {
|
||||
DEFAULT_EXECUTOR.shutdown();
|
||||
try {
|
||||
if (!DEFAULT_EXECUTOR.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
DEFAULT_EXECUTOR.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
DEFAULT_EXECUTOR.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.czg.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/4 13:58
|
||||
*/
|
||||
@Slf4j
|
||||
public class UploadFileUtil {
|
||||
|
||||
// 匹配常见的图片扩展名
|
||||
private static final Pattern PATTERN = Pattern.compile("\\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)(?:[\\?#]|$)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* 使用正则表达式提取图片后缀
|
||||
*/
|
||||
public static String extractImageExtension(String imageUrl) {
|
||||
java.util.regex.Matcher matcher = PATTERN.matcher(imageUrl);
|
||||
|
||||
if (matcher.find()) {
|
||||
String extension = matcher.group(1).toLowerCase();
|
||||
// 处理jpeg的情况
|
||||
return "jpeg".equals(extension) ? "jpg" : extension;
|
||||
}
|
||||
// 默认后缀
|
||||
return "png";
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载图片
|
||||
* @param url 图片地址
|
||||
* @return 图片字节数组
|
||||
*/
|
||||
public static byte[] downloadImage(String url) {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
try {
|
||||
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
||||
|
||||
if (response.statusCode() != 200) {
|
||||
throw new RuntimeException("Failed to download image, status code: " + response.statusCode());
|
||||
}
|
||||
|
||||
return response.body();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to download image: {}", e.getMessage());
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从URL中提取文件名
|
||||
*
|
||||
* @param url 图片URL
|
||||
* @return 提取的文件名,失败则返回默认名
|
||||
*/
|
||||
public static String extractFileNameFromUrl(String url) {
|
||||
try {
|
||||
if (url.contains("/")) {
|
||||
String fileName = url.substring(url.lastIndexOf("/") + 1);
|
||||
// 如果文件名包含参数,截取?之前的部分
|
||||
if (fileName.contains("?")) {
|
||||
fileName = fileName.substring(0, fileName.indexOf("?"));
|
||||
}
|
||||
// 如果提取的文件名有效,直接返回
|
||||
if (fileName.contains(".")) {
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("提取文件名失败,使用默认文件名", e);
|
||||
}
|
||||
// 默认文件名
|
||||
return "upload_" + System.currentTimeMillis() + ".png";
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
<description>第三方内容</description>
|
||||
<modules>
|
||||
<module>czg-pay</module>
|
||||
<module>aggregation-pay</module>
|
||||
</modules>
|
||||
<artifactId>cash-sdk</artifactId>
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ public class ShopInfoServiceImpl extends ServiceImpl<ShopInfoMapper, ShopInfo> i
|
||||
if (shopInfo == null) {
|
||||
throw new CzgException("店铺不存在");
|
||||
}
|
||||
if (shopInfo.getExpireTime() != null && (LocalDateTime.now().isAfter(shopInfo.getExpireTime()))) {
|
||||
if (shopInfo.getExpireTime() != null && (DateUtil.date().toLocalDateTime().isAfter(shopInfo.getExpireTime()))) {
|
||||
throw new CzgException("店铺已过期,请联系商家");
|
||||
}
|
||||
if (SystemConstants.OneZero.ZERO == shopInfo.getOnSale() || shopInfo.getStatus() != SystemConstants.OneZero.ONE) {
|
||||
|
||||
@@ -22,8 +22,6 @@ import com.czg.market.vo.InviteUserVO;
|
||||
import com.czg.market.vo.MemberConfigVO;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.service.account.mapper.ShopUserMapper;
|
||||
import com.czg.service.account.util.FunUtil;
|
||||
import com.czg.utils.FunUtils;
|
||||
import com.czg.utils.PageUtil;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
@@ -63,7 +61,6 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
||||
private MemberLevelConfigService memberLevelConfigService;
|
||||
@DubboReference
|
||||
private TbMemberConfigService memberConfigService;
|
||||
|
||||
private ShopUser getUserInfo(Long shopUserId) {
|
||||
ShopUser shopUser = queryChain().eq(ShopUser::getId, shopUserId).one();
|
||||
if (shopUser == null) {
|
||||
@@ -243,13 +240,9 @@ public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> i
|
||||
shopUser.setBirthDay(null);
|
||||
}
|
||||
shopUser.setNickName(userInfo.getNickName());
|
||||
// if (shopUser.getJoinTime() == null) {
|
||||
// shopUser.setJoinTime(LocalDateTime.now());
|
||||
// }
|
||||
boolean b = saveOrUpdate(shopUser);
|
||||
if (b) {
|
||||
FunUtils.transactionSafeRun(() -> memberConfigService.joinMemberByCondition(shopId, userId, shopUser));
|
||||
if (shopUser.getJoinTime() == null) {
|
||||
shopUser.setJoinTime(LocalDateTime.now());
|
||||
}
|
||||
return b;
|
||||
return saveOrUpdate(shopUser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.czg.market.entity.MkPointsUser;
|
||||
import com.czg.market.entity.MkShopCouponRecord;
|
||||
import com.czg.market.service.MkPointsUserService;
|
||||
import com.czg.market.service.MkShopCouponRecordService;
|
||||
import com.czg.market.service.TbMemberConfigService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.account.mapper.ShopConfigMapper;
|
||||
|
||||
@@ -85,6 +85,8 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
||||
private ShopUserService shopUserService;
|
||||
@DubboReference
|
||||
private UserInfoService userInfoService;
|
||||
@DubboReference
|
||||
private OrderPaymentService orderPaymentService;
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
@DubboReference
|
||||
@@ -704,16 +706,6 @@ public class MkDistributionUserServiceImpl extends ServiceImpl<MkDistributionUse
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void distributionUserAmount(MkDistributionFlow item, OrderInfo orderInfo) {
|
||||
ShopUser shopUser = shopUserService.getById(item.getDistributionUserId());
|
||||
updateShopInfoAmount(orderInfo.getShopId(), item.getRewardAmount().negate(), orderInfo.getId(), TableValueConstant.DistributionAmountFlow.Type.SUB, "分销扣减");
|
||||
updateIncome(item.getRewardAmount().negate(), item.getRewardAmount(), BigDecimal.ZERO,
|
||||
item.getDistributionUserId(), shopUser.getUserId(), item.getShopUserId(), item.getShopId(), item.getLevel());
|
||||
distributionFlowService.updateById(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distribute(Long sourceId, String orderNo, BigDecimal amount, Long sourceUserId, Long shopId, String type) {
|
||||
MkDistributionDeliver deliver = new MkDistributionDeliver().setSourceId(sourceId).setOrderNo(orderNo).setShopId(shopId).setType(type).setStatus("success");
|
||||
|
||||
@@ -192,7 +192,7 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
|
||||
.shopId(pointsUser.getShopId())
|
||||
.shopUserId(pointsUser.getShopUserId())
|
||||
.floatType(PointsConstant.SUB.getValue())
|
||||
.floatPoints(-floatPoints)
|
||||
.floatPoints(floatPoints)
|
||||
.balancePoints(pointsUser.getPointBalance())
|
||||
.sourceId(orderId.toString())
|
||||
.content(reason)
|
||||
|
||||
@@ -175,9 +175,9 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
|
||||
|
||||
// 标准充值
|
||||
if (rechargeDetailId != null) {
|
||||
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
|
||||
shopUserMoneyEditDTO.setMoney(rechargeDetail.getAmount());
|
||||
FunUtils.asyncSafeRunVoid(() -> {
|
||||
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
|
||||
shopUserMoneyEditDTO.setMoney(rechargeDetail.getAmount());
|
||||
// 赠送金额
|
||||
ShopUserMoneyEditDTO shopUserMoneyEditRewardDTO = new ShopUserMoneyEditDTO()
|
||||
.setId(shopUserId)
|
||||
|
||||
@@ -361,7 +361,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
|
||||
memberExpFlowService.save(expFlow);
|
||||
|
||||
upShopUser.setExperience(shopUser.getExperience() + exp);
|
||||
shopUser.setExperience(upShopUser.getExperience());
|
||||
// 修改会员等级
|
||||
MemberLevelConfig nextConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopUser.getMainShopId())
|
||||
.gt(MemberLevelConfig::getExperienceValue, levelVO.getExperienceValue()).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
|
||||
|
||||
@@ -36,7 +36,7 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
||||
private final BigDecimal MONEY_RATE = new BigDecimal("100");
|
||||
|
||||
@Resource
|
||||
private OrderPaymentService paymentService;
|
||||
private OrderPaymentService orderPaymentService;
|
||||
@Resource
|
||||
private MkDistributionConfigService configService;
|
||||
@Resource
|
||||
@@ -74,7 +74,7 @@ public class DistributionPayServiceImpl implements DistributionPayService {
|
||||
.setPayType(PayTypeConstants.PayType.PAY)
|
||||
.setOrderNo(payParam.getPlatformType() + IdUtil.getSnowflakeNextId())
|
||||
.setAmount(isRecharge ? payParam.getAmount() : detail.getPayAmount());
|
||||
paymentService.save(orderPayment);
|
||||
orderPaymentService.save(orderPayment);
|
||||
|
||||
InitInfo initInfo = new InitInfo().setConfig(detail);
|
||||
if (isRecharge) {
|
||||
|
||||
@@ -1060,8 +1060,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
distributionUserService.costUpgradeLevelBefore(orderInfo.getUserId(), orderInfo.getShopId());
|
||||
// 分销奖励
|
||||
distributionUserService.distribute(orderInfo.getId(), orderInfo.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), orderInfo.getShopId(), "order");
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
|
||||
boolean isFree = PayTypeConstants.SourceType.FREE.equals(payment.getSourceType());
|
||||
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
|
||||
OrderInfo orderInfo = null;
|
||||
@@ -1113,22 +1112,17 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
|
||||
payment.getId(), payment.getSourceType(), bizEnum, orderInfo == null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
|
||||
//购买会员
|
||||
ShopUser shopUser = shopUserService.getById(payment.getSourceId());
|
||||
memberConfigService.joinMember(payment.getShopId(), shopUser.getUserId(), payment.getRelatedId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
|
||||
distributionUserService.open(payment.getSourceId(), payment.getAmount(), payment.getShopId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
|
||||
goodPayService.payCallBack(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
|
||||
gbOrderService.payCallBack(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
|
||||
} else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
|
||||
ppPackageOrderService.paySuccess(payment.getSourceId(), payment.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, Ord
|
||||
@Override
|
||||
public BigDecimal countMemberInAmount(Long shopId, Long shopUserId) {
|
||||
return getOneAs(QueryWrapper.create().select("IFNULL(sum(amount), 0) as total_amount")
|
||||
.eq(OrderPayment::getShopId, shopId)
|
||||
.eq(OrderPayment::getShopId, 143)
|
||||
.eq(OrderPayment::getSourceType, PayTypeConstants.SourceType.MEMBER_IN)
|
||||
.eq(OrderPayment::getPayType, PayTypeConstants.PayType.PAY)
|
||||
.eq(OrderPayment::getSourceId, shopUserId)
|
||||
.eq(OrderPayment::getSourceId, 127452)
|
||||
.eq(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS), BigDecimal.class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user