Compare commits
75 Commits
633c0919eb
...
pay
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa4469b494 | ||
| 3537cf4dbd | |||
| c7b13dcf6b | |||
|
|
f4e82e9952 | ||
| d20d023dd1 | |||
|
|
cfa4158172 | ||
| 3ad73263c5 | |||
| d321393e12 | |||
|
|
3a0ca901f8 | ||
| 0a86cdc769 | |||
| e5be277941 | |||
|
|
21b9acf3c9 | ||
|
|
006035f71b | ||
|
|
f89fda0698 | ||
|
|
74122fae45 | ||
|
|
193f4d016a | ||
|
|
8501e21cf4 | ||
|
|
6ec6fafc98 | ||
|
|
7efc46126c | ||
|
|
8d9878a316 | ||
|
|
9a1b5b5cae | ||
|
|
484c40cdb5 | ||
|
|
8a8cef3005 | ||
|
|
38ea1478cb | ||
|
|
2046ad2486 | ||
|
|
0cdad226ea | ||
|
|
e179a910ba | ||
|
|
6b5c451f92 | ||
|
|
303db8bc49 | ||
| 6bddf05c36 | |||
| 19af647b04 | |||
| 87dd4cc3ba | |||
| 5df01f5192 | |||
| 3b83d210dc | |||
| d70546f55e | |||
| c6102dd4b4 | |||
|
|
f374c335c4 | ||
| b171b1a81f | |||
| 0b5ec53187 | |||
| ec59490f3a | |||
| 7d434ff5c7 | |||
| ef48e4e51d | |||
| 5cb895ac19 | |||
| e125eed517 | |||
|
|
621bf2401d | ||
| bae1762dba | |||
|
|
22a5ae8f68 | ||
|
|
ae65bf1814 | ||
|
|
b1215acca5 | ||
|
|
a6dd4f4611 | ||
| 506e74747a | |||
| 72c9379e87 | |||
| 441ede37cf | |||
| b359b08713 | |||
| 821b83f7c6 | |||
| a8bcf991fe | |||
| 240d672211 | |||
|
|
302504b891 | ||
|
|
a76c3f75a4 | ||
| a05d8083bc | |||
| ed1b6b2ecf | |||
| 7c9c6d6a02 | |||
|
|
658c7f14b2 | ||
| 8635c42506 | |||
|
|
f318c18606 | ||
|
|
2be24abced | ||
|
|
ee6df9ad1c | ||
|
|
81e102ff41 | ||
| 2f4226b3c8 | |||
| 56ab4d0403 | |||
| 7af2f8f925 | |||
| 5938520ddf | |||
| f88612d115 | |||
| ebe2da9163 | |||
| 0dbda61bac |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -61,3 +61,4 @@ build/
|
||||
/cash-api/product-server/src/main/resources/application-zs.yml
|
||||
/cash-api/system-server/src/main/resources/application-zs.yml
|
||||
/cash-service/code-generator/src/main/java/com/czg/Main.java
|
||||
/cash-api/product-server/logs/
|
||||
|
||||
@@ -147,32 +147,4 @@ public class NotifyController {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
String str = "<xml><ToUserName><![CDATA[gh_11fc27b7ef34]]></ToUserName><FromUserName><![CDATA[owWHW7Tzeh2gx3WmFsFSxBq2JUTk]]></FromUserName><CreateTime>1761095747</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[subscribe]]></Event><EventKey><![CDATA[qrscene_275]]></EventKey><Ticket><![CDATA[gQGF8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUTZDVHRTMXhmbUoxYUlYdk5GY2sAAgSsLvhoAwQAjScA]]></Ticket></xml>";
|
||||
// 2. 解析 XML 为 Map(便于获取字段)
|
||||
Map<String, String> messageMap = new HashMap<>();
|
||||
try {
|
||||
messageMap = parseXmlToMap(str);
|
||||
} catch (DocumentException e) {
|
||||
log.error("XML 解析失败,", e);
|
||||
}
|
||||
log.info("微信 POST 消息内容: {}", messageMap);
|
||||
//携带参数
|
||||
String eventKey = messageMap.get("EventKey");
|
||||
Long userId = null;
|
||||
if (eventKey != null && eventKey.startsWith("qrscene_")) {
|
||||
try {
|
||||
// 截取 "qrscene_" 前缀后的字符串(长度为 8),并转为 Long
|
||||
String numberStr = eventKey.substring("qrscene_".length());
|
||||
userId = Long.parseLong(numberStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("EventKey 后缀不是有效数字,eventKey: {}", eventKey, e);
|
||||
}
|
||||
}
|
||||
System.out.println("userId: " + userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
* @author GYJoker
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
@RequestMapping("/notify/test")
|
||||
public class TestController {
|
||||
@Resource
|
||||
private ShopUserFlowService shopUserFlowService;
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* 会员配置管理
|
||||
* @author ww
|
||||
*/
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.czg.annotation.SaAdminCheckPermission;
|
||||
import com.czg.market.dto.MkPointsConfigDTO;
|
||||
import com.czg.market.dto.MkPointsUserDTO;
|
||||
import com.czg.market.entity.MkPointsConfig;
|
||||
import com.czg.market.entity.MkPointsUser;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
import com.czg.market.service.MkPointsConfigService;
|
||||
import com.czg.market.service.MkPointsUserRecordService;
|
||||
@@ -12,15 +13,16 @@ import com.czg.market.service.MkPointsUserService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.utils.CzgStrUtils;
|
||||
import com.czg.validator.ValidatorUtil;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
import com.czg.validator.group.InsertGroup;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 积分配置
|
||||
@@ -88,4 +90,23 @@ public class PointsConfigController {
|
||||
@RequestParam(required = false) Long id) {
|
||||
return CzgResult.success(userRecordService.pageByPointsUserId(page, size, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户积分 包括配置信息
|
||||
* {
|
||||
* "pointsConfig": 配置信息,
|
||||
* "pointsUser": 用户积分信息
|
||||
* }
|
||||
*/
|
||||
@GetMapping("userPoints")
|
||||
public CzgResult<Map<String, Object>> userPoints(@RequestParam(required = false) Long shopUserId) {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
MkPointsConfig pointsConfig = pointsConfigService.getById(shopId);
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getShopUserId, shopUserId));
|
||||
result.put("pointsConfig", pointsConfig == null ? "" : pointsConfig);
|
||||
result.put("pointsUser", pointsUser == null ? "" : pointsUser);
|
||||
return CzgResult.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -89,6 +89,14 @@ public class PpPackageController {
|
||||
return CzgResult.success(ppPackageService.getPackagePage(reqVo, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐详情
|
||||
*/
|
||||
@GetMapping("/detail/{id}")
|
||||
public CzgResult<PpPackageVO> getPackageDetail(@PathVariable Long id, Long shopId) {
|
||||
return CzgResult.success(ppPackageService.getPackageDetail(id, shopId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套餐推广开关
|
||||
* 0: 关闭 1: 开启
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.market.dto.MkShopRechargeDTO;
|
||||
import com.czg.market.entity.MkShopConsumeDiscountRecord;
|
||||
import com.czg.market.entity.MkShopRechargeFlow;
|
||||
import com.czg.market.service.MkRechargeFlowService;
|
||||
import com.czg.market.service.MkShopConsumeDiscountRecordService;
|
||||
@@ -30,12 +29,6 @@ public class ShopRechargeController {
|
||||
@Resource
|
||||
private MkShopConsumeDiscountRecordService shopConsumeDiscountRecordService;
|
||||
|
||||
@GetMapping("/test")
|
||||
public CzgResult<MkShopConsumeDiscountRecord> get(@RequestParam Long shopId) {
|
||||
// return CzgResult.success(shopConsumeDiscountRecordService.get(shopId));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置信息获取
|
||||
* 权限标识: activate:list
|
||||
|
||||
@@ -60,10 +60,10 @@ public class UPointsController {
|
||||
Long shopId = StpKit.USER.getShopId();
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
MkPointsConfig pointsConfig = pointsConfigService.getById(shopId);
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getUserId, shopUserId));
|
||||
MkPointsUser pointsUser = pointsUserService.getOne(QueryWrapper.create().eq(MkPointsUser::getShopId, shopId).eq(MkPointsUser::getShopUserId, shopUserId));
|
||||
result.put("pointsConfig", pointsConfig == null ? "" : pointsConfig);
|
||||
result.put("pointsUser", pointsUser == null ? "" : pointsUser);
|
||||
return CzgResult.success();
|
||||
return CzgResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分销定时任务
|
||||
@@ -42,6 +43,8 @@ public class DistributionTask {
|
||||
@DubboReference
|
||||
private ShopUserService shopUserService;
|
||||
|
||||
List<String> list = List.of(OrderStatusEnums.REFUND.getCode(), OrderStatusEnums.PART_REFUND.getCode());
|
||||
|
||||
/**
|
||||
* 分销流水入账
|
||||
* AAMarketTasks 统一调用位置
|
||||
@@ -55,6 +58,10 @@ public class DistributionTask {
|
||||
// 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 -> {
|
||||
@@ -63,10 +70,12 @@ public class DistributionTask {
|
||||
|
||||
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;
|
||||
}
|
||||
if (CollUtil.newArrayList(OrderStatusEnums.REFUND.getCode(), OrderStatusEnums.REFUNDING.getCode(), OrderStatusEnums.PART_REFUND.getCode()).contains(orderInfo.getStatus())) {
|
||||
if (list.contains(orderInfo.getStatus())) {
|
||||
log.warn("订单已退款, 订单号: {}", item.getOrderNo());
|
||||
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
|
||||
} else {
|
||||
|
||||
@@ -4,8 +4,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.CzgPayUtils;
|
||||
import com.czg.account.entity.ShopUser;
|
||||
import com.czg.account.service.ShopUserService;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.entity.CzgBaseRespParams;
|
||||
import com.czg.market.entity.MkShopConsumeDiscountRecord;
|
||||
import com.czg.market.service.MkDistributionUserService;
|
||||
@@ -13,7 +12,6 @@ import com.czg.market.service.MkShopConsumeDiscountRecordService;
|
||||
import com.czg.market.service.OrderInfoService;
|
||||
import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
import com.czg.constants.PayTypeConstants;
|
||||
import com.czg.order.service.OrderInfoCustomService;
|
||||
import com.czg.order.service.OrderPaymentService;
|
||||
import com.czg.service.market.service.impl.AppWxServiceImpl;
|
||||
@@ -39,10 +37,6 @@ import java.io.IOException;
|
||||
@RequestMapping("/notify")
|
||||
public class NotifyController {
|
||||
private static final String SUCCESS = "SUCCESS";
|
||||
|
||||
@Resource
|
||||
private ShopUserService shopUserService;
|
||||
|
||||
@Resource
|
||||
private OrderInfoCustomService orderInfoCustomService;
|
||||
@Resource
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.czg.order.vo.HistoryOrderVo;
|
||||
import com.czg.order.vo.OrderInfoVo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.order.service.PayService;
|
||||
import com.czg.service.order.service.OrderPayService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.ServletUtil;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
@@ -31,7 +31,7 @@ public class AdminOrderController {
|
||||
@Resource
|
||||
private OrderInfoCustomService orderInfoService;
|
||||
@Resource
|
||||
private PayService payService;
|
||||
private OrderPayService orderPayService;
|
||||
|
||||
/**
|
||||
* 订单列表
|
||||
@@ -94,7 +94,7 @@ public class AdminOrderController {
|
||||
@PostMapping("/refundOrder")
|
||||
@Debounce(value = "#refundDTO.orderId")
|
||||
public CzgResult<Object> refundOrder(@Validated @RequestBody OrderInfoRefundDTO refundDTO) {
|
||||
return payService.refundOrderBefore(refundDTO);
|
||||
return orderPayService.refundOrderBefore(refundDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.EntryManager;
|
||||
import com.czg.annotation.Debounce;
|
||||
import com.czg.dto.req.AggregateMerchantDto;
|
||||
import com.czg.dto.resp.BankBranchDto;
|
||||
import com.czg.service.order.dto.AggregateMerchantVO;
|
||||
import com.czg.service.order.service.ShopDirectMerchantService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.task.EntryManagerTask;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件管理
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/admin/data/entryManager")
|
||||
public class EntryManagerController {
|
||||
|
||||
@Resource
|
||||
private ShopDirectMerchantService shopDirectMerchantService;
|
||||
@Resource
|
||||
private EntryManagerTask entryManagerTask;
|
||||
|
||||
/**
|
||||
* ocr识别填充
|
||||
* 阿里 ocr识别图片
|
||||
* 本接口支持:PNG、JPG、JPEG、BMP、GIF、TIFF、WebP、PDF。
|
||||
* 图片长宽需要大于 15 像素,小于 8192 像素。
|
||||
* 长宽比需要小于 50。长宽均大于 500px。
|
||||
* 图片二进制文件不能超过 10MB。
|
||||
* 图片过大会影响接口响应速度,建议使用小于 1.5M 图片进行识别,
|
||||
*
|
||||
* @param url 图片地址
|
||||
* @param type IdCard 身份证
|
||||
* BankCard 银行卡
|
||||
* BusinessLicense 营业执照
|
||||
*/
|
||||
@GetMapping("getInfoByImg")
|
||||
public CzgResult<JSONObject> getInfoByImg(String url, String type) throws Exception {
|
||||
return CzgResult.success(shopDirectMerchantService.getInfoByImg(url, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询银行支行列表
|
||||
*
|
||||
* @param province 省份 陕西省 从 /system/admin/common/region获取
|
||||
* @param city 城市 西安市 从 /system/admin/common/region获取
|
||||
* @param instId 顶级机构ID CMB 从 /system/admin/common/bankInfo 获取
|
||||
*/
|
||||
@GetMapping("bankBranchList")
|
||||
public CzgResult<List<BankBranchDto>> queryBankBranchList(String province, String city, String instId) {
|
||||
return CzgResult.success(EntryManager.queryBankBranchList(province, city, instId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取进件信息
|
||||
*/
|
||||
@GetMapping
|
||||
public CzgResult<AggregateMerchantVO> getEntry(Long shopId) {
|
||||
return CzgResult.success(shopDirectMerchantService.getEntry(shopId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动查询进件信息状态
|
||||
* 进件状态是INIT 待处理 AUDIT 审核中 SIGN 待签约
|
||||
* 3分钟内只能查一次
|
||||
*/
|
||||
@GetMapping("queryEntry")
|
||||
@Debounce(value = "#shopId", interval = 1000 * 60 * 3)
|
||||
public CzgResult<Boolean> queryEntry(Long shopId) {
|
||||
entryManagerTask.entryManager(shopId);
|
||||
return CzgResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请进件
|
||||
*/
|
||||
@Debounce(value = "#reqDto.shopId")
|
||||
@PostMapping
|
||||
public CzgResult<Boolean> entryManager(@RequestBody AggregateMerchantDto reqDto) {
|
||||
return CzgResult.success(shopDirectMerchantService.entryManager(reqDto));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.czg.market.service.GbWareService;
|
||||
import com.czg.order.dto.GbOrderQueryParam;
|
||||
import com.czg.order.service.GbOrderService;
|
||||
import com.czg.order.vo.GbOrderCountVO;
|
||||
import com.czg.order.vo.GbWareVO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.utils.AssertUtil;
|
||||
@@ -87,4 +88,12 @@ public class GbWareController {
|
||||
AssertUtil.isNull(id, "操作失败,请选择商品");
|
||||
return CzgResult.success(wareService.deleteGbWare(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品详情
|
||||
*/
|
||||
@GetMapping("/ware/detail")
|
||||
public CzgResult<GbWareVO> getWareDetail(@RequestParam Long shopId, @RequestParam Long wareId) {
|
||||
return CzgResult.success(gbOrderService.getWareDetail(shopId, wareId, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.czg.controller;
|
||||
package com.czg.controller.pay;
|
||||
|
||||
import com.czg.annotation.Debounce;
|
||||
import com.czg.order.dto.MkDistributionPayDTO;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.order.service.DistributionPayService;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.czg.controller;
|
||||
package com.czg.controller.pay;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
@@ -10,7 +10,7 @@ import com.czg.order.entity.OrderInfo;
|
||||
import com.czg.order.service.OrderInfoCustomService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.service.order.dto.OrderPayParamDTO;
|
||||
import com.czg.service.order.service.PayService;
|
||||
import com.czg.service.order.service.OrderPayService;
|
||||
import com.czg.system.service.SysParamsService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.ServletUtil;
|
||||
@@ -35,7 +35,7 @@ import java.util.Map;
|
||||
@RequestMapping("/pay")
|
||||
public class OrderPayController {
|
||||
@Resource
|
||||
private PayService payService;
|
||||
private OrderPayService orderPayService;
|
||||
@Resource
|
||||
private OrderInfoCustomService orderInfoCustomService;
|
||||
@Resource
|
||||
@@ -47,14 +47,14 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Object> creditPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.creditPayOrder(payParam);
|
||||
return orderPayService.creditPayOrder(payParam);
|
||||
}
|
||||
|
||||
@PostMapping("/cashPay")
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Object> cashPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.cashPayOrder(payParam);
|
||||
return orderPayService.cashPayOrder(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +66,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> rechargePayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.rechargePayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
return orderPayService.rechargePayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ public class OrderPayController {
|
||||
public CzgResult<Object> vipPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
AssertUtil.isBlank(payParam.getPayType(), "支付类型不可为空");
|
||||
return payService.vipPayOrder(payParam);
|
||||
return orderPayService.vipPayOrder(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> h5PayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.h5PayOrder(ServletUtil.getClientIP(request, ""), payParam);
|
||||
return orderPayService.h5PayOrder(ServletUtil.getClientIP(request, ""), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +106,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> jsPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.jsPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
return orderPayService.jsPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> ltPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.ltPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
return orderPayService.ltPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> scanPayOrder(@RequestHeader Long shopId, HttpServletRequest request, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
return orderPayService.scanPayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +139,7 @@ public class OrderPayController {
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> microPayOrder(@RequestHeader Long shopId, @Validated @RequestBody OrderPayParamDTO payParam) {
|
||||
payParam.setShopId(shopId);
|
||||
return payService.microPayOrder(payParam);
|
||||
return orderPayService.microPayOrder(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +174,7 @@ public class OrderPayController {
|
||||
@PostMapping("/shopPayApi/js2Pay")
|
||||
@Debounce(value = "#payParam.checkOrderPay.orderId")
|
||||
public CzgResult<Map<String, Object>> js2PayOrder(HttpServletRequest request, @RequestBody OrderPayParamDTO payParam) {
|
||||
return payService.js2PayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
return orderPayService.js2PayOrder(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.czg.controller;
|
||||
package com.czg.controller.pay;
|
||||
|
||||
import com.czg.annotation.Debounce;
|
||||
import com.czg.entity.resp.CzgBaseResp;
|
||||
@@ -7,6 +7,7 @@ import com.czg.service.order.dto.VipMemberPayParamDTO;
|
||||
import com.czg.service.order.dto.VipPayParamDTO;
|
||||
import com.czg.service.order.dto.VipRefundDTO;
|
||||
import com.czg.service.order.service.PayService;
|
||||
import com.czg.service.order.service.ShopUserPayService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.ServletUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -28,6 +29,8 @@ import java.util.Map;
|
||||
public class VipPayController {
|
||||
@Resource
|
||||
private PayService payService;
|
||||
@Resource
|
||||
private ShopUserPayService shopUserPayService;
|
||||
|
||||
/**
|
||||
* 现金充值
|
||||
@@ -39,7 +42,7 @@ public class VipPayController {
|
||||
public CzgResult<Object> cashPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.cashPayVip(payParam);
|
||||
return shopUserPayService.cashPayVip(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +55,7 @@ public class VipPayController {
|
||||
public CzgResult<Map<String, Object>> jsPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.jsPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
return shopUserPayService.jsPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +68,7 @@ public class VipPayController {
|
||||
public CzgResult<Map<String, Object>> ltPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.ltPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
return shopUserPayService.ltPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +84,7 @@ public class VipPayController {
|
||||
return CzgResult.failure("充值失败 未指定充值金额");
|
||||
}
|
||||
rechargeDTO.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.recharge(ServletUtil.getClientIP(request), rechargeDTO, rechargeDTO.getShopUserId());
|
||||
return shopUserPayService.recharge(ServletUtil.getClientIP(request), rechargeDTO, rechargeDTO.getShopUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +98,7 @@ public class VipPayController {
|
||||
public CzgResult<Map<String, Object>> ltPayMember(HttpServletRequest request, @Validated @RequestBody VipMemberPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "购买失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.ltPayMember(ServletUtil.getClientIP(request), payParam);
|
||||
return shopUserPayService.ltPayMember(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +111,7 @@ public class VipPayController {
|
||||
public CzgResult<Map<String, Object>> scanPayVip(HttpServletRequest request, @Validated @RequestBody VipPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
||||
return payService.scanPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
return shopUserPayService.scanPayVip(ServletUtil.getClientIP(request), payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +124,7 @@ public class VipPayController {
|
||||
public CzgResult<Map<String, Object>> microPayVip(@Validated @RequestBody VipPayParamDTO payParam) {
|
||||
AssertUtil.isNull(payParam.getShopUserId(), "充值失败 未指定店铺用户Id");
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(ServletUtil.getRequest(), "platformType"));
|
||||
return payService.microPayVip(payParam);
|
||||
return shopUserPayService.microPayVip(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +135,7 @@ public class VipPayController {
|
||||
@PostMapping("/refundVipBefore")
|
||||
@Debounce(value = "#payParam.flowId")
|
||||
public CzgResult<Map<String, BigDecimal>> refundVipBefore(@Validated @RequestBody VipRefundDTO payParam) {
|
||||
return payService.refundVipBefore(payParam);
|
||||
return shopUserPayService.refundVipBefore(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +158,7 @@ public class VipPayController {
|
||||
return CzgResult.failure("退款金额过大");
|
||||
}
|
||||
payParam.setPlatformType(ServletUtil.getHeaderIgnoreCase(request, "platformType"));
|
||||
return payService.refundVip(payParam);
|
||||
return shopUserPayService.refundVip(payParam);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.czg.mq;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.EntryManager;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.config.RabbitConstants;
|
||||
import com.czg.config.RedisCst;
|
||||
import com.czg.dto.resp.EntryRespDto;
|
||||
import com.czg.order.entity.ShopDirectMerchant;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.order.dto.AggregateMerchantVO;
|
||||
import com.czg.service.order.service.ShopDirectMerchantService;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.logging.log4j.ThreadContext;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 打印mq消息处理器
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class EntryManagerMqListener {
|
||||
@Resource
|
||||
private RedisService redisService;
|
||||
@Resource
|
||||
private ShopDirectMerchantService shopDirectMerchantService;
|
||||
|
||||
String key = RedisCst.SHOP_ENTRY;
|
||||
|
||||
@RabbitListener(
|
||||
bindings = @QueueBinding(
|
||||
value = @Queue(value = "${spring.profiles.active}-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER,
|
||||
durable = "true", exclusive = "false", autoDelete = "false"),
|
||||
exchange = @Exchange(value = "${spring.profiles.active}-" + RabbitConstants.Exchange.CASH_EXCHANGE),
|
||||
key = "${spring.profiles.active}-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER
|
||||
),
|
||||
concurrency = "5"
|
||||
)
|
||||
@RabbitHandler
|
||||
public void handle(Message message, Channel channel, String msg) throws IOException {
|
||||
String messageId = message.getMessageProperties().getMessageId();
|
||||
if (hasMessageId(messageId)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Long shopId = Long.valueOf(msg);
|
||||
// 将唯一标识添加到日志上下文
|
||||
ThreadContext.put("traceId", messageId);
|
||||
// 安全转换shopId
|
||||
if (shopId == null) {
|
||||
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
|
||||
return;
|
||||
}
|
||||
AggregateMerchantVO entry = shopDirectMerchantService.getEntry(Long.valueOf(msg));
|
||||
if (entry != null) {
|
||||
EntryManager.uploadParamImage(entry);
|
||||
List<String> platform = new ArrayList<>();
|
||||
if (PayCst.EntryStatus.WAIT.equals(entry.getAlipayStatus())) {
|
||||
platform.add(PayCst.Platform.ALIPAY);
|
||||
}
|
||||
if (PayCst.EntryStatus.WAIT.equals(entry.getWechatStatus())) {
|
||||
platform.add(PayCst.Platform.WECHAT);
|
||||
}
|
||||
EntryRespDto resp = EntryManager.entryMerchant(entry, platform.toArray(new String[0]));
|
||||
ShopDirectMerchant merchant = new ShopDirectMerchant();
|
||||
merchant.setShopId(entry.getShopId());
|
||||
|
||||
merchant.setWechatApplyId(resp.getWechatApplyId());
|
||||
merchant.setWechatStatus(resp.getWechatStatus());
|
||||
merchant.setWechatErrorMsg(resp.getWechatErrorMsg());
|
||||
|
||||
merchant.setAlipayOrderId(resp.getAlipayOrderId());
|
||||
merchant.setAlipayStatus(resp.getAlipayStatus());
|
||||
merchant.setAlipayErrorMsg(resp.getAlipayErrorMsg());
|
||||
shopDirectMerchantService.updateById(merchant);
|
||||
}
|
||||
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
|
||||
} catch (Exception e) {
|
||||
log.error("进件MQ对接业务异常shopId:{}", msg, e);
|
||||
ShopDirectMerchant merchant = new ShopDirectMerchant();
|
||||
merchant.setShopId(Long.valueOf(msg));
|
||||
merchant.setWechatStatus(PayCst.EntryStatus.REJECTED);
|
||||
merchant.setAlipayStatus(PayCst.EntryStatus.REJECTED);
|
||||
merchant.setErrorMsg("系统错误,请联系管理员后重试。");
|
||||
shopDirectMerchantService.updateById(merchant);
|
||||
|
||||
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
|
||||
} finally {
|
||||
delMessageId(messageId);
|
||||
// 清除日志上下文信息
|
||||
ThreadContext.remove("messageId");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMessageId(String messageId) {
|
||||
if (!redisService.hasKey(key)) {
|
||||
if (StrUtil.isNotBlank(messageId)) {
|
||||
redisService.leftPush(key, messageId);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
List<Object> list = redisService.lGet(key, 0, -1);
|
||||
if (!list.contains(messageId)) {
|
||||
redisService.leftPush(key, messageId);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void delMessageId(String messageId) {
|
||||
redisService.lRemove(key, 0, messageId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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})
|
||||
|
||||
@@ -6,13 +6,12 @@ import com.czg.config.RabbitConstants;
|
||||
import com.czg.config.RedisCst;
|
||||
import com.czg.order.entity.MqLog;
|
||||
import com.czg.order.service.MqLogService;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.order.print.PrinterHandler;
|
||||
import com.czg.service.order.utils.FunUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -28,19 +27,15 @@ public class PrintMqListener {
|
||||
@Resource
|
||||
private MqLogService mqLogService;
|
||||
@Resource
|
||||
private FunUtil funUtil;
|
||||
|
||||
// 注入自定义线程池(建议单独配置,避免使用默认线程池)
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor asyncExecutor;
|
||||
private RedisService redisService;
|
||||
@Lazy
|
||||
@Resource
|
||||
private PrinterHandler printerHandler;
|
||||
|
||||
private <T> void invokeFun(String type, String plat, T data, Consumer<T> consumer) {
|
||||
private <T> void invokeFun(String queue, String type, String plat, T data, Consumer<T> consumer) {
|
||||
long startTime = DateUtil.date().getTime();
|
||||
log.info("接收到{}打印消息:{}", type, data);
|
||||
MqLog mqLog = new MqLog().setQueue(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE).setMsg(data.toString())
|
||||
MqLog mqLog = new MqLog().setQueue(queue).setMsg(data.toString())
|
||||
.setType(type).setPlat(plat).setCreateTime(DateUtil.date().toLocalDateTime());
|
||||
try {
|
||||
consumer.accept(data);
|
||||
@@ -56,45 +51,18 @@ public class PrintMqListener {
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE})
|
||||
public void orderPrint(String req) {
|
||||
// 执行核心打印逻辑
|
||||
invokeFun("orderPrint", "java.order", req, (data) -> {
|
||||
invokeFun(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE, "orderPrint", "java.order", req, (data) -> {
|
||||
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
String orderId = jsonObject.getString("orderId");
|
||||
if (orderId == null) {
|
||||
throw new RuntimeException("订单打印失败,未传递orderId");
|
||||
}
|
||||
Boolean printOrder = jsonObject.getBoolean("printOrder");
|
||||
funUtil.runFunAndCheckKey(() -> {
|
||||
redisService.runFunAndCheckKey(() -> {
|
||||
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
||||
return null;
|
||||
}, RedisCst.getLockKey("orderPrint", orderId));
|
||||
});
|
||||
// // 使用异步线程池执行延迟任务,不阻塞当前消费者线程
|
||||
// CompletableFuture.runAsync(() -> {
|
||||
// try {
|
||||
// // 延迟3秒处理
|
||||
// TimeUnit.SECONDS.sleep(3);
|
||||
// // 执行核心打印逻辑
|
||||
// invokeFun("orderPrint", "java.order", req, (data) -> {
|
||||
// JSONObject jsonObject = JSONObject.parseObject(data);
|
||||
// String orderId = jsonObject.getString("orderId");
|
||||
// if (orderId == null) {
|
||||
// throw new RuntimeException("订单打印失败,未传递orderId");
|
||||
// }
|
||||
// Boolean printOrder = jsonObject.getBoolean("printOrder");
|
||||
// funUtil.runFunAndCheckKey(() -> {
|
||||
// printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
|
||||
// return null;
|
||||
// }, RedisCst.getLockKey("orderPrint", orderId));
|
||||
// });
|
||||
// } catch (InterruptedException e) {
|
||||
// Thread.currentThread().interrupt();
|
||||
// // 记录中断日志
|
||||
// log.warn("打印任务被中断,req:{}", req, e);
|
||||
// } catch (Exception e) {
|
||||
// // 记录业务异常日志
|
||||
// log.error("打印任务处理失败,req:{}", req, e);
|
||||
// }
|
||||
// }, asyncExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,14 +70,16 @@ public class PrintMqListener {
|
||||
*/
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE})
|
||||
public void handoverPrint(String id) {
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER));
|
||||
invokeFun(RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, "handoverPrint", "java.order", id, (data) ->
|
||||
printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER));
|
||||
}
|
||||
|
||||
/**
|
||||
* 交班打印
|
||||
* 叫号打印
|
||||
*/
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_PRINT_QUEUE})
|
||||
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_QUEUE})
|
||||
public void callTablePrint(String id) {
|
||||
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL));
|
||||
invokeFun(RabbitConstants.Queue.CALL_TABLE_QUEUE, "callTable", "java.order", id, (data) ->
|
||||
printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.czg.task;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.czg.EntryManager;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.account.entity.ShopInfo;
|
||||
import com.czg.account.service.ShopInfoService;
|
||||
import com.czg.dto.resp.QueryStatusResp;
|
||||
import com.czg.order.entity.ShopDirectMerchant;
|
||||
import com.czg.order.service.ShopOrderStatisticService;
|
||||
import com.czg.order.service.ShopProdStatisticService;
|
||||
import com.czg.order.service.ShopTableOrderStatisticService;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.service.order.service.ShopDirectMerchantService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 进件查询
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class EntryManagerTask {
|
||||
@Resource
|
||||
private ShopDirectMerchantService shopDirectMerchantService;
|
||||
@DubboReference
|
||||
private ShopInfoService shopInfoService;
|
||||
|
||||
//每10分钟查一次
|
||||
@Scheduled(cron = "0 0/10 * * * ? ")
|
||||
public void run() {
|
||||
log.info("进件查询,定时任务执行");
|
||||
long start = System.currentTimeMillis();
|
||||
entryManager(null);
|
||||
log.info("进件查询,定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询状态为待处理、待签约、待审核的进件
|
||||
*/
|
||||
public void entryManager(Long shopId) {
|
||||
List<ShopDirectMerchant> list = shopDirectMerchantService.list(QueryWrapper.create()
|
||||
.eq(ShopDirectMerchant::getShopId, shopId)
|
||||
.in(ShopDirectMerchant::getWechatStatus, PayCst.EntryStatus.NEED_QUERY_LIST)
|
||||
.or(ShopDirectMerchant::getAlipayStatus).in(PayCst.EntryStatus.NEED_QUERY_LIST));
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
for (ShopDirectMerchant shopDirectMerchant : list) {
|
||||
String wechatMerchantId = "";
|
||||
String alipayMerchantId = "";
|
||||
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getWechatStatus()) && StrUtil.isNotBlank(shopDirectMerchant.getWechatApplyId())) {
|
||||
QueryStatusResp wechatStatus = EntryManager.queryWechatEntryStatus(shopDirectMerchant.getWechatApplyId());
|
||||
shopDirectMerchant.setWechatStatus(wechatStatus.getStatus());
|
||||
shopDirectMerchant.setWechatErrorMsg(wechatStatus.getFailReason());
|
||||
shopDirectMerchant.setWechatSignUrl(wechatStatus.getSignUrl());
|
||||
if (PayCst.EntryStatus.FINISH.equals(wechatStatus.getStatus())) {
|
||||
wechatMerchantId = wechatStatus.getThirdMerchantId();
|
||||
}
|
||||
}
|
||||
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getAlipayStatus()) && StrUtil.isNotBlank(shopDirectMerchant.getAlipayOrderId())) {
|
||||
QueryStatusResp alipayStatus = EntryManager.queryAlipayEntryStatus(shopDirectMerchant.getAlipayOrderId());
|
||||
shopDirectMerchant.setAlipayStatus(alipayStatus.getStatus());
|
||||
shopDirectMerchant.setAlipayErrorMsg(alipayStatus.getFailReason());
|
||||
shopDirectMerchant.setAlipaySignUrl(alipayStatus.getSignUrl());
|
||||
if (PayCst.EntryStatus.FINISH.equals(alipayStatus.getStatus())) {
|
||||
alipayMerchantId = alipayStatus.getThirdMerchantId();
|
||||
}
|
||||
}
|
||||
shopDirectMerchantService.updateById(shopDirectMerchant);
|
||||
if (StrUtil.isNotBlank(wechatMerchantId) || StrUtil.isNotBlank(alipayMerchantId)) {
|
||||
shopInfoService.editEntry(shopDirectMerchant.getShopId(), wechatMerchantId, alipayMerchantId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单过期处理
|
||||
* 退款失败 补偿
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.util.URLUtil;
|
||||
import com.czg.log.annotation.OperationLog;
|
||||
import com.czg.product.dto.ConsStockFlowDTO;
|
||||
import com.czg.product.dto.OcrDTO;
|
||||
import com.czg.product.entity.MkOcrService;
|
||||
import com.czg.product.param.ConsCheckStockParam;
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.czg.product.param.ConsReportDamageParam;
|
||||
@@ -37,6 +38,8 @@ public class ConsStockFlowController {
|
||||
|
||||
@Resource
|
||||
private ConsStockFlowService consStockFlowService;
|
||||
@Resource
|
||||
private MkOcrService ocrService;
|
||||
|
||||
/**
|
||||
* 入库单识别
|
||||
@@ -46,17 +49,18 @@ public class ConsStockFlowController {
|
||||
URI uri = new URI(ocrDTO.getUrl());
|
||||
URL url = uri.toURL();
|
||||
InputStream stream = URLUtil.getStream(url);
|
||||
return CzgResult.success(consStockFlowService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream));
|
||||
return CzgResult.success(ocrService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream, "cons"));
|
||||
}
|
||||
|
||||
/**
|
||||
* ocr识别结果
|
||||
*
|
||||
* @param id ocrId
|
||||
* @return 识别结果
|
||||
*/
|
||||
@GetMapping("/ocrResult")
|
||||
public CzgResult<ConsInOutStockHeadParam> ocrResult(@RequestParam Long id) {
|
||||
return CzgResult.success(consStockFlowService.ocrDetail(id));
|
||||
return CzgResult.success(ocrService.ocrDetail(id));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 商品管理 - 商品列表
|
||||
* 管理端/商品管理 - 商品列表
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.product.service.MkOcrCountStickService;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* 拍照数签子
|
||||
* @author ww
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/stick")
|
||||
public class StickCountController {
|
||||
|
||||
@Resource
|
||||
private MkOcrCountStickService stickCountService;
|
||||
|
||||
/**
|
||||
* 文件上传并返回点数统计结果
|
||||
*
|
||||
* @param file 上传的图片文件
|
||||
* @return 点数统计结果
|
||||
*/
|
||||
@PostMapping("/count")
|
||||
public CzgResult<Integer> uploadAndCount(MultipartFile file) throws IOException {
|
||||
AssertUtil.isNull(file, "上传文件不能为空");
|
||||
// 9. 返回成功结果
|
||||
return CzgResult.success(stickCountService.getCountStick(file.getBytes(), file.getOriginalFilename()));
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import com.czg.product.vo.ShopProductSkuInfoVo;
|
||||
import com.czg.product.vo.ShopProductVo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.RedisService;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.validator.ValidatorUtil;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
@@ -24,7 +23,7 @@ import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 店铺商品
|
||||
* 用户端/店铺商品
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
@@ -34,7 +33,6 @@ import java.util.Map;
|
||||
@RequestMapping("/user/product")
|
||||
public class UProductController {
|
||||
private final UProductService uProductService;
|
||||
private final RedisService redisService;
|
||||
|
||||
/**
|
||||
* 小程序点餐-热销商品列表
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.czg.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.service.ProductService;
|
||||
import com.czg.product.service.UProductService;
|
||||
import com.czg.product.vo.ShopGroupProductVo;
|
||||
import com.czg.product.vo.ShopProductVo;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2025/12/24 13:36
|
||||
*/
|
||||
@SpringBootTest
|
||||
public class ProductTest {
|
||||
|
||||
@Resource
|
||||
private ProductService productService;
|
||||
|
||||
@Resource
|
||||
private UProductService uProductService;
|
||||
|
||||
@Test
|
||||
public void testGetById() {
|
||||
// ProductDTO product = productService.getProductById(169L);
|
||||
// System.out.println(JSONObject.toJSONString( product));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.czg.controller.admin;
|
||||
|
||||
import com.czg.BaseQueryParam;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.system.entity.SysBankInfo;
|
||||
import com.czg.system.entity.SysCategoryInfo;
|
||||
import com.czg.system.entity.SysRegion;
|
||||
import com.czg.system.service.SysBankInfoService;
|
||||
import com.czg.system.service.SysCategoryInfoService;
|
||||
import com.czg.system.service.SysRegionService;
|
||||
import com.czg.system.vo.SysCategoryInfoVO;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 通用
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/common")
|
||||
public class SysCommonController {
|
||||
@Resource
|
||||
private SysRegionService sysRegionService;
|
||||
@Resource
|
||||
private SysBankInfoService bankInfoService;
|
||||
@Resource
|
||||
private SysCategoryInfoService categoryInfoService;
|
||||
|
||||
/**
|
||||
* 获取所有地域
|
||||
*/
|
||||
@GetMapping("/region")
|
||||
public CzgResult<List<SysRegion>> region() {
|
||||
return CzgResult.success(sysRegionService.regionList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取银行信息
|
||||
*/
|
||||
@GetMapping("/bankInfo")
|
||||
public CzgResult<Page<SysBankInfo>> bankInfo(BaseQueryParam param, @RequestParam String bankName) {
|
||||
return CzgResult.success(bankInfoService.bankInfoList(param, bankName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 类目信息表
|
||||
*/
|
||||
@GetMapping("/category")
|
||||
public CzgResult<List<SysCategoryInfoVO>> category() {
|
||||
return CzgResult.success(categoryInfoService.categoryList());
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author GYJoker
|
||||
@@ -94,18 +96,19 @@ public class VersionController {
|
||||
@GetMapping(value = "/getCredentials")
|
||||
public CzgResult<Object> getCredentials() {
|
||||
try {
|
||||
Map<String, String> ossKeyMap = paramsService.getParamsByMap("ossKeySet", ParamCodeCst.OSS_KEY_SET);
|
||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
|
||||
.setAccessKeyId(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY))
|
||||
.setAccessKeyId(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY))
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
||||
.setAccessKeySecret(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET));
|
||||
.setAccessKeySecret(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET));
|
||||
|
||||
// Endpoint 请参考 https://api.aliyun.com/product/Sts
|
||||
config.endpoint = paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT);
|
||||
config.endpoint = ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT);
|
||||
|
||||
com.aliyun.sts20150401.Client client = new com.aliyun.sts20150401.Client(config);
|
||||
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest();
|
||||
assumeRoleRequest.setRoleArn(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN));
|
||||
assumeRoleRequest.setRoleArn(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN));
|
||||
assumeRoleRequest.setRoleSessionName("test");
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
|
||||
@@ -26,6 +26,7 @@ public class FilteredNacosRegistry extends NacosRegistry {
|
||||
"removeByMap",
|
||||
"getByIdOpt",
|
||||
"getOneOpt",
|
||||
"getOneAs",
|
||||
"getObjOpt",
|
||||
"getObjAs",
|
||||
"getObjAsOpt",
|
||||
|
||||
@@ -86,7 +86,6 @@ public class CzgControllerAdvice {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*/
|
||||
@@ -164,9 +163,20 @@ public class CzgControllerAdvice {
|
||||
@ExceptionHandler(value = Exception.class)
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
public CzgResult<Object> errorHandler(Exception ex) {
|
||||
// setErrorLog(ex);
|
||||
// 3. 处理未捕获的异常(系统异常,隐藏敏感信息)
|
||||
log.error("系统未处理异常", ex);
|
||||
Throwable rootCause = ex;
|
||||
while (rootCause.getCause() != null && !(rootCause instanceof CzgException)) {
|
||||
rootCause = rootCause.getCause();
|
||||
}
|
||||
|
||||
// 2. 如果根因是CzgException,直接抛出/返回该异常
|
||||
if (rootCause instanceof CzgException exception) {
|
||||
return CzgResult.failure(exception.getCode(), exception.getMsg());
|
||||
}else if (rootCause instanceof ValidateException exception) {
|
||||
return CzgResult.failure(exception.getStatus(), exception.getMessage());
|
||||
}
|
||||
|
||||
// 3. 非业务异常,按原有逻辑处理
|
||||
return CzgResult.failure(CzgRespCode.SYSTEM_ERROR.getCode(), "系统错误,请联系管理员");
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,24 @@ public class RabbitConfig {
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String activeProfile;
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DirectExchange directExchange() {
|
||||
return new DirectExchange(activeProfile + "-" + RabbitConstants.Exchange.CASH_EXCHANGE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------ 商家入驻
|
||||
@Bean
|
||||
public Queue entryManagerQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER, true, false, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding entryManagerExchange(Queue entryManagerQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(entryManagerQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER);
|
||||
}
|
||||
|
||||
//------------------------------------------------------订单打印队列
|
||||
@Bean
|
||||
public Queue orderPrintQueue() {
|
||||
@@ -36,6 +48,7 @@ public class RabbitConfig {
|
||||
args.put("x-message-ttl", 180000);
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_PRINT_QUEUE, true, false, false, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderPrintExchange(Queue orderPrintQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderPrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_PRINT_QUEUE);
|
||||
@@ -51,6 +64,7 @@ public class RabbitConfig {
|
||||
// args.put("x-message-ttl", 180000);
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE, true, false, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderMachinePrintExchange(Queue orderMachinePrintQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderMachinePrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE);
|
||||
@@ -61,6 +75,7 @@ public class RabbitConfig {
|
||||
public Queue handoverPrintQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, true, false, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingHandoverPrintExchange(Queue handoverPrintQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(handoverPrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE);
|
||||
@@ -69,11 +84,12 @@ public class RabbitConfig {
|
||||
//------------------------------------------------------叫号 打票
|
||||
@Bean
|
||||
public Queue callTablePrintQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_PRINT_QUEUE, true, false, false);
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_QUEUE, true, false, false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingCallTablePrintExchange(Queue callTablePrintQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(callTablePrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_PRINT_QUEUE);
|
||||
return BindingBuilder.bind(callTablePrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.CALL_TABLE_QUEUE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------订单取消
|
||||
@@ -81,9 +97,10 @@ public class RabbitConfig {
|
||||
public Queue orderCancelQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_CANCEL_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderCancelExchange(Queue orderPrintQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderPrintQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_CANCEL_QUEUE);
|
||||
public Binding bindingOrderCancelExchange(Queue orderCancelQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderCancelQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_CANCEL_QUEUE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------ 订单库存更新
|
||||
@@ -91,6 +108,7 @@ public class RabbitConfig {
|
||||
public Queue orderStockQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_STOCK_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderStockExchange(Queue orderStockQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderStockQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_STOCK_QUEUE);
|
||||
@@ -102,6 +120,7 @@ public class RabbitConfig {
|
||||
public Queue productInfoChangeQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.PRODUCT_INFO_CHANGE_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingProductInfoChange(Queue productInfoChangeQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(productInfoChangeQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.PRODUCT_INFO_CHANGE_QUEUE);
|
||||
@@ -112,6 +131,7 @@ public class RabbitConfig {
|
||||
public Queue orderRefundQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_REFUND_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderRefundExchange(Queue orderRefundQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderRefundQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_REFUND_QUEUE);
|
||||
@@ -119,6 +139,7 @@ public class RabbitConfig {
|
||||
|
||||
|
||||
//------------------------------------------------------ 申请短信模板队列
|
||||
|
||||
/**
|
||||
* 1,2,applySmsTemp 模版审核
|
||||
* 1,2,sendMarkSms 发送营销短信
|
||||
@@ -129,6 +150,7 @@ public class RabbitConfig {
|
||||
public Queue applySmsTemplateQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.APPLY_SMS_TEMPLATE_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingApplySmsTemplateExchange(Queue applySmsTemplateQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(applySmsTemplateQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.APPLY_SMS_TEMPLATE_QUEUE);
|
||||
@@ -139,6 +161,7 @@ public class RabbitConfig {
|
||||
public Queue birthdayGiftSmsQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.BIRTHDAY_GIFT_SMS_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingBirthdayGiftSmsExchange(Queue birthdayGiftSmsQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(birthdayGiftSmsQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.BIRTHDAY_GIFT_SMS_QUEUE);
|
||||
@@ -149,6 +172,7 @@ public class RabbitConfig {
|
||||
public Queue orderProductStatusQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_PRODUCT_STATUS_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderProductStatusExchange(Queue orderProductStatusQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderProductStatusQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_PRODUCT_STATUS_QUEUE);
|
||||
@@ -160,6 +184,7 @@ public class RabbitConfig {
|
||||
public Queue orderDetailStatusQueue() {
|
||||
return new Queue(activeProfile + "-" + RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE, true);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindingOrderDetailStatusExchange(Queue orderDetailStatusQueue, DirectExchange exchange) {
|
||||
return BindingBuilder.bind(orderDetailStatusQueue).to(exchange).with(activeProfile + "-" + RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE);
|
||||
|
||||
@@ -10,13 +10,14 @@ public interface RabbitConstants {
|
||||
}
|
||||
|
||||
class Queue {
|
||||
public static final String SHOP_ENTRY_MANAGER = "shop.entry.manager";
|
||||
public static final String ORDER_STOCK_QUEUE = "order.stock.queue";
|
||||
public static final String ORDER_REFUND_QUEUE = "order.refund.queue";
|
||||
public static final String ORDER_CANCEL_QUEUE = "order.cancel.queue";
|
||||
public static final String ORDER_PRINT_QUEUE = "order.print.queue";
|
||||
public static final String ORDER_MACHINE_PRINT_QUEUE = "order.machine.print.queue";
|
||||
public static final String ORDER_HANDOVER_PRINT_QUEUE = "order.handover.print.queue";
|
||||
public static final String CALL_TABLE_PRINT_QUEUE = "call.table.print.queue";
|
||||
public static final String CALL_TABLE_QUEUE = "call.table.print.queue";
|
||||
public static final String PRODUCT_INFO_CHANGE_QUEUE = "product.info.change.queue";
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,9 +130,17 @@ public class RabbitPublisher {
|
||||
sendMsg(RabbitConstants.Queue.ORDER_PRODUCT_STATUS_QUEUE, qrContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单商品状态消息
|
||||
*/
|
||||
public void sendEntryManagerMsg(String shopId) {
|
||||
sendMsg(RabbitConstants.Queue.SHOP_ENTRY_MANAGER, shopId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单商品状态消息
|
||||
* type bc 广播
|
||||
*/
|
||||
public void sendOrderDetailStatusMsg(String shopId, String type) {
|
||||
sendMsg(RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE, JSONObject.toJSONString(Map.of(
|
||||
|
||||
@@ -33,6 +33,8 @@ public interface RedisCst {
|
||||
public static final String EXPIRED_WECHAT = "expired:wechat:";
|
||||
}
|
||||
|
||||
//商家进件
|
||||
String SHOP_ENTRY = "shop:entry";
|
||||
|
||||
String SMS_CODE = "sms:code:";
|
||||
// 店铺会员动态支付码
|
||||
|
||||
@@ -280,5 +280,9 @@ public class ShopInfoEditDTO {
|
||||
* 上菜时间 分钟
|
||||
*/
|
||||
private Integer serveTime;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
private Integer isCountStick;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,5 +27,6 @@ public class ShopUserDTO extends ShopUser {
|
||||
private String memberLevelName;
|
||||
private String nextMemberLevelName;
|
||||
private Long nextExperience;
|
||||
private Long pointBalance;
|
||||
private boolean isNew;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@ public class ShopConfig implements Serializable {
|
||||
* 套餐推广 开关
|
||||
*/
|
||||
private Integer isPackagePromotion;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
private Integer isCountStick;
|
||||
|
||||
|
||||
private String dingAppKey;
|
||||
|
||||
@@ -142,6 +142,14 @@ public class ShopInfo implements Serializable {
|
||||
* -1 平台禁用 0-过期,1正式营业,
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 微信商户id
|
||||
*/
|
||||
private String wechatMerchantId;
|
||||
/**
|
||||
* 支付宝商户id
|
||||
*/
|
||||
private String alipayMerchantId;
|
||||
|
||||
/**
|
||||
* 到期时间
|
||||
@@ -352,6 +360,11 @@ public class ShopInfo implements Serializable {
|
||||
private Integer serveTime;
|
||||
@Column(ignore = true)
|
||||
private Integer isGroupBuy;
|
||||
/**
|
||||
* 数签子
|
||||
*/
|
||||
@Column(ignore = true)
|
||||
private Integer isCountStick;
|
||||
|
||||
/**
|
||||
* 运营端余额
|
||||
|
||||
@@ -37,6 +37,11 @@ public interface ShopInfoService extends IService<ShopInfo> {
|
||||
|
||||
Boolean edit(ShopInfoEditDTO shopInfoEditDTO);
|
||||
|
||||
/**
|
||||
* 进件结果保存
|
||||
*/
|
||||
Boolean editEntry(Long shopId, String wechatMerchantId, String alipayMerchantId);
|
||||
|
||||
ShopDetailDTO detail(Long id) throws CzgException;
|
||||
|
||||
ShopInfoByCodeDTO getByCode(String tableCode, String lat, String lng, boolean checkState);
|
||||
|
||||
@@ -11,5 +11,5 @@ public class PointsShopListVO {
|
||||
private String logo;
|
||||
private String coverImg;
|
||||
private Long shopId;
|
||||
private Integer accountPoints;
|
||||
private Integer pointBalance;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.czg.constants;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 系统参数编码常量类
|
||||
*
|
||||
@@ -9,6 +11,65 @@ package com.czg.constants;
|
||||
*/
|
||||
public interface ParamCodeCst {
|
||||
|
||||
/**
|
||||
* 用户小程序参数
|
||||
*/
|
||||
Set<String> USER_MINI_KEY_SET = Set.of(Wechat.Mini.USER_WX_APP_ID, Wechat.Mini.USER_WX_SECRETE);
|
||||
|
||||
/**
|
||||
* 商家小程序参数
|
||||
*/
|
||||
Set<String> SHOP_MINI_KEY_SET = Set.of(Wechat.Mini.SHOP_WX_APP_ID, Wechat.Mini.SHOP_WX_SECRETE);
|
||||
|
||||
/**
|
||||
* 商家公众号参数 推送 库存不足等消息
|
||||
*/
|
||||
Set<String> SHOP_AC_KEY_SET = Set.of(Wechat.Ac.SHOP_WX_AC_APP_ID, Wechat.Ac.SHOP_WX_AC_SECRETE);
|
||||
/**
|
||||
* 用户公众号参数 推送商家模板消息
|
||||
*/
|
||||
Set<String> USER_AC_KEY_SET = Set.of(Wechat.Ac.USER_WX_AC_APP_ID, Wechat.Ac.USER_WX_AC_SECRETE);
|
||||
|
||||
/**
|
||||
* 微信支付参数KEY
|
||||
*/
|
||||
Set<String> PAY_KEY_SET = Set.of(
|
||||
Wechat.Pay.WX_PUB_KEY,
|
||||
Wechat.Pay.WX_API_CLIENT_KEY,
|
||||
Wechat.Pay.WX_API_CLIENT_CERT,
|
||||
Wechat.Pay.WX_MCH_ID,
|
||||
Wechat.Pay.WX_V3_KEY,
|
||||
System.NATIVE_NOTIFY_URL
|
||||
);
|
||||
|
||||
/**
|
||||
* 支付宝参数KEY
|
||||
*/
|
||||
Set<String> ALI_PAY_KEY_SET = Set.of(
|
||||
Alipay.Web.ALI_GATEWAY,
|
||||
Alipay.Mini.ALI_MINI_APP_ID,
|
||||
Alipay.Mini.ALI_MINI_PRIVATE_KEY,
|
||||
Alipay.Mini.ALI_MINI_PUBLIC_KEY,
|
||||
Alipay.Web.ALI_ACCOUNT_APP_ID,
|
||||
Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY,
|
||||
Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY
|
||||
);
|
||||
|
||||
/**
|
||||
* 阿里云OSS参数KEY
|
||||
*/
|
||||
Set<String> ALI_OSS_KEY_SET = Set.of(
|
||||
ParamCodeCst.AliYun.ALI_SMS_KEY,
|
||||
ParamCodeCst.AliYun.ALI_SMS_SECRET,
|
||||
ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE
|
||||
);
|
||||
|
||||
/**
|
||||
* 阿里云临时凭证
|
||||
*/
|
||||
Set<String> OSS_KEY_SET = Set.of(AliYun.ALI_OSS_ACCESS_KEY, AliYun.ALI_OSS_ACCESS_SECRET, AliYun.ALI_OSS_ENDPOINT, AliYun.ALI_OSS_ROLE_ARN);
|
||||
|
||||
|
||||
/**
|
||||
* 系统通用配置项
|
||||
* <p>存放跨业务模块的通用系统配置</p>
|
||||
|
||||
@@ -21,6 +21,7 @@ public interface MkConsumeCashbackService extends IService<MkConsumeCashback> {
|
||||
|
||||
/**
|
||||
* 消费返现
|
||||
*
|
||||
* @param shopId 店铺id
|
||||
* @param userId 用户id
|
||||
* @param amount 金额
|
||||
@@ -28,4 +29,9 @@ public interface MkConsumeCashbackService extends IService<MkConsumeCashback> {
|
||||
* @param orderNo 订单号
|
||||
*/
|
||||
void cashback(Long shopId, Long userId, BigDecimal amount, Long orderId, String orderNo);
|
||||
|
||||
/**
|
||||
* 订单退款 删除返现
|
||||
*/
|
||||
void removeCashback(Long shopId, Long userId, Long orderId, String orderNo);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.czg.market.service;
|
||||
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
import com.czg.account.entity.UserInfo;
|
||||
import com.czg.constant.TableValueConstant;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.market.dto.MkDistributionUserDTO;
|
||||
import com.czg.market.dto.MkDistributionWithdrawFlowDTO;
|
||||
import com.czg.market.entity.MkDistributionConfig;
|
||||
@@ -57,7 +59,7 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
/**
|
||||
* 分销员中心-绑定邀请人
|
||||
*/
|
||||
void bindInviteUser(MkDistributionUserDTO param);
|
||||
void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException;
|
||||
|
||||
/**
|
||||
* 获取分销员分页列表
|
||||
@@ -85,6 +87,7 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
* 更新分销员
|
||||
*/
|
||||
void updateDistributionUserById(MkDistributionUserDTO param);
|
||||
|
||||
/**
|
||||
* 重置分销员等级
|
||||
*/
|
||||
@@ -100,7 +103,6 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
void deleteDistributionUser(Long id, Long shopId);
|
||||
|
||||
|
||||
|
||||
Boolean cashPayOrder(long adminId, MkDistributionPayDTO payParam);
|
||||
|
||||
/**
|
||||
@@ -141,6 +143,7 @@ public interface MkDistributionUserService extends IService<MkDistributionUser>
|
||||
|
||||
/**
|
||||
* 微信转账回调
|
||||
*
|
||||
* @param outBillNo 转账单号
|
||||
* @param state ACCEPTED:单据已受理
|
||||
* PROCESSING:单据处理中,转账结果尚未明确,如一直处于此状态,建议检查账户余额是否足够
|
||||
|
||||
@@ -17,4 +17,9 @@ public interface MkPointsConfigService extends IService<MkPointsConfig> {
|
||||
*
|
||||
*/
|
||||
void consumeAwardPoints(ShopUser shopUser, OrderInfo orderInfo);
|
||||
|
||||
/**
|
||||
* 订单退款成功,通过计算 给用户赠送积分
|
||||
*/
|
||||
void removeConsumeAwardPoints(Long shopId, Long userId, Long orderId, String orderNo);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.czg.market.service;
|
||||
|
||||
import com.czg.account.vo.PointsShopListVO;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.MkPointsUserRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会员积分变动记录 服务层。
|
||||
|
||||
@@ -48,4 +48,9 @@ public interface MkPointsUserService extends IService<MkPointsUser> {
|
||||
*/
|
||||
Long alterPoints(Long userId, Long shopUserId, @NotNull Long shopId, @NotNull PointsConstant floatType,
|
||||
@NotNull Integer points, Long sourceId, @NotBlank String reason);
|
||||
|
||||
/**
|
||||
* 订单退款 赠送的积分 扣除
|
||||
*/
|
||||
void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ public interface MkShopConsumerCouponService extends IService<MkShopConsumerCoup
|
||||
*/
|
||||
void receiveConsumerCoupon(Long shopId, Long orderId, BigDecimal orderAmount, Long userId, Long shopUserId);
|
||||
|
||||
/**
|
||||
* 订单退款 移除消费赠券
|
||||
*
|
||||
*/
|
||||
void removeConsumerCoupon(Long shopId, Long userId, Long orderId);
|
||||
|
||||
MkShopConsumerCouponDTO getConsumerCouponById(Long id);
|
||||
|
||||
void addConsumerCoupon(MkShopConsumerCouponDTO param);
|
||||
|
||||
@@ -22,13 +22,20 @@ import java.util.List;
|
||||
public interface MkShopRechargeService extends IService<MkShopRecharge> {
|
||||
|
||||
MkShopRechargeVO detail(Long shopId);
|
||||
|
||||
MkShopRechargeVO detailApp(Long shopId);
|
||||
|
||||
Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO);
|
||||
|
||||
BigDecimal checkRecharge(Long mainShopId, @NotNull(message = "店铺不能为空") Long shopId, Long userId, Long rechargeDetailId, @DecimalMin("0.01") BigDecimal money);
|
||||
|
||||
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum);
|
||||
/**
|
||||
* 充值
|
||||
* @param isNoJoin 是否没有执行 加入会员的方法
|
||||
* 会员如果是条件开通 则 需要统计
|
||||
*/
|
||||
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId,
|
||||
String payType, ShopUserFlowBizEnum bizEnum, boolean isNoJoin);
|
||||
|
||||
List<RechargeListVO> getList(long loginIdAsLong);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.PpHelpRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 套餐推广助力记录 服务层。
|
||||
*
|
||||
@@ -20,5 +22,7 @@ public interface PpHelpRecordService extends IService<PpHelpRecord> {
|
||||
|
||||
void removeHelpRecord(Long orderId);
|
||||
|
||||
void deleteByOrderIds(List<Long> orderIds);
|
||||
|
||||
Page<PpHelpRecordDTO> helpPage(PageQueryParam reqVo);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.czg.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 拼团参与 DTO
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class GroupJoinDTO extends LtPayOtherDTO{
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.czg.order.dto;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -13,6 +14,7 @@ import java.math.BigDecimal;
|
||||
* @author ww
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class LtPayOtherDTO {
|
||||
/**
|
||||
* 积分商品id/团购商品id
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.czg.order.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 积分商品兑换信息
|
||||
*
|
||||
* @author ww
|
||||
*/
|
||||
@Data
|
||||
public class PointGoodsExchangeDTO extends LtPayOtherDTO{
|
||||
/**
|
||||
* 积分商品id
|
||||
*/
|
||||
@NotNull(message = "积分商品不能为空")
|
||||
private Long pointsGoodsId;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.czg.order.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 商户进件 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-07
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("tb_shop_direct_merchant")
|
||||
public class ShopDirectMerchant implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 店铺id
|
||||
*/
|
||||
@Id
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 营业执照编号
|
||||
*/
|
||||
private String licenceNo;
|
||||
/**
|
||||
* 支付宝账号
|
||||
*/
|
||||
private String alipayAccount;
|
||||
|
||||
/**
|
||||
* 商户编号(在当前系统唯一)
|
||||
*/
|
||||
private String merchantCode;
|
||||
|
||||
/**
|
||||
* 商户基础信息
|
||||
*/
|
||||
private String merchantBaseInfo;
|
||||
|
||||
/**
|
||||
* 法人信息
|
||||
*/
|
||||
private String legalPersonInfo;
|
||||
|
||||
/**
|
||||
* 营业执照信息
|
||||
*/
|
||||
private String businessLicenceInfo;
|
||||
|
||||
/**
|
||||
* 门店信息
|
||||
*/
|
||||
private String storeInfo;
|
||||
|
||||
/**
|
||||
* 结算信息
|
||||
*/
|
||||
private String settlementInfo;
|
||||
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
|
||||
private String errorMsg;
|
||||
|
||||
private String wechatApplyId;
|
||||
/**
|
||||
* 微信状态
|
||||
*/
|
||||
private String wechatStatus;
|
||||
|
||||
/**
|
||||
* 微信进件错误信息
|
||||
*/
|
||||
private String wechatErrorMsg;
|
||||
/**
|
||||
* 微信进件签名地址
|
||||
*/
|
||||
private String wechatSignUrl;
|
||||
|
||||
private String alipayOrderId;
|
||||
|
||||
/**
|
||||
* 支付宝状态
|
||||
*/
|
||||
private String alipayStatus;
|
||||
|
||||
/**
|
||||
* 支付宝进件错误信息
|
||||
*/
|
||||
private String alipayErrorMsg;
|
||||
/**
|
||||
* 支付宝进件签名地址
|
||||
*/
|
||||
private String alipaySignUrl;
|
||||
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package com.czg.order.service;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.order.entity.OrderPayment;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 支付详情 服务层。
|
||||
*
|
||||
@@ -11,4 +13,5 @@ import com.czg.order.entity.OrderPayment;
|
||||
*/
|
||||
public interface OrderPaymentService extends IService<OrderPayment> {
|
||||
|
||||
BigDecimal countMemberInAmount(Long shopId, Long shopUserId);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package com.czg.product.dto;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.czg.product.vo.ProductGroupVo;
|
||||
import com.czg.validator.group.DefaultGroup;
|
||||
import com.czg.validator.group.InsertGroup;
|
||||
import com.czg.validator.group.UpdateGroup;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -235,6 +238,12 @@ public class ProductDTO implements Serializable {
|
||||
* 是否可售时间 1-是 0-否
|
||||
*/
|
||||
private Integer isSaleTime;
|
||||
/**
|
||||
* 相关推荐商品
|
||||
*/
|
||||
private List<RelatedProductDTO> relatedRecommendJson;
|
||||
@JsonIgnore
|
||||
private String relatedRecommend;
|
||||
|
||||
public Object getImages() {
|
||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||
@@ -250,4 +259,16 @@ public class ProductDTO implements Serializable {
|
||||
public Object getGroupSnap() {
|
||||
return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
|
||||
}
|
||||
|
||||
public String getRelatedRecommendStr() {
|
||||
if (CollUtil.isNotEmpty(relatedRecommendJson)) {
|
||||
JSONArray array = new JSONArray();
|
||||
for (RelatedProductDTO relatedProductDTO : relatedRecommendJson) {
|
||||
array.add(relatedProductDTO.getId());
|
||||
}
|
||||
return array.toJSONString();
|
||||
}
|
||||
|
||||
return "[]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.czg.product.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 相关推荐 商品 DTO
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2025/12/24 13:34
|
||||
*/
|
||||
@Data
|
||||
public class RelatedProductDTO implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商品 ID
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 商品图片
|
||||
*/
|
||||
private String coverImg;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.czg.product.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("mk_ocr_count_stick")
|
||||
public class MkOcrCountStick implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 渠道名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 标记
|
||||
*/
|
||||
private String mark;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 状态 0/1
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
private Integer sort;
|
||||
|
||||
private String token;
|
||||
private String account;
|
||||
private String pwd;
|
||||
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.czg.product.entity;
|
||||
|
||||
import com.czg.product.param.ConsInOutStockHeadParam;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.market.entity.MkOcr;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* ocr识别结果 服务层。
|
||||
*
|
||||
@@ -11,4 +14,7 @@ import com.czg.market.entity.MkOcr;
|
||||
*/
|
||||
public interface MkOcrService extends IService<MkOcr> {
|
||||
|
||||
ConsInOutStockHeadParam ocrDetail(Long id);
|
||||
|
||||
Integer ocr(String originalFilename, InputStream inputStream, String type);
|
||||
}
|
||||
|
||||
@@ -142,6 +142,10 @@ public class Product implements Serializable {
|
||||
* 退款是否退回库存
|
||||
*/
|
||||
private Integer isRefundStock;
|
||||
/**
|
||||
* 相关推荐
|
||||
*/
|
||||
private String relatedRecommend;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.czg.product.vo.ConsCheckStockRecordVo;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -25,7 +24,6 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
|
||||
* 手动入库
|
||||
*
|
||||
* @param param 手动出库入参
|
||||
* @return
|
||||
*/
|
||||
ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param);
|
||||
|
||||
@@ -78,8 +76,4 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
|
||||
* @param entity 库存变动记录实体
|
||||
*/
|
||||
void saveFlow(ConsStockFlow entity);
|
||||
|
||||
Integer ocr(String originalFilename, InputStream inputStream);
|
||||
|
||||
ConsInOutStockHeadParam ocrDetail(Long id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.czg.product.service;
|
||||
|
||||
import com.czg.product.entity.MkOcrCountStick;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
/**
|
||||
* 数签子的外链渠道 服务层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2025-12-24
|
||||
*/
|
||||
public interface MkOcrCountStickService extends IService<MkOcrCountStick> {
|
||||
|
||||
int getCountStick(byte[] stream, String fileName);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.czg.product.service;
|
||||
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.dto.RelatedProductDTO;
|
||||
import com.czg.product.entity.Product;
|
||||
import com.czg.product.entity.ProductStockFlow;
|
||||
import com.czg.product.param.*;
|
||||
|
||||
@@ -3,12 +3,14 @@ package com.czg.product.vo;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品规格详情
|
||||
@@ -109,6 +111,12 @@ public class ShopProductInfoVo implements Serializable {
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
private LocalTime endTime;
|
||||
/**
|
||||
* 相关推荐商品
|
||||
*/
|
||||
private List<ShopProductVo> relatedRecommendJson;
|
||||
@JsonIgnore
|
||||
private String relatedRecommend;
|
||||
|
||||
public Object getImages() {
|
||||
return JSON.parseArray(Convert.toStr(images, "[]"));
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.czg.system.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 银行账户信息表 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("sys_bank_info")
|
||||
public class SysBankInfo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private BigInteger id;
|
||||
|
||||
/**
|
||||
* 银行名称
|
||||
*/
|
||||
private String accountBank;
|
||||
|
||||
/**
|
||||
* 银行数字编码
|
||||
*/
|
||||
private Integer accountBankCode;
|
||||
|
||||
/**
|
||||
* 银行别名
|
||||
*/
|
||||
private String bankAlias;
|
||||
|
||||
/**
|
||||
* 银行别名编码
|
||||
*/
|
||||
private String bankAliasCode;
|
||||
|
||||
/**
|
||||
* 不知道干啥的
|
||||
*/
|
||||
private Boolean needBankBranch;
|
||||
|
||||
/**
|
||||
* 银行英文编码
|
||||
*/
|
||||
private String bankCode;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.czg.system.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 类目信息表 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("sys_category_info")
|
||||
public class SysCategoryInfo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Auto)
|
||||
private BigInteger id;
|
||||
|
||||
/**
|
||||
* 一级类目code
|
||||
*/
|
||||
private String firstCategoryCode;
|
||||
/**
|
||||
* 一级类目
|
||||
*/
|
||||
private String firstCategory;
|
||||
|
||||
/**
|
||||
* 二级类目code
|
||||
*/
|
||||
private String secondCategoryCode;
|
||||
|
||||
/**
|
||||
* 二级类目
|
||||
*/
|
||||
private String secondCategory;
|
||||
|
||||
/**
|
||||
* 适用商家说明
|
||||
*/
|
||||
private String applicableMerchant;
|
||||
|
||||
/**
|
||||
* 特殊资质(为空则无需提供)
|
||||
*/
|
||||
private String specialQualification;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()", onUpdateValue = "now()")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.czg.system.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 行政区表 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table("sys_region")
|
||||
public class SysRegion implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 区域编码
|
||||
*/
|
||||
@Id
|
||||
private String regionId;
|
||||
|
||||
/**
|
||||
* 上级区域编码
|
||||
*/
|
||||
private String parentRegionId;
|
||||
|
||||
/**
|
||||
* 区域级别:1=国家,2=省,3=市,4=县
|
||||
*/
|
||||
@Id
|
||||
private Integer regionLevel;
|
||||
|
||||
/**
|
||||
* 区域中文全称
|
||||
*/
|
||||
private String regionName;
|
||||
|
||||
/**
|
||||
* 区域拼音
|
||||
*/
|
||||
private String regionPinyin;
|
||||
|
||||
/**
|
||||
* 全级别名称(如“中国|北京|北京市|东城区)
|
||||
*/
|
||||
private String fullName;
|
||||
|
||||
/**
|
||||
* 子级区域
|
||||
*/
|
||||
@Column(ignore = true)
|
||||
private List<SysRegion> children;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.czg.system.service;
|
||||
|
||||
import com.czg.BaseQueryParam;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.system.entity.SysBankInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 银行账户信息表 服务层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
public interface SysBankInfoService extends IService<SysBankInfo> {
|
||||
|
||||
Page<SysBankInfo> bankInfoList(BaseQueryParam param, String bankName);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.czg.system.service;
|
||||
|
||||
import com.czg.system.vo.SysCategoryInfoVO;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.system.entity.SysCategoryInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 类目信息表 服务层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
public interface SysCategoryInfoService extends IService<SysCategoryInfo> {
|
||||
|
||||
|
||||
List<SysCategoryInfoVO> categoryList();
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.czg.system.service;
|
||||
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.resp.CzgResult;
|
||||
import com.czg.system.dto.SysParamsDTO;
|
||||
import com.czg.system.entity.SysParams;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 服务层。
|
||||
@@ -23,6 +26,7 @@ public interface SysParamsService extends IService<SysParams> {
|
||||
* @return 参数列表
|
||||
*/
|
||||
CzgResult<List<SysParamsDTO>> getParamsByType(Integer type);
|
||||
|
||||
/**
|
||||
* 新增参数
|
||||
*
|
||||
@@ -62,4 +66,13 @@ public interface SysParamsService extends IService<SysParams> {
|
||||
*/
|
||||
String getSysParamValue(String code);
|
||||
|
||||
|
||||
/**
|
||||
* 根据参数类型获取参数
|
||||
* dubbo 调用需要 显式抛出 异常类型
|
||||
*
|
||||
* @param type 参数类型
|
||||
* @param keyList 内容为 {@link com.czg.constants.ParamCodeCst}的Set集合
|
||||
*/
|
||||
Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.czg.system.service;
|
||||
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import com.czg.system.entity.SysRegion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 行政区表 服务层。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
public interface SysRegionService extends IService<SysRegion> {
|
||||
|
||||
List<SysRegion> regionList();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.czg.system.vo;
|
||||
|
||||
import com.czg.system.entity.SysCategoryInfo;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 类目信息表 实体类。
|
||||
*
|
||||
* @author ww
|
||||
* @since 2026-01-06
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SysCategoryInfoVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 一级类目
|
||||
*/
|
||||
private String firstCategory;
|
||||
|
||||
private List<SysCategoryInfo> child;
|
||||
}
|
||||
@@ -11,6 +11,8 @@ public enum ShopUserFlowBizEnum {
|
||||
// 会员充值
|
||||
CASH_IN("cashIn", "会员充值"),
|
||||
CASHBACK("cashback", "消费返现"),
|
||||
CASHBACK_REFUND("cashback_refund", "消费返现扣减"),
|
||||
|
||||
FREE_IN("freeIn", "霸王餐充值"),
|
||||
// 重置奖励
|
||||
AWARD_IN("awardIn", "充值奖励"),
|
||||
|
||||
@@ -16,9 +16,6 @@ import com.czg.exception.CzgException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -35,9 +32,8 @@ public class AliOcrUtil {
|
||||
/**
|
||||
* <b>description</b> :
|
||||
* <p>使用凭据初始化账号Client</p>
|
||||
* @return Client
|
||||
*
|
||||
* @throws Exception
|
||||
* @return Client
|
||||
*/
|
||||
public static com.aliyun.bailian20231229.Client createClient() {
|
||||
|
||||
@@ -56,7 +52,6 @@ public class AliOcrUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
|
||||
|
||||
String md5 = DigestUtil.md5Hex(bytes);
|
||||
@@ -118,7 +113,7 @@ public class AliOcrUtil {
|
||||
// 复制代码运行请自行打印 API 的返回值
|
||||
DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime);
|
||||
|
||||
log.info("file status: {}", describeFileResponse.getBody());
|
||||
log.info("file status: {}", describeFileResponse.getStatusCode());
|
||||
return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus());
|
||||
} catch (Exception error) {
|
||||
throw new RuntimeException(error);
|
||||
@@ -158,9 +153,9 @@ public class AliOcrUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String appCall(byte[] bytes, String fileName) {
|
||||
String id = null;
|
||||
//地址 https://bailian.console.aliyun.com
|
||||
public static String appCall(byte[] bytes, String fileName, String detail) {
|
||||
String id;
|
||||
try {
|
||||
id = getSessionId(bytes, fileName);
|
||||
} catch (Exception e) {
|
||||
@@ -169,7 +164,7 @@ public class AliOcrUtil {
|
||||
ApplicationParam param = ApplicationParam.builder()
|
||||
.apiKey("sk-2343af4413834ad1ab43b036e3a903de")
|
||||
.appId("cd612ac509a4499f8ac68a656532d4ae")
|
||||
.prompt("你是一名票据OCR结构化专家,请从我提供的票据图片中智能提取信息并只输出JSON,不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串,使用以下固定JSON结构:{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\",\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}],\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则:documentType对应单据类型/销售单/采购单/出货单;orderNumber对应单号/编号/No;date对应日期/开单日期;customerName对应客户名称/收货单位/供应商;operator对应业务员/经办人/制单人/操作员;items.conName对应品名/名称;items.spec对应规格/型号;items.unitName对应单位;items.inOutNumber对应数量;items.purchasePrice对应单价;items.subTotal对应金额/小计;totalAmount对应总金额/合计金额;remark对应备注。严禁生成图片中不存在的字段内容,看不清或未出现的字段必须为null,不允许推测或补全,不得生成多余字段;items只能根据识别到的行生成,不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。最终输出必须是纯JSON,不得包含任何非JSON字符。")
|
||||
.prompt(detail)
|
||||
.ragOptions(RagOptions.builder()
|
||||
.sessionFileIds(List.of(id))
|
||||
.build())
|
||||
@@ -187,11 +182,4 @@ public class AliOcrUtil {
|
||||
return result.getOutput().getText();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
|
||||
static void main() throws Exception {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.czg.utils;
|
||||
|
||||
import cn.hutool.core.lang.func.Func0;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author zs
|
||||
*/
|
||||
@Slf4j
|
||||
public class FunUtils {
|
||||
/**
|
||||
@@ -38,4 +42,31 @@ public class FunUtils {
|
||||
log.error(errorMsg, args, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void asyncSafeRunVoid(Runnable func, String... msg) {
|
||||
ThreadUtil.execAsync(() -> safeRunVoid(func, msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* 在事务提交后执行方法
|
||||
* 异步 执行
|
||||
*
|
||||
* @param func 方法
|
||||
*/
|
||||
public static void transactionSafeRun(Runnable func) {
|
||||
try {
|
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
safeRunVoid(func, "");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
safeRunVoid(func, "");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("方法执行失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,15 @@ public class PageUtil {
|
||||
return new Page<>(pageNum, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取空Page对象
|
||||
*/
|
||||
public <T> Page<T> emptyPage() {
|
||||
return Page.of(1,10,0) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 构造排序QueryWrapper
|
||||
* 从param体获取
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -5,26 +5,35 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>cash-service</artifactId>
|
||||
<artifactId>cash-sdk</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>pay-service</artifactId>
|
||||
<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.javen205</groupId>
|
||||
<artifactId>IJPay-All</artifactId>
|
||||
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||
<artifactId>wechatpay-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java-v3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>czg-pay</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>ocr_api20210707</artifactId>
|
||||
<version>3.1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
461
cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java
Normal file
461
cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java
Normal file
@@ -0,0 +1,461 @@
|
||||
package com.czg;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
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.dto.resp.EntryThirdRespDto;
|
||||
import com.czg.dto.resp.QueryStatusResp;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.AlipayEntryManager;
|
||||
import com.czg.third.alipay.AlipayIsvEntryManager;
|
||||
import com.czg.third.wechat.WechatEntryManager;
|
||||
import com.czg.utils.AssertUtil;
|
||||
import com.czg.utils.AsyncTaskExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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(null, instId, province, city);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询微信进件状态
|
||||
*
|
||||
* @param merchantCode 商户编号, 进件时返回的批次号 {@link EntryRespDto#wechatApplyId}
|
||||
* @return 进件状态
|
||||
*/
|
||||
public static QueryStatusResp queryWechatEntryStatus(String merchantCode) {
|
||||
return WechatEntryManager.queryMerchantEntryStatus(null, merchantCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付宝进件状态
|
||||
*
|
||||
* @param batchNo 商户编号, 进件时返回的批次号 {@link EntryRespDto#alipayOrderId}
|
||||
* @return 进件状态
|
||||
*/
|
||||
public static QueryStatusResp queryAlipayEntryStatus(String batchNo) {
|
||||
return AlipayIsvEntryManager.queryMerchantBatchStatus(null, batchNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 进件
|
||||
* 请先执行:
|
||||
* 1. {@link com.czg.EntryManager#verifyEntryParam(AggregateMerchantDto)} 验证进件参数
|
||||
* 2. {@link com.czg.EntryManager#uploadParamImage(AggregateMerchantDto)} 上传图片至第三方
|
||||
*
|
||||
* @param reqDto 进件参数
|
||||
* @param platform 平台 {@link com.czg.PayCst.Platform}
|
||||
*/
|
||||
public static EntryRespDto entryMerchant(AggregateMerchantDto reqDto, String... platform) {
|
||||
List<Supplier<EntryThirdRespDto>> tasks = new ArrayList<>();
|
||||
|
||||
if (platform == null || platform.length == 0) {
|
||||
platform = new String[]{PayCst.Platform.WECHAT, PayCst.Platform.ALIPAY};
|
||||
}
|
||||
|
||||
if (ArrayUtil.contains(platform, PayCst.Platform.WECHAT)) {
|
||||
tasks.add(() -> WechatEntryManager.entryMerchant(null, reqDto));
|
||||
}
|
||||
if (ArrayUtil.contains(platform, PayCst.Platform.ALIPAY)) {
|
||||
tasks.add(() -> AlipayIsvEntryManager.entryMerchant(null, reqDto));
|
||||
}
|
||||
|
||||
// 执行所有任务
|
||||
List<AsyncTaskExecutor.TaskResult<EntryThirdRespDto>> results = AsyncTaskExecutor.executeAll(tasks);
|
||||
|
||||
return getEntryRespDto(results);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static EntryRespDto getEntryRespDto(List<AsyncTaskExecutor.TaskResult<EntryThirdRespDto>> results) {
|
||||
EntryRespDto entryRespDto = new EntryRespDto();
|
||||
for (AsyncTaskExecutor.TaskResult<EntryThirdRespDto> result : results) {
|
||||
// 合并两个进件结果
|
||||
EntryThirdRespDto respDto = result.result();
|
||||
if (PayCst.Platform.WECHAT.equals(respDto.getPlatform())) {
|
||||
entryRespDto.setWechatApplyId(respDto.getEntryId());
|
||||
entryRespDto.setWechatStatus(respDto.getStatus());
|
||||
entryRespDto.setWechatErrorMsg(respDto.getErrorMsg());
|
||||
} else if (PayCst.Platform.ALIPAY.equals(respDto.getPlatform())) {
|
||||
entryRespDto.setAlipayOrderId(respDto.getEntryId());
|
||||
entryRespDto.setAlipayStatus(respDto.getStatus());
|
||||
entryRespDto.setAlipayErrorMsg(respDto.getErrorMsg());
|
||||
}
|
||||
}
|
||||
return 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.getMccCode(), "商户行业编码不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getAlipayAccount(), "支付宝账号不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPersonType(), "联系人类型不能为空");
|
||||
if (!PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType()) && !PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
|
||||
throw new CzgException("联系人类型错误");
|
||||
}
|
||||
if (PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType())) {
|
||||
AssertUtil.isBlank(baseInfo.getCertType(), "证件类型不能为空");
|
||||
if (!"0".equals(baseInfo.getCertType())) {
|
||||
throw new CzgException("证件类型错误");
|
||||
}
|
||||
AssertUtil.isBlank(baseInfo.getContactName(), "联系人姓名不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPersonId(), "联系人身份证号不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPhone(), "联系人电话不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactAddr(), "联系人地址不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactEmail(), "联系人邮箱不能为空");
|
||||
AssertUtil.isBlank(baseInfo.getContactPersonIdStartDate(), "联系人身份证开始日期不能为空");
|
||||
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.getLegalIdPersonStartDate(), "法人身份证开始日期不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonIdEndDate(), "法人身份证到期日期不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonPhone(), "法人电话不能为空");
|
||||
AssertUtil.isBlank(legalPersonInfo.getLegalPersonEmail(), "法人邮箱不能为空");
|
||||
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.getMercProvCode(), "门店省ID不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercCityCode(), "门店市ID不能为空");
|
||||
AssertUtil.isBlank(storeInfo.getMercAreaCode(), "门店区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.getBankName(), "结算银行名称不能为空");
|
||||
AssertUtil.isBlank(settlementInfo.getBankInstId(), "结算银行缩写不能为空");
|
||||
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 = getTestMerchantEntryData();
|
||||
|
||||
// verifyEntryParam(merchantDto);
|
||||
// uploadParamImage(merchantDto);
|
||||
|
||||
verifyEntryParam(merchantDto);
|
||||
// uploadParamImage(merchantDto);
|
||||
// System.out.println(merchantDto);
|
||||
// entryMerchant(merchantDto, PayCst.Platform.WECHAT);
|
||||
entryMerchant(merchantDto, PayCst.Platform.ALIPAY);
|
||||
// entryMerchant(merchantDto, PayCst.Platform.WECHAT, PayCst.Platform.ALIPAY);
|
||||
}
|
||||
|
||||
private static AggregateMerchantDto getTestMerchantEntryData() {
|
||||
AggregateMerchantDto merchantDto = new AggregateMerchantDto();
|
||||
merchantDto.setMerchantCode("20220106000000000001");
|
||||
|
||||
MerchantBaseInfoDto baseInfoDto = new MerchantBaseInfoDto();
|
||||
baseInfoDto.setUserType("1");
|
||||
baseInfoDto.setCompanyChildType("1");
|
||||
baseInfoDto.setShortName("测试商户");
|
||||
baseInfoDto.setAlipayAccount("1157756119@qq.com");
|
||||
baseInfoDto.setMccCode("A0001_B0001");
|
||||
baseInfoDto.setContactPersonType(PayCst.ContactPersonType.SUPER);
|
||||
baseInfoDto.setContactName("张三");
|
||||
baseInfoDto.setContactPersonId("110101199001011234");
|
||||
baseInfoDto.setContactPersonIdStartDate("2021-01-01");
|
||||
baseInfoDto.setContactPersonIdEndDate("2025-01-01");
|
||||
baseInfoDto.setContactPhone("13800000000");
|
||||
baseInfoDto.setContactEmail("1157756119@qq.com");
|
||||
baseInfoDto.setContactAddr("广东省深圳市南山区");
|
||||
baseInfoDto.setContactIdCardFrontPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
baseInfoDto.setContactIdCardBackPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
merchantDto.setMerchantBaseInfo(baseInfoDto);
|
||||
|
||||
BusinessLicenceInfoDto businessLicenceInfoDto = new BusinessLicenceInfoDto();
|
||||
businessLicenceInfoDto.setLicenceName("测试商户");
|
||||
businessLicenceInfoDto.setLicenceNo("110101199001011234");
|
||||
businessLicenceInfoDto.setLicenceStartDate("2021-01-01");
|
||||
businessLicenceInfoDto.setLicenceEndDate("2052-01-01");
|
||||
businessLicenceInfoDto.setRegisteredAddress("广东省深圳市南山区");
|
||||
businessLicenceInfoDto.setLicensePic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
merchantDto.setBusinessLicenceInfo(businessLicenceInfoDto);
|
||||
|
||||
LegalPersonInfoDto legalPersonInfoDto = new LegalPersonInfoDto();
|
||||
legalPersonInfoDto.setLegalPersonName("张三");
|
||||
legalPersonInfoDto.setLegalPersonId("110101199001011234");
|
||||
legalPersonInfoDto.setLegalIdPersonStartDate("2021-01-01");
|
||||
legalPersonInfoDto.setLegalPersonIdEndDate("2055-01-01");
|
||||
legalPersonInfoDto.setLegalPersonPhone("13800000000");
|
||||
legalPersonInfoDto.setLegalPersonEmail("1157756119@qq.com");
|
||||
legalPersonInfoDto.setLegalGender("1");
|
||||
legalPersonInfoDto.setLegalAddress("广东省深圳市南山区");
|
||||
legalPersonInfoDto.setIdCardHandPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
legalPersonInfoDto.setIdCardFrontPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
legalPersonInfoDto.setIdCardBackPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
merchantDto.setLegalPersonInfo(legalPersonInfoDto);
|
||||
|
||||
StoreInfoDto storeInfoDto = new StoreInfoDto();
|
||||
storeInfoDto.setMercProvCode("440000");
|
||||
storeInfoDto.setMercCityCode("440300");
|
||||
storeInfoDto.setMercAreaCode("440303");
|
||||
storeInfoDto.setMercProv("广东省");
|
||||
storeInfoDto.setMercCity("深圳市");
|
||||
storeInfoDto.setMercArea("南山区");
|
||||
storeInfoDto.setBusinessAddress("广东省深圳市南山区");
|
||||
storeInfoDto.setInsidePic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
storeInfoDto.setDoorPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
storeInfoDto.setCashierDeskPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
merchantDto.setStoreInfo(storeInfoDto);
|
||||
|
||||
SettlementInfoDto settlementInfoDto = new SettlementInfoDto();
|
||||
settlementInfoDto.setSettlementType("1");
|
||||
settlementInfoDto.setSettlementCardType("21");
|
||||
settlementInfoDto.setSettlementName("张三");
|
||||
settlementInfoDto.setSettlementCardNo("110101199001011234");
|
||||
settlementInfoDto.setBankMobile("13800000000");
|
||||
settlementInfoDto.setOpenAccProvinceId("440000");
|
||||
settlementInfoDto.setOpenAccCityId("440300");
|
||||
settlementInfoDto.setOpenAccAreaId("440303");
|
||||
settlementInfoDto.setOpenAccProvince("广东省");
|
||||
settlementInfoDto.setOpenAccCity("深圳市");
|
||||
settlementInfoDto.setOpenAccArea("南山区");
|
||||
settlementInfoDto.setBankName("中国工商银行");
|
||||
settlementInfoDto.setBankInstId("ICBC");
|
||||
settlementInfoDto.setBankType("1");
|
||||
settlementInfoDto.setBankBranchName("广东省深圳市南山区");
|
||||
settlementInfoDto.setBankBranchCode("440300");
|
||||
settlementInfoDto.setBankCardFrontPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
settlementInfoDto.setBankCardBackPic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
settlementInfoDto.setOpenAccountLicencePic(new ImageDto("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg"));
|
||||
merchantDto.setSettlementInfo(settlementInfoDto);
|
||||
|
||||
return merchantDto;
|
||||
}
|
||||
}
|
||||
68
cash-sdk/aggregation-pay/src/main/java/com/czg/OcrUtils.java
Normal file
68
cash-sdk/aggregation-pay/src/main/java/com/czg/OcrUtils.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.czg;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.aliyun.ocr_api20210707.models.RecognizeAllTextResponse;
|
||||
import com.aliyun.tea.*;
|
||||
import com.czg.exception.CzgException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author ww
|
||||
*/
|
||||
@Slf4j
|
||||
public class OcrUtils {
|
||||
/**
|
||||
* 阿里 ocr识别图片
|
||||
* 本接口支持:PNG、JPG、JPEG、BMP、GIF、TIFF、WebP、PDF。
|
||||
* 图片长宽需要大于 15 像素,小于 8192 像素。
|
||||
* 长宽比需要小于 50。长宽均大于 500px。
|
||||
* 图片二进制文件不能超过 10MB。
|
||||
* 图片过大会影响接口响应速度,建议使用小于 1.5M 图片进行识别,
|
||||
*
|
||||
* @param url 图片地址
|
||||
* @param type IdCard 身份证
|
||||
* BankCard 银行卡
|
||||
* BusinessLicense 营业执照
|
||||
* 目前使用的角色为 czg-oss@1413456038175003.onaliyun.com
|
||||
* 需要 AliyunOCRFullAccess 权限
|
||||
* AliyunBSSContractFullAccess 权限
|
||||
* 文档地址 <a href="https://help.aliyun.com/zh/ocr/developer-reference/api-ocr-api-2021-07-07-recognizealltext?spm=a2c4g.11186623.0.0.543669f32I79Gw#api-detail-35">
|
||||
*/
|
||||
public static JSONObject getInfoByImg(String accessKeyId, String accessKeySecret,
|
||||
String url, String type) throws Exception {
|
||||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
|
||||
.setAccessKeyId(accessKeyId)
|
||||
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
|
||||
.setAccessKeySecret(accessKeySecret);
|
||||
config.endpoint = "ocr-api.cn-hangzhou.aliyuncs.com";
|
||||
|
||||
com.aliyun.ocr_api20210707.Client client = new com.aliyun.ocr_api20210707.Client(config);
|
||||
com.aliyun.ocr_api20210707.models.RecognizeAllTextRequest recognizeAllTextRequest = new com.aliyun.ocr_api20210707.models.RecognizeAllTextRequest()
|
||||
.setUrl(url).setType(type);
|
||||
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
|
||||
try {
|
||||
RecognizeAllTextResponse resp = client.recognizeAllTextWithOptions(recognizeAllTextRequest, runtime);
|
||||
return JSONObject.from(resp.body.data);
|
||||
} catch (TeaException error) {
|
||||
// // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||
// // 错误 message
|
||||
// System.out.println(error.getMessage());
|
||||
// // 诊断地址
|
||||
// System.out.println(error.getData().get("Recommend"));
|
||||
// com.aliyun.teautil.Common.assertAsString(error.message);
|
||||
log.error("识别失败, msg: {}", error.getMessage());
|
||||
throw new CzgException(error.getMessage());
|
||||
} catch (Exception error) {
|
||||
// TeaException error = new TeaException(_error.getMessage(), _error);
|
||||
// // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||
// // 错误 message
|
||||
// System.out.println(error.getMessage());
|
||||
// // 诊断地址
|
||||
// System.out.println(error.getData().get("Recommend"));
|
||||
// com.aliyun.teautil.Common.assertAsString(error.message);
|
||||
log.error("识别失败, msg: {}", error.getMessage());
|
||||
throw new CzgException(error.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
87
cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java
Normal file
87
cash-sdk/aggregation-pay/src/main/java/com/czg/PayCst.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package com.czg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 支付相关常量
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/7 09:20
|
||||
*/
|
||||
public interface PayCst {
|
||||
|
||||
/**
|
||||
* 长期有效时间
|
||||
*/
|
||||
String LONG_TERM_DATE = "2099-12-31";
|
||||
|
||||
/**
|
||||
* 平台
|
||||
*/
|
||||
class Platform {
|
||||
/**
|
||||
* 微信
|
||||
*/
|
||||
public static final String WECHAT = "wechat";
|
||||
/**
|
||||
* 支付宝
|
||||
*/
|
||||
public static final String ALIPAY = "alipay";
|
||||
}
|
||||
|
||||
/**
|
||||
* 进件状态
|
||||
*/
|
||||
class EntryStatus {
|
||||
/**
|
||||
* 待提交
|
||||
*/
|
||||
public static final String WAIT = "WAIT";
|
||||
|
||||
/**
|
||||
* 待处理
|
||||
*/
|
||||
public static final String INIT = "INIT";
|
||||
/**
|
||||
* 审核中
|
||||
*/
|
||||
public static final String AUDIT = "AUDIT";
|
||||
|
||||
/**
|
||||
* 待签约
|
||||
*/
|
||||
public static final String SIGN = "SIGN";
|
||||
|
||||
/**
|
||||
* 已完成
|
||||
*/
|
||||
public static final String FINISH = "FINISH";
|
||||
|
||||
/**
|
||||
* 失败
|
||||
*/
|
||||
public static final String REJECTED = "REJECTED";
|
||||
|
||||
|
||||
/**
|
||||
* 需要查询的状态列表
|
||||
* 待处理、待签约、待审核的进件
|
||||
*/
|
||||
public static final List<String> NEED_QUERY_LIST = List.of(INIT, AUDIT, SIGN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 联系人类型
|
||||
*/
|
||||
class ContactPersonType {
|
||||
/**
|
||||
* 法人
|
||||
*/
|
||||
public static final String LEGAL = "LEGAL";
|
||||
|
||||
/**
|
||||
* 经办人
|
||||
*/
|
||||
public static final String SUPER = "SUPER";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 统一进件
|
||||
*
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 10:02
|
||||
*/
|
||||
@Data
|
||||
public class AggregateMerchantDto {
|
||||
/**
|
||||
* 商户Id
|
||||
*/
|
||||
private Long shopId;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 自己生成 CZGyyyy-MM-dd HH:mm:ss.SSS
|
||||
* 商户编号(在当前系统唯一)
|
||||
*/
|
||||
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,34 @@
|
||||
package com.czg.dto.req;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/6 16:53
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ImageDto {
|
||||
|
||||
/**
|
||||
* 图片 url
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 微信 图片 mediaId
|
||||
*/
|
||||
private String wechatId;
|
||||
|
||||
/**
|
||||
* 支付宝 图片 mediaId
|
||||
*/
|
||||
private String alipayId;
|
||||
|
||||
public ImageDto() {}
|
||||
|
||||
public ImageDto(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
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 legalIdPersonStartDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人身份证到期日期
|
||||
*/
|
||||
private String legalPersonIdEndDate;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人电话
|
||||
*/
|
||||
private String legalPersonPhone;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人邮箱
|
||||
*/
|
||||
private String legalPersonEmail;
|
||||
|
||||
/**
|
||||
* 法人性别(0男 1女)
|
||||
*/
|
||||
private String legalGender;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 法人地址
|
||||
*/
|
||||
private String legalAddress;
|
||||
|
||||
/**
|
||||
* 身份证手持 图片
|
||||
*/
|
||||
private ImageDto idCardHandPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证正面
|
||||
*/
|
||||
private ImageDto idCardFrontPic;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 身份证反面
|
||||
*/
|
||||
private ImageDto idCardBackPic;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 行业编码
|
||||
* 一级类目code_二级类目code
|
||||
* 【示例值】A0001_B0199
|
||||
*/
|
||||
private String mccCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 支付宝账号
|
||||
*/
|
||||
private String alipayAccount;
|
||||
|
||||
/**
|
||||
* 联系人类型
|
||||
* LEGAL: 经营者/法定代表人
|
||||
* SUPER: 经办人
|
||||
*/
|
||||
private String contactPersonType = "LEGAL";
|
||||
|
||||
/**
|
||||
* 联系人姓名
|
||||
*/
|
||||
private String contactName;
|
||||
|
||||
/**
|
||||
* 证件类型
|
||||
* 目前只支持身份证 传值:0
|
||||
*/
|
||||
private String certType = "0";
|
||||
|
||||
/**
|
||||
* 联系人身份证号
|
||||
*/
|
||||
private String contactPersonId;
|
||||
|
||||
/**
|
||||
* 联系人身份证开始日期
|
||||
*/
|
||||
private String contactPersonIdStartDate;
|
||||
|
||||
/**
|
||||
* 联系人身份证到期日期
|
||||
*/
|
||||
private String contactPersonIdEndDate;
|
||||
|
||||
/**
|
||||
* 联系人身份证背面
|
||||
*/
|
||||
private ImageDto contactIdCardBackPic;
|
||||
|
||||
/**
|
||||
* 联系人身份证正面
|
||||
*/
|
||||
private ImageDto contactIdCardFrontPic;
|
||||
|
||||
/**
|
||||
* 联系人电话
|
||||
*/
|
||||
private String contactPhone;
|
||||
|
||||
/**
|
||||
* 联系人通讯地址
|
||||
*/
|
||||
private String contactAddr;
|
||||
|
||||
/**
|
||||
* 联系人邮箱
|
||||
*/
|
||||
private String contactEmail;
|
||||
|
||||
/**
|
||||
* 企业类型,1:普通企业,2:事业单位,3:政府机关,4:社会组织
|
||||
*/
|
||||
private String companyChildType = "1";
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
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 bankInstId;
|
||||
|
||||
/**
|
||||
* 开户行编号
|
||||
*/
|
||||
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 {
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属省Code
|
||||
*/
|
||||
private String mercProvCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属市Code
|
||||
*/
|
||||
private String mercCityCode;
|
||||
|
||||
/**
|
||||
* 【必填】
|
||||
* 商户归属区Code
|
||||
*/
|
||||
private String mercAreaCode;
|
||||
|
||||
/**
|
||||
* 商户归属省
|
||||
*/
|
||||
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,46 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 微信状态
|
||||
* {@link com.czg.PayCst.EntryStatus}
|
||||
*/
|
||||
private String wechatStatus;
|
||||
|
||||
/**
|
||||
* 微信进件错误信息
|
||||
*/
|
||||
private String wechatErrorMsg;
|
||||
|
||||
/**
|
||||
* 支付宝订单 Id
|
||||
*/
|
||||
private String alipayOrderId;
|
||||
|
||||
/**
|
||||
* 支付宝状态
|
||||
* {@link com.czg.PayCst.EntryStatus}
|
||||
*/
|
||||
private String alipayStatus;
|
||||
|
||||
/**
|
||||
* 支付宝进件错误信息
|
||||
*/
|
||||
private String alipayErrorMsg;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.czg.dto.resp;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @author yjjie
|
||||
* @date 2026/1/7 09:07
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class EntryThirdRespDto {
|
||||
|
||||
/**
|
||||
* 录入id
|
||||
*/
|
||||
private String entryId;
|
||||
|
||||
/**
|
||||
* 平台
|
||||
*/
|
||||
private String platform;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* {@link com.czg.PayCst.EntryStatus}
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errorMsg;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.czg.dto.resp;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 查询进件状态
|
||||
* @author yjjie
|
||||
* @date 2026/1/7 17:12
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class QueryStatusResp {
|
||||
|
||||
/**
|
||||
* 平台
|
||||
* {@link com.czg.PayCst.Platform}
|
||||
*/
|
||||
private String platform;
|
||||
|
||||
/**
|
||||
* 商户编号
|
||||
*/
|
||||
private String merchantCode;
|
||||
|
||||
/**
|
||||
* 进件编号
|
||||
*/
|
||||
private String applyId;
|
||||
|
||||
/**
|
||||
* 三方商户id
|
||||
*/
|
||||
private String thirdMerchantId;
|
||||
|
||||
/**
|
||||
* 进件状态
|
||||
* {@link com.czg.PayCst.EntryStatus}
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 签约地址
|
||||
*/
|
||||
private String signUrl;
|
||||
|
||||
/**
|
||||
* 失败原因
|
||||
*/
|
||||
private String failReason;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
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 void setApiClient(AlipayConfigDto configDto) {
|
||||
if (configDto == null) {
|
||||
configDto = AlipayConfigDto.getDefaultConfig();
|
||||
}
|
||||
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);
|
||||
} catch (Exception e) {
|
||||
log.error("创建支付宝客户端失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
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,385 @@
|
||||
package com.czg.third.alipay;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.FileItem;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.AlipayFinancialnetAuthPbcnameQueryRequest;
|
||||
import com.alipay.api.request.AntMerchantExpandIndirectImageUploadRequest;
|
||||
import com.alipay.api.request.AntMerchantExpandIndirectZftCreateRequest;
|
||||
import com.alipay.api.request.AntMerchantExpandIndirectZftorderQueryRequest;
|
||||
import com.alipay.api.response.AlipayFinancialnetAuthPbcnameQueryResponse;
|
||||
import com.alipay.api.response.AntMerchantExpandIndirectImageUploadResponse;
|
||||
import com.alipay.api.response.AntMerchantExpandIndirectZftCreateResponse;
|
||||
import com.alipay.api.response.AntMerchantExpandIndirectZftorderQueryResponse;
|
||||
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.model.AlipayOpenAgentCreateDefaultResponse;
|
||||
import com.alipay.v3.model.AlipayOpenAgentCreateModel;
|
||||
import com.alipay.v3.model.AlipayOpenAgentCreateResponseModel;
|
||||
import com.alipay.v3.model.ContactModel;
|
||||
import com.alipay.v3.util.model.AlipayConfig;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.dto.req.*;
|
||||
import com.czg.dto.resp.BankBranchDto;
|
||||
import com.czg.dto.resp.EntryThirdRespDto;
|
||||
import com.czg.dto.resp.QueryStatusResp;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
||||
import com.czg.third.wechat.dto.resp.WechatQueryStateResp;
|
||||
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 merchantCode 自系统的商户编号
|
||||
* @return 进件状态
|
||||
*/
|
||||
public static QueryStatusResp queryMerchantEntryStatus(AlipayConfigDto configDto, String merchantCode) {
|
||||
QueryStatusResp queryStatusResp = new QueryStatusResp();
|
||||
queryStatusResp.setPlatform(PayCst.Platform.ALIPAY);
|
||||
queryStatusResp.setMerchantCode(merchantCode);
|
||||
|
||||
AntMerchantExpandIndirectZftorderQueryRequest request = new AntMerchantExpandIndirectZftorderQueryRequest();
|
||||
|
||||
AntMerchantExpandIndirectZftorderQueryModel model = new AntMerchantExpandIndirectZftorderQueryModel();
|
||||
model.setExternalId(merchantCode);
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
try {
|
||||
DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(configDto);
|
||||
AntMerchantExpandIndirectZftorderQueryResponse response = defaultAlipayClient.execute(request);
|
||||
log.info("支付宝查询进件状态结果:{}", response.getBody());
|
||||
|
||||
if (response.isSuccess()) {
|
||||
List<ZftSubMerchantOrder> orders = response.getOrders();
|
||||
if (orders != null && !orders.isEmpty()) {
|
||||
ZftSubMerchantOrder first = orders.getFirst();
|
||||
queryStatusResp.setApplyId(first.getExternalId());
|
||||
|
||||
if ("99".equals(first.getStatus())) {
|
||||
// 已完成
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.FINISH);
|
||||
queryStatusResp.setThirdMerchantId(first.getSmid());
|
||||
queryStatusResp.setFailReason("");
|
||||
return queryStatusResp;
|
||||
}
|
||||
if ("-1".equals(first.getStatus())) {
|
||||
// 拒绝
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
queryStatusResp.setFailReason(first.getReason());
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(first.getFkAudit())) {
|
||||
if ("REJECT".equals(first.getFkAudit())) {
|
||||
// 风控拒绝
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
queryStatusResp.setFailReason(first.getFkAuditMemo());
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
if ("CREATE".equals(first.getFkAudit())) {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.AUDIT);
|
||||
queryStatusResp.setFailReason(first.getFkAuditMemo());
|
||||
return queryStatusResp;
|
||||
}
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(first.getKzAudit())) {
|
||||
if ("REJECT".equals(first.getKzAudit())) {
|
||||
// 风控拒绝
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
queryStatusResp.setFailReason(first.getKzAuditMemo());
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
if ("CREATE".equals(first.getKzAudit())) {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.AUDIT);
|
||||
queryStatusResp.setFailReason(first.getKzAuditMemo());
|
||||
return queryStatusResp;
|
||||
}
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(first.getSubConfirm()) && "FAIL".equals(first.getSubConfirm())) {
|
||||
// 签约失败
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
queryStatusResp.setFailReason("签约失败");
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.SIGN);
|
||||
queryStatusResp.setSignUrl(first.getSubSignQrCodeUrl());
|
||||
return queryStatusResp;
|
||||
}
|
||||
} else {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
queryStatusResp.setFailReason(response.getSubMsg());
|
||||
}
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("支付宝查询进件状态报错:{}", e.getMessage(), e);
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.INIT);
|
||||
}
|
||||
|
||||
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 进件商户
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param reqDto 请求信息
|
||||
*/
|
||||
public static EntryThirdRespDto entryMerchant(AlipayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
AntMerchantExpandIndirectZftCreateModel entryReqDto = buildEntryParams(reqDto);
|
||||
EntryThirdRespDto respDto = new EntryThirdRespDto()
|
||||
.setPlatform(PayCst.Platform.ALIPAY);
|
||||
|
||||
try {
|
||||
AntMerchantExpandIndirectZftCreateRequest request = new AntMerchantExpandIndirectZftCreateRequest();
|
||||
DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(configDto);
|
||||
request.setBizModel(entryReqDto);
|
||||
AntMerchantExpandIndirectZftCreateResponse response = defaultAlipayClient.execute(request);
|
||||
log.info("支付宝进件结果:{}", response.getBody());
|
||||
if (response.isSuccess()) {
|
||||
respDto.setStatus(PayCst.EntryStatus.INIT);
|
||||
respDto.setEntryId(response.getOrderId());
|
||||
respDto.setErrorMsg("");
|
||||
} else {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setEntryId("");
|
||||
respDto.setErrorMsg(response.getSubMsg());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝进件报错:{}", e.getMessage(), e);
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setEntryId("");
|
||||
respDto.setErrorMsg(e.getMessage());
|
||||
}
|
||||
|
||||
return respDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param url 图片地址
|
||||
* @return 图片ID
|
||||
*/
|
||||
public static String uploadImage(AlipayConfigDto configDto, String url) {
|
||||
try {
|
||||
byte[] bytes = UploadFileUtil.downloadImage(url);
|
||||
|
||||
Path tempFile = Files.createTempFile("image_", ".png");
|
||||
|
||||
// 写入数据
|
||||
Files.write(tempFile, bytes);
|
||||
|
||||
File file = tempFile.toFile();
|
||||
|
||||
AntMerchantExpandIndirectImageUploadRequest request = new AntMerchantExpandIndirectImageUploadRequest();
|
||||
request.setImageType(UploadFileUtil.extractImageExtension(url));
|
||||
|
||||
// 设置图片内容
|
||||
FileItem imageContent = new FileItem(file);
|
||||
request.setImageContent(imageContent);
|
||||
|
||||
DefaultAlipayClient defaultAlipayClient = AlipayClient.getDefaultClient(configDto);
|
||||
AntMerchantExpandIndirectImageUploadResponse response = defaultAlipayClient.execute(request);
|
||||
|
||||
return response.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(AlipayConfigDto configDto, 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(configDto);
|
||||
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<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建进件参数
|
||||
*
|
||||
* @param reqDto 请求参数
|
||||
* @return 进件参数
|
||||
*/
|
||||
private static AntMerchantExpandIndirectZftCreateModel buildEntryParams(AggregateMerchantDto reqDto) {
|
||||
AntMerchantExpandIndirectZftCreateModel entryParams = new AntMerchantExpandIndirectZftCreateModel();
|
||||
|
||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
BusinessLicenceInfoDto businessLicenceInfo = reqDto.getBusinessLicenceInfo();
|
||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
||||
SettlementInfoDto settlementInfo = reqDto.getSettlementInfo();
|
||||
|
||||
entryParams.setExternalId(reqDto.getMerchantCode());
|
||||
if ("0".equals(baseInfo.getUserType())) {
|
||||
entryParams.setMerchantType("07");
|
||||
} else if ("1".equals(baseInfo.getUserType())) {
|
||||
switch (baseInfo.getCompanyChildType()) {
|
||||
case "1" -> entryParams.setMerchantType("01");
|
||||
case "2" -> entryParams.setMerchantType("02");
|
||||
case "3" -> entryParams.setMerchantType("05");
|
||||
case "4" -> entryParams.setMerchantType("04");
|
||||
default -> throw new CzgException("主体类型错误");
|
||||
}
|
||||
} else {
|
||||
throw new CzgException("用户类型错误");
|
||||
}
|
||||
entryParams.setName(businessLicenceInfo.getLicenceName());
|
||||
entryParams.setAliasName(baseInfo.getShortName());
|
||||
entryParams.setMcc(baseInfo.getMccCode());
|
||||
entryParams.setService(List.of("当面付", "jsapi支付", "小程序支付"));
|
||||
entryParams.setInDoorImages(List.of(storeInfo.getInsidePic().getAlipayId(), storeInfo.getCashierDeskPic().getAlipayId()));
|
||||
entryParams.setOutDoorImages(List.of(storeInfo.getDoorPic().getAlipayId()));
|
||||
|
||||
// 证件类型(目前只支持个体和企业,所以都是营业执照)
|
||||
entryParams.setCertType("201");
|
||||
entryParams.setCertImage(businessLicenceInfo.getLicensePic().getAlipayId());
|
||||
entryParams.setCertNo(businessLicenceInfo.getLicenceNo());
|
||||
|
||||
entryParams.setLegalName(legalPersonInfo.getLegalPersonName());
|
||||
entryParams.setLegalCertNo(legalPersonInfo.getLegalPersonId());
|
||||
entryParams.setLegalCertFrontImage(legalPersonInfo.getIdCardFrontPic().getAlipayId());
|
||||
entryParams.setLegalCertBackImage(legalPersonInfo.getIdCardBackPic().getAlipayId());
|
||||
|
||||
entryParams.setServicePhone(PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType()) ? legalPersonInfo.getLegalPersonPhone() : baseInfo.getContactPhone());
|
||||
|
||||
com.alipay.api.domain.AddressInfo addressInfo = new com.alipay.api.domain.AddressInfo();
|
||||
addressInfo.setCityCode(storeInfo.getMercCityCode());
|
||||
addressInfo.setDistrictCode(storeInfo.getMercAreaCode());
|
||||
addressInfo.setProvinceCode(storeInfo.getMercProvCode());
|
||||
addressInfo.setAddress(storeInfo.getBusinessAddress());
|
||||
entryParams.setBusinessAddress(addressInfo);
|
||||
|
||||
com.alipay.api.domain.SettleCardInfo settleCardInfo = new com.alipay.api.domain.SettleCardInfo();
|
||||
settleCardInfo.setAccountHolderName(settlementInfo.getSettlementName());
|
||||
settleCardInfo.setAccountNo(settlementInfo.getSettlementCardNo());
|
||||
settleCardInfo.setAccountInstProvince(settlementInfo.getOpenAccProvince());
|
||||
settleCardInfo.setAccountInstCity(settlementInfo.getOpenAccCity());
|
||||
settlementInfo.setBankBranchName(settlementInfo.getBankBranchName());
|
||||
settleCardInfo.setUsageType("21".equals(settlementInfo.getSettlementCardType()) ? "01" : "02");
|
||||
settleCardInfo.setAccountType("DC");
|
||||
settleCardInfo.setAccountInstName(settlementInfo.getBankName());
|
||||
settleCardInfo.setAccountInstId(settlementInfo.getBankInstId());
|
||||
settleCardInfo.setBankCode(settlementInfo.getBankBranchCode());
|
||||
entryParams.setBizCards(List.of(settleCardInfo));
|
||||
|
||||
com.alipay.api.domain.ContactInfo contactInfo = new com.alipay.api.domain.ContactInfo();
|
||||
if (PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType())) {
|
||||
contactInfo.setName(baseInfo.getContactName());
|
||||
contactInfo.setMobile(baseInfo.getContactPhone());
|
||||
contactInfo.setEmail(baseInfo.getContactEmail());
|
||||
contactInfo.setIdCardNo(baseInfo.getContactPersonId());
|
||||
} else if (PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
|
||||
contactInfo.setName(legalPersonInfo.getLegalPersonName());
|
||||
contactInfo.setMobile(legalPersonInfo.getLegalPersonPhone());
|
||||
contactInfo.setEmail(legalPersonInfo.getLegalPersonEmail());
|
||||
contactInfo.setIdCardNo(legalPersonInfo.getLegalPersonId());
|
||||
} else {
|
||||
throw new CzgException("联系人类型错误");
|
||||
}
|
||||
entryParams.setContactInfos(List.of(contactInfo));
|
||||
|
||||
entryParams.setLicenseAuthLetterImage(businessLicenceInfo.getLicensePic().getAlipayId());
|
||||
|
||||
// 小程序
|
||||
SiteInfo miniAppInfo = new SiteInfo();
|
||||
miniAppInfo.setSiteType("06");
|
||||
miniAppInfo.setSiteUrl("https://sxczgkj.cn");
|
||||
miniAppInfo.setSiteName("银收客");
|
||||
miniAppInfo.setTinyAppId("2021004145625815");
|
||||
entryParams.setSites(List.of(miniAppInfo));
|
||||
|
||||
return entryParams;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws ApiException {
|
||||
|
||||
// queryBankBranchList("CMB", "陕西省", "西安市");
|
||||
// uploadImage(null, "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/20240312/31476c871c224389aea0ac4e17c964a3.jpg");
|
||||
|
||||
test();
|
||||
}
|
||||
|
||||
// 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);
|
||||
log.info("dd: {}", JSONObject.toJSONString(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,239 @@
|
||||
package com.czg.third.alipay;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alipay.v3.ApiException;
|
||||
import com.alipay.v3.api.*;
|
||||
import com.alipay.v3.model.*;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.dto.req.*;
|
||||
import com.czg.dto.resp.EntryThirdRespDto;
|
||||
import com.czg.dto.resp.QueryStatusResp;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.alipay.dto.config.AlipayConfigDto;
|
||||
import com.czg.utils.UploadFileUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 支付宝服务商进件管理
|
||||
* <a href="https://opendocs.alipay.com/open-v3/b4c46445_alipay.open.agent.create?scene=common&pathHash=d7084b4b">...</a>
|
||||
* @author yjjie
|
||||
* @date 2026/1/8 13:34
|
||||
*/
|
||||
@Slf4j
|
||||
public class AlipayIsvEntryManager {
|
||||
|
||||
private static final String ERR_MESSAGE_KEY = "message";
|
||||
|
||||
public static QueryStatusResp queryMerchantBatchStatus(AlipayConfigDto configDto, String batchNo) {
|
||||
QueryStatusResp respDto = new QueryStatusResp()
|
||||
.setPlatform(PayCst.Platform.ALIPAY);
|
||||
AlipayClient.setApiClient(configDto);
|
||||
|
||||
try {
|
||||
AlipayOpenAgentOrderApi api = new AlipayOpenAgentOrderApi();
|
||||
AlipayOpenAgentOrderQueryResponseModel response = api.query(batchNo);
|
||||
|
||||
log.info("支付宝查询进件状态: 响应={}", response);
|
||||
respDto.setApplyId(batchNo);
|
||||
|
||||
switch (response.getOrderStatus()) {
|
||||
case "MERCHANT_INFO_HOLD" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setFailReason("三方异常,请重新提交");
|
||||
return respDto;
|
||||
}
|
||||
case "MERCHANT_CONFIRM_TIME_OUT" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setFailReason("商户确认超时,请重新提交");
|
||||
return respDto;
|
||||
}
|
||||
case "MERCHANT_AUDITING" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.AUDIT);
|
||||
respDto.setFailReason("");
|
||||
return respDto;
|
||||
}
|
||||
case "MERCHANT_CONFIRM" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.SIGN);
|
||||
respDto.setFailReason("");
|
||||
respDto.setSignUrl(response.getConfirmUrl());
|
||||
return respDto;
|
||||
}
|
||||
case "MERCHANT_APPLY_ORDER_CANCELED" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setFailReason(response.getRejectReason());
|
||||
return respDto;
|
||||
}
|
||||
case "MERCHANT_CONFIRM_SUCCESS" -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.FINISH);
|
||||
respDto.setFailReason("");
|
||||
respDto.setThirdMerchantId(response.getMerchantPid());
|
||||
return respDto;
|
||||
}
|
||||
case null -> {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setFailReason("查询失败");
|
||||
return respDto;
|
||||
}
|
||||
default -> {
|
||||
return respDto;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ApiException e) {
|
||||
String body = e.getResponseBody();
|
||||
log.error("支付宝查询进件状态异常: {}", body);
|
||||
JSONObject object = JSONObject.parseObject(body);
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setFailReason(object.getString(ERR_MESSAGE_KEY));
|
||||
return respDto;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建商户
|
||||
* @param configDto 配置信息
|
||||
* @param reqDto 请求信息
|
||||
*/
|
||||
public static EntryThirdRespDto entryMerchant(AlipayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
AlipayClient.setApiClient(configDto);
|
||||
EntryThirdRespDto respDto = new EntryThirdRespDto()
|
||||
.setPlatform(PayCst.Platform.ALIPAY);
|
||||
try {
|
||||
String batchNo = createRequest(reqDto);
|
||||
|
||||
AlipayOpenAgentFacetofaceSignModel signModel = buildFaceToFaceModel(reqDto, batchNo);
|
||||
File businessLicensePic = UploadFileUtil.getFileByUrl(reqDto.getBusinessLicenceInfo().getLicensePic().getUrl());
|
||||
File shopScenePic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getInsidePic().getUrl());
|
||||
File shopSignBoardPic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getDoorPic().getUrl());
|
||||
|
||||
// 构造请求参数以调用接口
|
||||
AlipayOpenAgentFacetofaceApi api = new AlipayOpenAgentFacetofaceApi();
|
||||
Object response = api.sign(null, businessLicensePic, signModel, shopScenePic, shopSignBoardPic, null);
|
||||
log.info("支付宝开启代商户签约: 响应={}", JSONObject.toJSONString(response));
|
||||
|
||||
try {
|
||||
String orderNo = confirmRequest(batchNo);
|
||||
respDto.setEntryId(orderNo);
|
||||
respDto.setStatus(PayCst.EntryStatus.INIT);
|
||||
respDto.setErrorMsg("");
|
||||
return respDto;
|
||||
} catch (CzgException e) {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setErrorMsg(e.getMessage());
|
||||
return respDto;
|
||||
}
|
||||
} catch (ApiException e) {
|
||||
String body = e.getResponseBody();
|
||||
log.error("支付宝开启代商户签约,创建应用事务异常: {}", body);
|
||||
JSONObject object = JSONObject.parseObject(body);
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setErrorMsg(object.getString(ERR_MESSAGE_KEY));
|
||||
return respDto;
|
||||
} catch (IOException e) {
|
||||
log.error("上传图片出错", e);
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setErrorMsg("上传图片出错");
|
||||
return respDto;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启代商户签约、创建应用事务
|
||||
* @param reqDto 请求信息
|
||||
* @return 请求ID
|
||||
*/
|
||||
public static String createRequest(AggregateMerchantDto reqDto) {
|
||||
AlipayOpenAgentApi api = new AlipayOpenAgentApi();
|
||||
AlipayOpenAgentCreateModel openModel = new AlipayOpenAgentCreateModel();
|
||||
|
||||
MerchantBaseInfoDto info = reqDto.getMerchantBaseInfo();
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
String contactPersonType = info.getContactPersonType();
|
||||
boolean isSuper = PayCst.ContactPersonType.SUPER.equals(contactPersonType);
|
||||
|
||||
ContactModel contactModel = new ContactModel();
|
||||
// 联系人名称
|
||||
contactModel.setContactName(isSuper ? info.getContactName() : legalPersonInfo.getLegalPersonName());
|
||||
// 联系人手机号码
|
||||
contactModel.setContactMobile(isSuper ? info.getContactPhone() : legalPersonInfo.getLegalPersonPhone());
|
||||
// 联系人邮箱
|
||||
contactModel.setContactEmail(isSuper ? info.getContactEmail() : legalPersonInfo.getLegalPersonEmail());
|
||||
openModel.setContactInfo(contactModel);
|
||||
|
||||
openModel.setAccount(reqDto.getMerchantBaseInfo().getAlipayAccount());
|
||||
|
||||
try {
|
||||
AlipayOpenAgentCreateResponseModel responseModel = api.create(openModel);
|
||||
log.info("支付宝开启代商户签约,开启事务: 结果={}, batchNo={}", responseModel.getBatchStatus(), responseModel.getBatchNo());
|
||||
return responseModel.getBatchNo();
|
||||
} catch (ApiException e) {
|
||||
String body = e.getResponseBody();
|
||||
log.error("支付宝开启代商户签约,开启事务异常: {}", body);
|
||||
JSONObject object = JSONObject.parseObject(body);
|
||||
throw new CzgException("支付宝开启代商户签约,开启事务异常: " + object.getString(ERR_MESSAGE_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
public static String confirmRequest(String batchNo) {
|
||||
AlipayClient.setApiClient(null);
|
||||
// 构造请求参数以调用接口
|
||||
AlipayOpenAgentCommonsignApi api = new AlipayOpenAgentCommonsignApi();
|
||||
AlipayOpenAgentCommonsignConfirmModel data = new AlipayOpenAgentCommonsignConfirmModel();
|
||||
|
||||
// 设置ISV 代商户操作事务编号
|
||||
data.setBatchNo(batchNo);
|
||||
try {
|
||||
AlipayOpenAgentCommonsignConfirmResponseModel response = api.confirm(data);
|
||||
log.info("支付宝开启代商户签约,确认事务: 响应={}", response);
|
||||
return response.getOrderNo();
|
||||
} catch (ApiException e) {
|
||||
String body = e.getResponseBody();
|
||||
log.error("支付宝开启代商户签约,确认事务异常: {}", body);
|
||||
JSONObject object = JSONObject.parseObject(body);
|
||||
throw new CzgException(object.getString(ERR_MESSAGE_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 当面付参数
|
||||
*/
|
||||
public static AlipayOpenAgentFacetofaceSignModel buildFaceToFaceModel(AggregateMerchantDto reqDto, String batchNo) {
|
||||
AlipayOpenAgentFacetofaceSignModel signModel = new AlipayOpenAgentFacetofaceSignModel();
|
||||
signModel.setBatchNo(batchNo);
|
||||
|
||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
BusinessLicenceInfoDto licenceInfo = reqDto.getBusinessLicenceInfo();
|
||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
||||
|
||||
signModel.setMccCode(baseInfo.getMccCode());
|
||||
signModel.setRate("0.38");
|
||||
signModel.setSignAndAuth(true);
|
||||
|
||||
signModel.setBusinessLicenseNo(licenceInfo.getLicenceNo());
|
||||
signModel.setBusinessLicenseMobile(legalPersonInfo.getLegalPersonPhone());
|
||||
signModel.setLongTerm(PayCst.LONG_TERM_DATE.equals(licenceInfo.getLicenceEndDate()));
|
||||
signModel.setDateLimitation(licenceInfo.getLicenceStartDate());
|
||||
|
||||
signModel.setShopName(baseInfo.getShortName());
|
||||
|
||||
// 设置店铺地址
|
||||
SignAddressInfo shopAddress = new SignAddressInfo();
|
||||
shopAddress.setCountryCode("156");
|
||||
shopAddress.setDistrictCode(storeInfo.getMercAreaCode());
|
||||
shopAddress.setDetailAddress(storeInfo.getBusinessAddress());
|
||||
shopAddress.setProvinceCode(storeInfo.getMercProvCode());
|
||||
shopAddress.setCityCode(storeInfo.getMercCityCode());
|
||||
signModel.setShopAddress(shopAddress);
|
||||
|
||||
return signModel;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// confirmRequest("2026010815384505500018243");
|
||||
queryMerchantBatchStatus(null, "2026010815384505500018243");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
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("2021006121646825")
|
||||
.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")
|
||||
.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
||||
.setDomain("https://openapi.alipay.com");
|
||||
// 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");
|
||||
// return new AlipayConfigDto()
|
||||
// .setAppId("2021004145625815")
|
||||
// .setPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCAjDBuS8K/IJb9ui+KuNm/sTUdEiaji4BNpZ92avO1N5JpNlGmac6ec4p3tNFT950sBLcQkClcUpQxUHQzAT6DYNNXOKyvfI/EmcqwCw6PaMNLs/8cV//J2WWZBUhLaOsjKurpm9/3W5MnTh4BGxIfBoeBMA8f8K3BgKdmyKtvIEV2h2cyjsMskdn+g6oNZcmWcms0pvpPHyH46mRaGFhpp0v19wX3WsamGldh1L2VntmaDN3C2XbSrXv90XYp5bEUqwTbLwXpMAlzTibF56d/iqv9oYi8cpAKougUFLOymnbutLNs2tLrEDSFwHcmG2/wbZHybZyYcIgFgv4arf+tAgMBAAECggEAf7hKKlw1y6Z6vvAtalxNZUuRZSfyog3p1bwYWxTavZPQcZ7Zs0lvVDmiO1u5m/7q96BbryY9IhCeUv0H5uF2lhwu/3s9AEL3qTPQkeb6eXxyhhX6A9RfPdM1Qbtg4CQHdHKg4qjP9znSVHwmDZ0y/QaEvdPdQzPjv92u9c2tn4N4x6XyBYcU5gzxiJNnIugCmBgcJo/3H2fgV+XXEhORPvy5of9b4oATHEaLS/8dAS2wuOjhzaGS4MXp3VkXn3XaYjwSzaL03qYWA+xm+aO5sJv8bmqZW7sNVck5o3sPo7cQ4VkBFVzyrRdmJcxcSRJ9MsB9JsrhoKI8pgaXrVie4QKBgQDU2vai0lpBIK/0jzRpPNoqdT8lnafnnWni8nU4kfAh+gCLi+HBPhQRT0kv4unQc2q2/gALE7sgZVO00JGY5a3R0orsojPoUSZlpypGW7GGqKy576NHn0nw4o/PdfysT92VWgt1hlfTf6qfCDhfE9APU+RGvlSWXcT8nxVel3iUaQKBgQCamoJN6+4v+chJvL2nqV8NVVRLp0vDIHxs1QOtKwUodx8Qp1D6CJYtavCXn8aNUFVNQJPJ7TQPpJjXP2rI4SN01weDwx+I+wh8PBGHV6/234R+6TvFgY1PrYgCdfNP4i/E7B4uyEhAxdU73PB8qkqRAeJGok05p7oG71KCOBiYpQKBgEZfGflcuDAeAW5GRhqg3rP4zWa/R7qgZVh9tll8jjp9b96y4XFE99d9MgId8BVVgyt6sEL5Q/2C4ni+F9TH4n6jMADp42VkJuCmsqhOOlP9whU67+2G8Sgtj0QUivPg964f9ffl8XVgGOW5DwIIB9p5btggptCLscufQK5kP545AoGADBvf6tR4wl8w9b2HqTMV08iEIqzGvVC1Dh0c/Zop/EJgN4CzUfIMOSBwGaAVAApzs+pD6QPgGP2OTwWTioo/qa4R05sbxDHNN1XJFa2jhZV6HiqMWOrNs5jm1zJ/zRjtHuJTdtyO9CvKiLbESy9XScY4/8lEfSiK5HIoJzTXkFUCgYAkYkvkW6psJpWj05XWq44UN0n6QOU/Igl35Um/iuOMVhsTmIt09STQVTuzJzfH82+sCqoRsD1blE5unKNUC1DK77aNKTv3Z0dxN9R7FAyfZRiYQXTrbBPBqWjay6FCNxn8e8UsJN4Z6FIV2LGlQI114krSap1MALKLVvnld0NaUQ==")
|
||||
// .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB")
|
||||
// .setDomain("https://openapi.alipay.com/gateway.do");
|
||||
}
|
||||
}
|
||||
@@ -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,418 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.czg.PayCst;
|
||||
import com.czg.dto.req.*;
|
||||
import com.czg.dto.resp.EntryThirdRespDto;
|
||||
import com.czg.dto.resp.QueryStatusResp;
|
||||
import com.czg.exception.CzgException;
|
||||
import com.czg.third.wechat.dto.config.WechatPayConfigDto;
|
||||
import com.czg.third.wechat.dto.req.entry.*;
|
||||
import com.czg.third.wechat.dto.req.entry.business.WechatEntryBusinessReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.business.WechatEntryIdentityReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.business.WechatEntryLicenseReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryMiniProgramReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntrySalesInfoReqDto;
|
||||
import com.czg.third.wechat.dto.req.entry.business.sales.WechatEntryStoreInfoReqDto;
|
||||
import com.czg.third.wechat.dto.resp.WechatAuditDetail;
|
||||
import com.czg.third.wechat.dto.resp.WechatQueryStateResp;
|
||||
import com.czg.utils.UploadFileUtil;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
|
||||
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.List;
|
||||
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 applyId 自系统的商户编号
|
||||
* @return 进件状态
|
||||
*/
|
||||
public static QueryStatusResp queryMerchantEntryStatus(WechatPayConfigDto configDto, String applyId) {
|
||||
QueryStatusResp queryStatusResp = new QueryStatusResp();
|
||||
queryStatusResp.setPlatform(PayCst.Platform.WECHAT);
|
||||
queryStatusResp.setMerchantCode(applyId);
|
||||
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/applyment4sub/applyment/applyment_id/" + applyId, Map.of());
|
||||
JSONObject object = JSONObject.parseObject(resp);
|
||||
JSONObject data = object.getJSONObject("data");
|
||||
if (data == null) {
|
||||
log.error("微信查询进件状态失败:{}", resp);
|
||||
queryStatusResp.setFailReason(object.getString("message"));
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
return queryStatusResp;
|
||||
}
|
||||
log.info("微信查询进件状态:{}", resp);
|
||||
WechatQueryStateResp stateResp = JSONObject.parseObject(data.toJSONString(), WechatQueryStateResp.class);
|
||||
|
||||
queryStatusResp.setApplyId(stateResp.getApplyId());
|
||||
switch (stateResp.getApplyState()) {
|
||||
case "APPLYMENT_STATE_EDITTING" -> {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.WAIT);
|
||||
queryStatusResp.setFailReason("");
|
||||
}
|
||||
case "APPLYMENT_STATE_AUDITING" -> {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.AUDIT);
|
||||
queryStatusResp.setFailReason("");
|
||||
}
|
||||
case "APPLYMENT_STATE_REJECTED" -> {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
StringBuilder msg = new StringBuilder();
|
||||
for (WechatAuditDetail auditDetail : stateResp.getAuditDetail()) {
|
||||
msg.append(auditDetail.getRejectReason()).append(",");
|
||||
}
|
||||
queryStatusResp.setFailReason(msg.toString());
|
||||
}
|
||||
case "APPLYMENT_STATE_TO_BE_CONFIRMED", "APPLYMENT_STATE_TO_BE_SIGNED" -> {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.SIGN);
|
||||
queryStatusResp.setFailReason("");
|
||||
queryStatusResp.setSignUrl(stateResp.getSignUrl());
|
||||
}
|
||||
case "APPLYMENT_STATE_SIGNING", "APPLYMENT_STATE_FINISHED" -> {
|
||||
queryStatusResp.setStatus(PayCst.EntryStatus.FINISH);
|
||||
queryStatusResp.setFailReason("");
|
||||
queryStatusResp.setThirdMerchantId(stateResp.getSubMchId());
|
||||
}
|
||||
}
|
||||
|
||||
return queryStatusResp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 进件商户
|
||||
*
|
||||
* @param configDto 配置信息
|
||||
* @param reqDto 请求信息
|
||||
*/
|
||||
public static EntryThirdRespDto entryMerchant(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
WechatEntryReqDto entryReqDto = buildEntryParams(configDto, reqDto);
|
||||
EntryThirdRespDto respDto = new EntryThirdRespDto()
|
||||
.setPlatform(PayCst.Platform.WECHAT);
|
||||
|
||||
log.info("微信进件参数:{}", JSONObject.toJSONString(entryReqDto));
|
||||
try {
|
||||
String params = JSONObject.toJSONString(entryReqDto, JSONWriter.Feature.IgnoreEmpty);
|
||||
String respBody = WechatReqUtils.postReq(configDto, "/v3/applyment4sub/applyment/", params);
|
||||
JSONObject object = JSONObject.parseObject(respBody);
|
||||
JSONObject data = object.getJSONObject("data");
|
||||
log.info("微信进件结果:{}", respBody);
|
||||
if (data != null) {
|
||||
respDto.setStatus(PayCst.EntryStatus.INIT);
|
||||
respDto.setEntryId(data.getString("applyment_id"));
|
||||
respDto.setErrorMsg("");
|
||||
} else {
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setEntryId("");
|
||||
respDto.setErrorMsg(object.getString("message"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("微信进件报错:{}", e.getMessage(), e);
|
||||
respDto.setStatus(PayCst.EntryStatus.REJECTED);
|
||||
respDto.setEntryId("");
|
||||
respDto.setErrorMsg(e.getMessage());
|
||||
}
|
||||
|
||||
return respDto;
|
||||
}
|
||||
|
||||
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));
|
||||
log.info("微信查询银行支行列表:{}", resp);
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
public static JSONObject queryProvinceList(WechatPayConfigDto configDto) {
|
||||
String resp = WechatReqUtils.getReq(configDto, "/v3/capital/capitallhh/areas/provinces", Map.of());
|
||||
log.info("微信查询省份列表:{}", resp);
|
||||
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());
|
||||
log.info("微信查询城市列表:{}", resp);
|
||||
return JSONObject.parseObject(resp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @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 "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建进件参数
|
||||
*
|
||||
* @param reqDto 请求参数
|
||||
* @return 进件参数
|
||||
*/
|
||||
private static WechatEntryReqDto buildEntryParams(WechatPayConfigDto configDto, AggregateMerchantDto reqDto) {
|
||||
WechatEntryReqDto entryParams = new WechatEntryReqDto();
|
||||
|
||||
Config config = WechatConfig.getRsaConfig(configDto);
|
||||
PrivacyEncryptor encryptor = config.createEncryptor();
|
||||
|
||||
entryParams.setBusinessCode(reqDto.getMerchantCode());
|
||||
|
||||
MerchantBaseInfoDto baseInfo = reqDto.getMerchantBaseInfo();
|
||||
LegalPersonInfoDto legalPersonInfo = reqDto.getLegalPersonInfo();
|
||||
BusinessLicenceInfoDto businessLicenceInfo = reqDto.getBusinessLicenceInfo();
|
||||
StoreInfoDto storeInfo = reqDto.getStoreInfo();
|
||||
SettlementInfoDto settlementInfo = reqDto.getSettlementInfo();
|
||||
|
||||
WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto();
|
||||
contactInfo.setContactType(baseInfo.getContactPersonType());
|
||||
// 默认都使用身份证 暂不支持其他证件
|
||||
contactInfo.setContactIdDocCopy("IDENTIFICATION_TYPE_IDCARD");
|
||||
if (PayCst.ContactPersonType.SUPER.equals(baseInfo.getContactPersonType())) {
|
||||
contactInfo.setContactName(encryptor.encrypt(baseInfo.getContactName()));
|
||||
contactInfo.setContactIdNumber(encryptor.encrypt(baseInfo.getContactPersonId()));
|
||||
contactInfo.setContactIdDocCopy(baseInfo.getContactIdCardFrontPic().getWechatId());
|
||||
contactInfo.setContactIdDocCopyBack(baseInfo.getContactIdCardBackPic().getWechatId());
|
||||
contactInfo.setContactPeriodBegin(baseInfo.getContactPersonIdStartDate());
|
||||
contactInfo.setContactPeriodEnd(baseInfo.getContactPersonIdEndDate());
|
||||
contactInfo.setMobilePhone(encryptor.encrypt(baseInfo.getContactPhone()));
|
||||
contactInfo.setContactEmail(encryptor.encrypt(baseInfo.getContactEmail()));
|
||||
} else if (PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType())) {
|
||||
contactInfo.setContactName(encryptor.encrypt(legalPersonInfo.getLegalPersonName()));
|
||||
contactInfo.setContactIdNumber(encryptor.encrypt(legalPersonInfo.getLegalPersonId()));
|
||||
contactInfo.setContactIdDocCopy(legalPersonInfo.getIdCardFrontPic().getWechatId());
|
||||
contactInfo.setContactIdDocCopyBack(legalPersonInfo.getIdCardBackPic().getWechatId());
|
||||
contactInfo.setContactPeriodBegin(legalPersonInfo.getLegalIdPersonStartDate());
|
||||
contactInfo.setContactPeriodEnd(legalPersonInfo.getLegalPersonIdEndDate());
|
||||
contactInfo.setMobilePhone(encryptor.encrypt(legalPersonInfo.getLegalPersonPhone()));
|
||||
contactInfo.setContactEmail(encryptor.encrypt(legalPersonInfo.getLegalPersonEmail()));
|
||||
} else {
|
||||
throw new CzgException("联系人类型错误");
|
||||
}
|
||||
entryParams.setContactInfo(contactInfo);
|
||||
|
||||
WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto();
|
||||
if ("0".equals(baseInfo.getUserType())) {
|
||||
subjectInfo.setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
|
||||
} else if ("1".equals(baseInfo.getUserType())) {
|
||||
switch (baseInfo.getCompanyChildType()) {
|
||||
case "1" -> subjectInfo.setSubjectType("SUBJECT_TYPE_ENTERPRISE");
|
||||
case "2" -> subjectInfo.setSubjectType("SUBJECT_TYPE_INSTITUTIONS");
|
||||
case "3" -> subjectInfo.setSubjectType("SUBJECT_TYPE_GOVERNMENT");
|
||||
case "4" -> subjectInfo.setSubjectType("SUBJECT_TYPE_OTHERS");
|
||||
default -> throw new CzgException("主体类型错误");
|
||||
}
|
||||
} else {
|
||||
throw new CzgException("用户类型错误");
|
||||
}
|
||||
subjectInfo.setFinanceInstitution(false);
|
||||
|
||||
WechatEntryLicenseReqDto licenseReqDto = new WechatEntryLicenseReqDto();
|
||||
licenseReqDto.setLicenseCopy(businessLicenceInfo.getLicensePic().getWechatId());
|
||||
licenseReqDto.setLicenseNumber(businessLicenceInfo.getLicenceNo());
|
||||
licenseReqDto.setMerchantName(businessLicenceInfo.getLicenceName());
|
||||
licenseReqDto.setLegalPerson(legalPersonInfo.getLegalPersonName());
|
||||
licenseReqDto.setLicenseAddress(businessLicenceInfo.getRegisteredAddress());
|
||||
licenseReqDto.setPeriodBegin(businessLicenceInfo.getLicenceStartDate());
|
||||
licenseReqDto.setPeriodEnd(businessLicenceInfo.getLicenceEndDate());
|
||||
subjectInfo.setBusinessLicenseInfo(licenseReqDto);
|
||||
WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto();
|
||||
identityInfo.setIdHolderType(PayCst.ContactPersonType.LEGAL);
|
||||
subjectInfo.setIdentityInfo(identityInfo);
|
||||
entryParams.setSubjectInfo(subjectInfo);
|
||||
|
||||
WechatEntryBusinessReqDto businessReqInfo = new WechatEntryBusinessReqDto();
|
||||
businessReqInfo.setMerchantShortname(baseInfo.getShortName());
|
||||
businessReqInfo.setServicePhone(PayCst.ContactPersonType.LEGAL.equals(baseInfo.getContactPersonType()) ? legalPersonInfo.getLegalPersonPhone() : baseInfo.getContactPhone());
|
||||
WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto();
|
||||
salesInfo.setSalesScenesType(List.of("SALES_SCENES_STORE", "SALES_SCENES_MINI_PROGRAM"));
|
||||
WechatEntryStoreInfoReqDto bizStoreInfo = new WechatEntryStoreInfoReqDto();
|
||||
bizStoreInfo.setBizStoreName(baseInfo.getShortName());
|
||||
bizStoreInfo.setBizAddressCode(storeInfo.getMercAreaCode());
|
||||
bizStoreInfo.setBizStoreAddress(storeInfo.getBusinessAddress());
|
||||
bizStoreInfo.setStoreEntrancePic(List.of(storeInfo.getDoorPic().getWechatId()));
|
||||
bizStoreInfo.setIndoorPic(List.of(storeInfo.getInsidePic().getWechatId(), storeInfo.getCashierDeskPic().getWechatId()));
|
||||
salesInfo.setBizStoreInfo(bizStoreInfo);
|
||||
WechatEntryMiniProgramReqDto miniProgramInfo = new WechatEntryMiniProgramReqDto();
|
||||
miniProgramInfo.setMiniProgramAppid("wxd88fffa983758a30");
|
||||
salesInfo.setMiniProgramInfo(miniProgramInfo);
|
||||
businessReqInfo.setSalesInfo(salesInfo);
|
||||
entryParams.setBusinessInfo(businessReqInfo);
|
||||
|
||||
WechatEntrySettleReqDto settlementReqInfo = new WechatEntrySettleReqDto();
|
||||
settlementReqInfo.setSettlementId("0".equals(baseInfo.getUserType()) ? "719" : "716");
|
||||
settlementReqInfo.setQualificationType("餐饮");
|
||||
settlementReqInfo.setActivitiesId("20191030111cff5b5e");
|
||||
settlementReqInfo.setActivitiesRate("0.38");
|
||||
entryParams.setSettlementInfo(settlementReqInfo);
|
||||
|
||||
WechatEntryBankAccountReqDto bankAccountReqInfo = new WechatEntryBankAccountReqDto();
|
||||
bankAccountReqInfo.setBankAccountType("21".equals(settlementInfo.getSettlementCardType()) ? "BANK_ACCOUNT_TYPE_CORPORATE" : "BANK_ACCOUNT_TYPE_PERSONAL");
|
||||
bankAccountReqInfo.setAccountName(encryptor.encrypt(settlementInfo.getSettlementName()));
|
||||
bankAccountReqInfo.setAccountBank(settlementInfo.getBankName());
|
||||
bankAccountReqInfo.setBankBranchId(settlementInfo.getBankBranchCode());
|
||||
bankAccountReqInfo.setBankName(settlementInfo.getBankBranchName());
|
||||
bankAccountReqInfo.setAccountNumber(encryptor.encrypt(settlementInfo.getSettlementCardNo()));
|
||||
entryParams.setBankAccountInfo(bankAccountReqInfo);
|
||||
|
||||
return entryParams;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
|
||||
queryMerchantEntryStatus(null, "20220106000000000001");
|
||||
|
||||
// int offset = 0;
|
||||
// Integer limit = 100;
|
||||
// JSONObject resp = queryBankList(null, 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,112 @@
|
||||
package com.czg.third.wechat;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
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) {
|
||||
if (configDto == null) {
|
||||
configDto = WechatPayConfigDto.getDefaultConfig();
|
||||
}
|
||||
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("不支持的请求方法");
|
||||
};
|
||||
HttpResponse response = request.execute();
|
||||
String s = response.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);
|
||||
|
||||
Config config = WechatConfig.getRsaConfig(configDto);
|
||||
Signer signer = config.createSigner();
|
||||
String signature = signer.sign(encryptStr).getSign();
|
||||
log.info("微信签名 encryptStr = {},\nsignature:{}", encryptStr, signature);
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取随机串
|
||||
*/
|
||||
private static String getNonceStr() {
|
||||
return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳
|
||||
*/
|
||||
private static long getTimestamp() {
|
||||
return System.currentTimeMillis() / 1000;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user