Compare commits

...

2 Commits

Author SHA1 Message Date
6be4421ed9 feat(payment): 添加微信支付商家转账场景报备信息配置
- 在 application-cms.yml、application-dev.yml、application-prod.yml 和 application-yd.yml 中
  添加 wechatpay.transfer.scene-id 和 scene-report-infos-json 配置项
- 重构 CmsNavigation 实体类,将 modelName 字段位置调整到正确位置
- 修改 CmsNavigationMapper.xml 添加模型名称关联查询
- 更新 JSONUtil 工具类,注册 JavaTimeModule 支持 LocalDateTime 等 Java8 时间类型
- 扩展 ShopDealerUser 实体类,添加 dealerName 和 community 字段
- 在 ShopDealerUserController 中添加手机号排重逻辑
- 修改 ShopDealerUserMapper.xml 增加关键词搜索字段
- 移除 ShopDealerWithdrawController 中多余的操作日志注解
- 扩展 ShopGoods 实体类,添加 categoryName 字段并修改关联查询
- 更新 WxLoginController 构造函数注入 ObjectMapper
- 增强 WxTransferService 添加转账场景报备信息验证和日志记录
2026-01-29 20:49:18 +08:00
4c290ea4fe ```
feat(payment): 升级微信商家转账接口为新版API

- 将批量转账接口替换为商家转账(升级版)接口 /v3/fund-app/mch-transfer/transfer-bills
- 新增 transfer_scene_id 和场景报备信息配置支持
- 参数从 outBatchNo/outDetailNo 统一为 outBillNo 单号
- 添加商户单号长度限制校验(5-32字符)
- 支持接口路径fallback机制,兼容不同环境差异
- 实现转账场景报备信息的JSON配置解析功能
- 更新日志记录格式以匹配新接口响应结构
```
2026-01-29 02:39:24 +08:00
15 changed files with 265 additions and 76 deletions

View File

@@ -43,6 +43,10 @@ public class CmsNavigation implements Serializable {
@Schema(description = "模型")
private String model;
@Schema(description = "模型名称")
@TableField(exist = false)
private String modelName;
@Schema(description = "标识")
private String code;
@@ -114,9 +118,6 @@ public class CmsNavigation implements Serializable {
@TableField(exist = false)
private Integer parentPosition;
@Schema(description = "模型名称")
private String modelName;
@Schema(description = "绑定的页面(已废弃)")
private Integer pageId;

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*, b.title as parentName, b.position as parentPosition
SELECT a.*, b.title as parentName, b.position as parentPosition, c.name as modelName
FROM cms_navigation a
LEFT JOIN cms_navigation b ON a.parent_id = b.navigation_id
LEFT JOIN cms_model c ON a.model = c.model
<where>
<if test="param.navigationId != null">
AND a.navigation_id = #{param.navigationId}

View File

@@ -1,8 +1,13 @@
package com.gxwebsoft.common.core.utils;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.TimeZone;
/**
* JSON解析工具类
@@ -11,8 +16,21 @@ import com.fasterxml.jackson.databind.ObjectWriter;
* @since 2017-06-10 10:10:39
*/
public class JSONUtil {
private static final ObjectMapper objectMapper = new ObjectMapper();
private static final ObjectWriter objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
/**
* 注意:不要直接 new ObjectMapper() 否则不支持 Java8 时间类型LocalDateTime 等)。
* 这里做最小可用配置,避免在 Redis/日志/签名等场景序列化失败。
*/
private static final ObjectMapper objectMapper;
private static final ObjectWriter objectWriter;
static {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
objectWriter = objectMapper.writerWithDefaultPrettyPrinter();
}
/**
* 对象转json字符串

View File

@@ -54,7 +54,7 @@ import static com.gxwebsoft.common.core.constants.RedisConstants.MP_WX_KEY;
public class WxLoginController extends BaseController {
private final StringRedisTemplate redisTemplate;
private final OkHttpClient http = new OkHttpClient();
private final ObjectMapper om = new ObjectMapper();
private final ObjectMapper om;
private volatile long tokenExpireEpoch = 0L; // 过期的 epoch 秒
@Resource
private SettingService settingService;
@@ -80,8 +80,9 @@ public class WxLoginController extends BaseController {
private CmsWebsiteService cmsWebsiteService;
public WxLoginController(StringRedisTemplate redisTemplate) {
public WxLoginController(StringRedisTemplate redisTemplate, ObjectMapper objectMapper) {
this.redisTemplate = redisTemplate;
this.om = objectMapper;
}
@Operation(summary = "获取微信AccessToken")

View File

@@ -4,49 +4,83 @@ import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.payment.exception.PaymentException;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.http.Constant;
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
import com.wechat.pay.java.core.http.HttpClient;
import com.wechat.pay.java.core.http.HttpHeaders;
import com.wechat.pay.java.core.http.HttpMethod;
import com.wechat.pay.java.core.http.HttpRequest;
import com.wechat.pay.java.core.http.HttpResponse;
import com.wechat.pay.java.core.http.JsonRequestBody;
import com.wechat.pay.java.core.http.MediaType;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.util.GsonUtil;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.lang.reflect.Type;
import java.util.List;
/**
* 微信支付-商家转账到零钱(批量转账)封装
* 使用 wechatpay-java (APIv3) SDK 发起转账。
* 微信支付-商家转账到零钱封装
*
* 注意:部分商户号开通了“商家转账(升级版)”后,会被微信侧限制使用旧版“批量转账到零钱”接口(/v3/transfer/batches
* 需改用升级版接口(/v3/fund-app/mch-transfer/transfer-bills
*/
@Slf4j
@Service
public class WxTransferService {
// 商家转账(升级版)接口在 fund-app 域下
private static final String TRANSFER_BILLS_API =
"https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
// 兼容少数文档/环境差异:如 fund-app 路径不可用时,尝试该路径(仅在 404 时重试)
private static final String TRANSFER_BILLS_API_FALLBACK =
"https://api.mch.weixin.qq.com/v3/transfer/bills";
@Resource
private WxPayConfigService wxPayConfigService;
/**
* 发起单笔“商家转账到零钱”(使用批量转账接口,明细数=1
* 商家转账升级版场景ID。直连模式下在“产品中心-商家转账”配置后获得
*/
@Value("${wechatpay.transfer.scene-id:1005}")
private String transferSceneId;
/**
* 转账场景报备信息(升级版必填项之一,内容需与商户平台该 transfer_scene_id 的报备信息对应)。
*
* 配置示例YAML
* wechatpay:
* transfer:
* scene-report-infos-json: '[{"info_type":"...","info_content":"..."}]'
*/
@Value("${wechatpay.transfer.scene-report-infos-json:}")
private String transferSceneReportInfosJson;
/**
* 发起单笔“商家转账到零钱”(升级版接口 /v3/fund-app/mch-transfer/transfer-bills
*
* @param tenantId 租户ID用于获取微信支付配置
* @param openid 收款用户openid必须是该appid下的openid
* @param amountYuan 转账金额(单位:元)
* @param outBatchNo 商家批次单号(字母/数字,商户内唯一)
* @param outDetailNo 商家明细单号(字母/数字,批次内唯一
* @param batchName 批次名称(<=32字符
* @param remark 备注(<=32字符既用于批次备注也用于单条明细备注
* @param outBillNo 商家单号(字母/数字,商户内唯一)
* @param remark 备注(<=32字符
* @param userName 收款用户姓名(可选;金额>=2000元时强制要求
*/
public InitiateBatchTransferResponse initiateSingleTransfer(Integer tenantId,
String openid,
BigDecimal amountYuan,
String outBatchNo,
String outDetailNo,
String batchName,
String remark,
String userName) throws PaymentException {
public TransferBillsResponse initiateSingleTransfer(Integer tenantId,
String openid,
BigDecimal amountYuan,
String outBillNo,
String remark,
String userName) throws PaymentException {
if (tenantId == null) {
throw PaymentException.paramError("租户ID不能为空");
@@ -57,18 +91,15 @@ public class WxTransferService {
if (amountYuan == null || amountYuan.compareTo(BigDecimal.ZERO) <= 0) {
throw PaymentException.amountError("转账金额必须大于0");
}
if (StrUtil.isBlank(outBatchNo) || !outBatchNo.matches("^[0-9A-Za-z]+$")) {
throw PaymentException.paramError("outBatchNo不合法仅允许数字/大小写字母");
if (StrUtil.isBlank(transferSceneId)) {
throw PaymentException.paramError("transfer_scene_id未配置无法发起商家转账升级版");
}
// 微信接口限制:商家批次单号长度需在区间内(当前实测最小 5
if (outBatchNo.length() < 5 || outBatchNo.length() > 32) {
throw PaymentException.paramError("outBatchNo长度不合法要求 5-32");
if (StrUtil.isBlank(outBillNo) || !outBillNo.matches("^[0-9A-Za-z]+$")) {
throw PaymentException.paramError("outBillNo不合法仅允许数字/大小写字母)");
}
if (StrUtil.isBlank(outDetailNo) || !outDetailNo.matches("^[0-9A-Za-z]+$")) {
throw PaymentException.paramError("outDetailNo不合法仅允许数字/大小写字母)");
}
if (outDetailNo.length() > 32) {
throw PaymentException.paramError("outDetailNo长度不合法最大 32");
// 保守校验:多数微信单号字段限制在 5-32你此前 out_batch_no 也是 5-32
if (outBillNo.length() < 5 || outBillNo.length() > 32) {
throw PaymentException.paramError("outBillNo长度不合法要求 5-32");
}
// 微信要求金额单位为“分”,必须为整数
@@ -91,41 +122,86 @@ public class WxTransferService {
userName = null;
}
// 升级版接口必填transfer_scene_report_infos且必须与 transfer_scene_id 的报备信息一致)
List<TransferSceneReportInfo> sceneReportInfos = parseTransferSceneReportInfos();
if (sceneReportInfos == null
|| sceneReportInfos.isEmpty()
|| sceneReportInfos.stream().anyMatch(i -> i == null
|| StrUtil.isBlank(i.getInfoType())
|| StrUtil.isBlank(i.getInfoContent()))) {
throw PaymentException.paramError(
"未传入完整且对应的转账场景报备信息:请在配置中设置 wechatpay.transfer.scene-report-infos-json需与 transfer_scene_id="
+ transferSceneId + " 的报备信息一致)");
}
Payment paymentConfig = wxPayConfigService.getPaymentConfigForStrategy(tenantId);
Config wxPayConfig = wxPayConfigService.getWxPayConfig(tenantId);
InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
request.setAppid(paymentConfig.getAppId());
request.setOutBatchNo(outBatchNo);
request.setBatchName(limitLen(batchName, 32));
request.setBatchRemark(limitLen(remark, 32));
request.setTotalAmount(amountFen);
request.setTotalNum(1);
// 可选:复用支付通知地址(如配置为 https用于接收转账结果通知
if (StrUtil.isNotBlank(paymentConfig.getNotifyUrl()) && paymentConfig.getNotifyUrl().startsWith("https://")) {
request.setNotifyUrl(paymentConfig.getNotifyUrl());
}
TransferDetailInput detail = new TransferDetailInput();
detail.setOutDetailNo(outDetailNo);
detail.setTransferAmount(amountFen);
detail.setTransferRemark(limitLen(remark, 32));
detail.setOpenid(openid);
if (StrUtil.isNotBlank(userName)) {
detail.setUserName(userName);
}
request.setTransferDetailList(Collections.singletonList(detail));
try {
TransferBatchService service = new TransferBatchService.Builder().config(wxPayConfig).build();
InitiateBatchTransferResponse response = service.initiateBatchTransfer(request);
log.info("微信商家转账已受理: tenantId={}, outBatchNo={}, batchId={}, batchStatus={}",
tenantId, response.getOutBatchNo(), response.getBatchId(), response.getBatchStatus());
HttpClient httpClient = new DefaultHttpClientBuilder().config(wxPayConfig).build();
PrivacyEncryptor encryptor = wxPayConfig.createEncryptor();
TransferBillsRequest request = new TransferBillsRequest();
request.setAppid(paymentConfig.getAppId());
request.setOutBillNo(outBillNo);
request.setTransferSceneId(transferSceneId);
request.setOpenid(openid);
request.setTransferAmount(amountFen);
request.setTransferRemark(limitLen(remark, 32));
request.setTransferSceneReportInfos(sceneReportInfos);
log.debug("微信商家转账(升级版)请求参数: tenantId={}, outBillNo={}, transferSceneId={}, sceneReportInfosCount={}",
tenantId, outBillNo, transferSceneId, sceneReportInfos.size());
// 可选:转账结果通知地址(必须 https
if (StrUtil.isNotBlank(paymentConfig.getNotifyUrl()) && paymentConfig.getNotifyUrl().startsWith("https://")) {
request.setNotifyUrl(paymentConfig.getNotifyUrl());
}
// 需要姓名时按平台证书加密,并带上 Wechatpay-Serial
if (StrUtil.isNotBlank(userName)) {
request.setUserName(encryptor.encrypt(userName));
}
HttpHeaders headers = new HttpHeaders();
headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue());
headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue());
headers.addHeader(Constant.WECHAT_PAY_SERIAL, encryptor.getWechatpaySerial());
HttpRequest httpRequest = buildTransferBillsHttpRequest(TRANSFER_BILLS_API, headers, request);
HttpResponse<TransferBillsResponse> httpResponse;
try {
httpResponse = httpClient.execute(httpRequest, TransferBillsResponse.class);
} catch (ServiceException se) {
// 404 且无 body 通常意味着接口路径不正确;做一次兜底重试。
if (se.getHttpStatusCode() == 404) {
log.warn("商家转账接口返回404尝试fallback路径: tenantId={}, outBillNo={}, url={}",
tenantId, outBillNo, TRANSFER_BILLS_API_FALLBACK);
HttpRequest fallbackReq = buildTransferBillsHttpRequest(TRANSFER_BILLS_API_FALLBACK, headers, request);
httpResponse = httpClient.execute(fallbackReq, TransferBillsResponse.class);
} else if (se.getHttpStatusCode() == 400
&& "PARAM_ERROR".equals(se.getErrorCode())
&& se.getErrorMessage() != null
&& se.getErrorMessage().contains("转账场景报备信息")) {
// 常见:升级版商家转账需带 transfer_scene_report_infos且内容必须与商户平台场景报备一致
throw PaymentException.paramError(
"未传入完整且对应的转账场景报备信息:请在配置中设置 wechatpay.transfer.scene-report-infos-json需与 transfer_scene_id="
+ transferSceneId + " 的报备信息一致)");
} else {
throw se;
}
}
TransferBillsResponse response = httpResponse.getServiceResponse();
log.info("微信商家转账已受理(升级版): tenantId={}, outBillNo={}, transferBillNo={}, state={}",
tenantId, outBillNo,
response != null ? response.getTransferBillNo() : null,
response != null ? response.getState() : null);
return response;
} catch (PaymentException e) {
// 业务/参数错误保持原样抛出,避免被包装成 systemError
throw e;
} catch (Exception e) {
log.error("微信商家转账失败: tenantId={}, outBatchNo={}, openid={}, amountFen={}, err={}",
tenantId, outBatchNo, openid, amountFen, e.getMessage(), e);
log.error("微信商家转账失败(升级版): tenantId={}, outBillNo={}, openid={}, amountFen={}, err={}",
tenantId, outBillNo, openid, amountFen, e.getMessage(), e);
throw PaymentException.systemError("微信商家转账失败: " + e.getMessage(), e);
}
}
@@ -139,4 +215,61 @@ public class WxTransferService {
}
return s.substring(0, maxLen);
}
private static HttpRequest buildTransferBillsHttpRequest(String url, HttpHeaders headers, TransferBillsRequest request) {
return new HttpRequest.Builder()
.httpMethod(HttpMethod.POST)
.url(url)
.headers(headers)
.body(new JsonRequestBody.Builder().body(GsonUtil.toJson(request)).build())
.build();
}
private List<TransferSceneReportInfo> parseTransferSceneReportInfos() throws PaymentException {
if (StrUtil.isBlank(transferSceneReportInfosJson)) {
return null;
}
try {
Type t = new TypeToken<List<TransferSceneReportInfo>>() {}.getType();
return GsonUtil.getGson().fromJson(transferSceneReportInfosJson, t);
} catch (Exception e) {
throw PaymentException.paramError("转账场景报备信息配置解析失败wechatpay.transfer.scene-report-infos-json");
}
}
/**
* 商家转账升级版请求体POST /v3/fund-app/mch-transfer/transfer-bills
* 字段命名使用 GsonUtil 的 lower_case_with_underscores 策略自动转换。
*/
@lombok.Data
private static class TransferBillsRequest {
private String appid;
private String outBillNo;
private String transferSceneId;
private String openid;
private Long transferAmount;
private String transferRemark;
private String userName;
private String notifyUrl;
private List<TransferSceneReportInfo> transferSceneReportInfos;
}
@lombok.Data
private static class TransferSceneReportInfo {
@SerializedName(value = "info_type", alternate = {"infoType"})
private String infoType;
@SerializedName(value = "info_content", alternate = {"infoContent"})
private String infoContent;
}
/**
* 商家转账(升级版)响应体(按需字段)
*/
@lombok.Data
public static class TransferBillsResponse {
private String outBillNo;
private String transferBillNo;
private String createTime;
private String state;
}
}

View File

@@ -3,6 +3,7 @@ package com.gxwebsoft.shop.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.service.ShopDealerUserService;
@@ -67,6 +68,10 @@ public class ShopDealerUserController extends BaseController {
if (loginUser != null) {
shopDealerUser.setUserId(loginUser.getUserId());
}
// 排重
if (shopDealerUserService.count(new LambdaQueryWrapper<ShopDealerUser>().eq(ShopDealerUser::getMobile, shopDealerUser.getMobile())) > 0) {
return fail("添加失败,手机号码已存在!");
}
if (shopDealerUserService.save(shopDealerUser)) {
return success("添加成功", shopDealerUser);
}

View File

@@ -66,7 +66,6 @@ public class ShopDealerWithdrawController extends BaseController {
}
@PreAuthorize("hasAuthority('shop:shopDealerWithdraw:save')")
@OperationLog
@Transactional(rollbackFor = {Exception.class})
@Operation(summary = "添加分销商提现明细表")
@PostMapping()
@@ -87,7 +86,6 @@ public class ShopDealerWithdrawController extends BaseController {
}
@PreAuthorize("hasAuthority('shop:shopDealerWithdraw:update')")
@OperationLog
@Transactional(rollbackFor = {Exception.class})
@Operation(summary = "修改分销商提现明细表")
@PutMapping()
@@ -138,10 +136,9 @@ public class ShopDealerWithdrawController extends BaseController {
return fail("用户openid为空无法发起微信转账");
}
// 微信支付批量转账接口对 out_batch_no 有最小长度限制(当前为 >= 5
// 微信支付商家转账接口对商户单号通常有最小长度限制(当前实测为 >= 5
// 使用 0 填充,避免如 "WD59" 这种过短导致 PARAM_ERROR。
String outBatchNo = String.format("WD%03d", db.getId());
String outDetailNo = outBatchNo + "D1";
String outBillNo = String.format("WD%03d", db.getId());
String remark = "分销商提现";
String userName = db.getRealName();
@@ -150,9 +147,7 @@ public class ShopDealerWithdrawController extends BaseController {
tenantId,
openid,
db.getMoney(),
outBatchNo,
outDetailNo,
"分销商提现",
outBillNo,
remark,
userName
);

View File

@@ -37,6 +37,12 @@ public class ShopDealerUser implements Serializable {
@TableField(exist = false)
private String openid;
@Schema(description = "店铺名称")
private String dealerName;
@Schema(description = "小区名称")
private String community;
@Schema(description = "头像")
@TableField(exist = false)
private String avatar;

View File

@@ -2,6 +2,7 @@ package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -44,6 +45,10 @@ public class ShopGoods implements Serializable {
@Schema(description = "产品分类ID")
private Integer categoryId;
@Schema(description = "分类名称")
@TableField(exist = false)
private String categoryName;
@Schema(description = "路由地址")
private String path;

View File

@@ -64,6 +64,7 @@
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR a.user_id = #{param.keywords} OR a.dealer_name LIKE CONCAT('%', #{param.keywords}, '%') OR a.real_name LIKE CONCAT('%', #{param.keywords}, '%') OR a.mobile LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>

View File

@@ -4,8 +4,9 @@
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
SELECT a.*, b.title AS categoryName
FROM shop_goods a
LEFT JOIN cms_navigation b ON a.category_id = b.navigation_id
<where>
<if test="param.goodsId != null">
AND a.goods_id = #{param.goodsId}

View File

@@ -75,3 +75,9 @@ payment:
key-prefix: "Payment:1"
# 缓存过期时间(小时)
expire-hours: 24
# 微信支付-商家转账(升级版)转账场景报备信息(必须与商户平台 transfer_scene_id=1005 的报备信息一致)
wechatpay:
transfer:
scene-id: 1005
scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"业务员"},{"info_type":"报酬说明","info_content":"配送费"}]'

View File

@@ -63,3 +63,9 @@ aliyun:
access-key-id: LTAI5tEsyhW4GCKbds1qsopg
access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO
endpoint: mt.cn-hangzhou.aliyuncs.com
# 微信支付-商家转账(升级版)转账场景报备信息(必须与商户平台 transfer_scene_id=1005 的报备信息一致)
wechatpay:
transfer:
scene-id: 1005
scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"业务员"},{"info_type":"报酬说明","info_content":"配送费"}]'

View File

@@ -77,3 +77,7 @@ aliyun:
access-key-id: LTAI5tEsyhW4GCKbds1qsopg
access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO
endpoint: mt.cn-hangzhou.aliyuncs.com
wechatpay:
transfer:
scene-id: 1005
scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"业务员"},{"info_type":"报酬说明","info_content":"配送费"}]'

View File

@@ -75,3 +75,9 @@ payment:
key-prefix: "Payment:1"
# 缓存过期时间(小时)
expire-hours: 24
# 微信支付-商家转账(升级版)转账场景报备信息(必须与商户平台 transfer_scene_id=1005 的报备信息一致)
wechatpay:
transfer:
scene-id: 1005
scene-report-infos-json: '[{"info_type":"岗位类型","info_content":"业务员"},{"info_type":"报酬说明","info_content":"配送费"}]'