mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-13 21:33:41 +08:00
feat: 直连商户V3分账
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package cn.felord.payment.wechat.enumeration;
|
||||
|
||||
|
||||
/**
|
||||
* 分账接收方类型
|
||||
*
|
||||
* @author n1
|
||||
* @since 2021/5/31 17:47
|
||||
*/
|
||||
public enum ReceiverType {
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
MERCHANT_ID,
|
||||
/**
|
||||
* 个人openid(由父商户APPID转换得到)
|
||||
*/
|
||||
PERSONAL_OPENID,
|
||||
/**
|
||||
* 个人sub_openid(由子商户APPID转换得到),服务商模式
|
||||
*/
|
||||
PERSONAL_SUB_OPENID
|
||||
}
|
||||
@@ -496,6 +496,7 @@ public enum WechatPayV3Type {
|
||||
/**
|
||||
* 查询转账明细电子回单受理结果API.
|
||||
* 请求方式同{@link WechatPayV3Type#BATCH_TRANSFER_ELECTRONIC}不同
|
||||
*
|
||||
* @since 1.0.11.RELEASES
|
||||
*/
|
||||
BATCH_TRANSFER_ELECTRONIC_DETAIL(HttpMethod.GET, "%s/v3/transfer-detail/electronic-receipts"),
|
||||
@@ -510,7 +511,8 @@ public enum WechatPayV3Type {
|
||||
*
|
||||
* @since 1.0.11.RELEASES
|
||||
*/
|
||||
BATCH_TRANSFER_FUND_DAY_BALANCE(HttpMethod.GET, "%s/v3/merchant/fund/dayendbalance/{account_type}"), /**
|
||||
BATCH_TRANSFER_FUND_DAY_BALANCE(HttpMethod.GET, "%s/v3/merchant/fund/dayendbalance/{account_type}"),
|
||||
/**
|
||||
* 商户银行来账查询API
|
||||
*
|
||||
* @since 1.0.11.RELEASES
|
||||
@@ -565,7 +567,56 @@ public enum WechatPayV3Type {
|
||||
* @since 1.0.0.RELEASE
|
||||
*/
|
||||
TRANSACTION_OUT_TRADE_NO_PARTNER(HttpMethod.GET, "%s/v3/pay/partner/transactions/out-trade-no/{out_trade_no}"),
|
||||
;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/**
|
||||
* 请求分账API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_ORDERS(HttpMethod.POST, "%s/v3/profitsharing/orders"),
|
||||
/**
|
||||
* 查询分账结果API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_ORDERS_RESULT(HttpMethod.GET, "%s/v3/profitsharing/orders/{out_order_no}"),
|
||||
/**
|
||||
* 请求分账回退API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_RETURN_ORDERS(HttpMethod.POST, "%s/v3/profitsharing/return-orders"),
|
||||
/**
|
||||
* 查询分账回退结果API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_RETURN_ORDERS_RESULT(HttpMethod.GET, "%s/v3/profitsharing/return-orders"),
|
||||
/**
|
||||
* 解冻剩余资金API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_ORDERS_UNFREEZE(HttpMethod.POST, "%s/v3/profitsharing/orders/unfreeze"),
|
||||
/**
|
||||
* 查询剩余待分金额API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_AMOUNTS(HttpMethod.GET, "%s/v3/profitsharing/transactions/{transaction_id}/amounts"),
|
||||
/**
|
||||
* 添加分账接收方API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_RECEIVERS_ADD(HttpMethod.POST, "%s/v3/profitsharing/receivers/add"),
|
||||
/**
|
||||
* 删除分账接收方API.
|
||||
*
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
PROFITSHARING_RECEIVERS_DELETE(HttpMethod.POST, "%s/v3/profitsharing/receivers/add");
|
||||
/**
|
||||
* The Pattern.
|
||||
*
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.List;
|
||||
* 微信支付分账
|
||||
* <p>
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.10.RELEASE
|
||||
*/
|
||||
@Slf4j
|
||||
@@ -72,20 +73,20 @@ public class WechatAllocationApi {
|
||||
*/
|
||||
@SneakyThrows
|
||||
public JsonNode profitSharing(ProfitSharingModel profitSharingModel) {
|
||||
ProfitSharingSModel profitSharingSModel = new ProfitSharingSModel();
|
||||
ProfitSharingSModel model = new ProfitSharingSModel();
|
||||
List<Receiver> receivers = profitSharingModel.getReceivers();
|
||||
profitSharingSModel.setReceivers(MAPPER.writeValueAsString(receivers));
|
||||
model.setReceivers(MAPPER.writeValueAsString(receivers));
|
||||
|
||||
WechatPayProperties.V3 v3 = wechatV2Client.getWechatMetaBean().getV3();
|
||||
profitSharingSModel.setAppid(v3.getAppId());
|
||||
profitSharingSModel.setMchId(v3.getMchId());
|
||||
model.setAppid(v3.getAppId());
|
||||
model.setMchId(v3.getMchId());
|
||||
|
||||
profitSharingSModel.setTransactionId(profitSharingModel.getTransactionId());
|
||||
profitSharingSModel.setOutOrderNo(profitSharingModel.getOutOrderNo());
|
||||
model.setTransactionId(profitSharingModel.getTransactionId());
|
||||
model.setOutOrderNo(profitSharingModel.getOutOrderNo());
|
||||
|
||||
profitSharingSModel.certPath(v3.getCertPath());
|
||||
profitSharingSModel.signType(BaseModel.HMAC_SHA256);
|
||||
return wechatV2Client.wechatPayRequest(profitSharingSModel,
|
||||
model.certPath(v3.getCertPath());
|
||||
model.signType(BaseModel.HMAC_SHA256);
|
||||
return wechatV2Client.wechatPayRequest(model,
|
||||
HttpMethod.POST,
|
||||
"https://api.mch.weixin.qq.com/secapi/pay/profitsharing");
|
||||
}
|
||||
|
||||
@@ -77,11 +77,11 @@ public class WechatBatchTransferApi extends AbstractApi {
|
||||
List<CreateBatchTransferParams.TransferDetailListItem> transferDetailList = createBatchTransferParams.getTransferDetailList();
|
||||
|
||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||
final X509WechatCertificateInfo certificate = signatureProvider.getCertificate();
|
||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate();
|
||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
||||
List<CreateBatchTransferParams.TransferDetailListItem> encrypted = transferDetailList.stream()
|
||||
.peek(transferDetailListItem -> {
|
||||
String userName = transferDetailListItem.getUserName();
|
||||
X509Certificate x509Certificate = certificate.getX509Certificate();
|
||||
String encryptedUserName = signatureProvider.encryptRequestMessage(userName, x509Certificate);
|
||||
transferDetailListItem.setUserName(encryptedUserName);
|
||||
String userIdCard = transferDetailListItem.getUserIdCard();
|
||||
@@ -262,7 +262,7 @@ public class WechatBatchTransferApi extends AbstractApi {
|
||||
* <p>
|
||||
* 受理转账明细电子回单接口,商户通过该接口可以申请受理转账明细单电子回单服务。
|
||||
* <p>
|
||||
* 返回的下载链接可调用{@link this#downloadBillResponse(String, String)}下载文件
|
||||
* 返回的下载链接可调用{@link #downloadBillResponse(String, String)}下载文件
|
||||
*
|
||||
* @param params the params
|
||||
* @return the wechat response entity
|
||||
|
||||
@@ -29,6 +29,7 @@ import cn.felord.payment.wechat.v3.model.payscore.PayScoreConsumer;
|
||||
import cn.felord.payment.wechat.v3.model.payscore.PayScoreUserConfirmConsumeData;
|
||||
import cn.felord.payment.wechat.v3.model.payscore.PayScoreUserPaidConsumeData;
|
||||
import cn.felord.payment.wechat.v3.model.payscore.PayScoreUserPermissionConsumeData;
|
||||
import cn.felord.payment.wechat.v3.model.profitsharing.ProfitsharingConsumeData;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
@@ -39,7 +40,6 @@ import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -73,8 +73,8 @@ public class WechatPayCallback {
|
||||
static {
|
||||
MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
|
||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false)
|
||||
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,true)
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
|
||||
.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class WechatPayCallback {
|
||||
|
||||
|
||||
/**
|
||||
* 微信支付分账回调.
|
||||
* 微信支付分账V2回调.
|
||||
*
|
||||
* @param params the params
|
||||
* @param consumeDataConsumer the consume data consumer
|
||||
@@ -100,14 +100,11 @@ public class WechatPayCallback {
|
||||
* @since 1.0.10.RELEASE
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> profitSharingCallback(ResponseSignVerifyParams params, Consumer<ProfitSharingConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> profitSharingCallback(ResponseSignVerifyParams params, Consumer<ProfitSharingConsumeData> consumeDataConsumer) {
|
||||
String data = this.callback(params, EventType.TRANSACTION);
|
||||
ProfitSharingConsumeData consumeData = MAPPER.readValue(data, ProfitSharingConsumeData.class);
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
Map<String, Object> responseBody = new HashMap<>(2);
|
||||
responseBody.put("code", 200);
|
||||
responseBody.put("message", "SUCCESS");
|
||||
return responseBody;
|
||||
return response();
|
||||
|
||||
}
|
||||
|
||||
@@ -121,14 +118,11 @@ public class WechatPayCallback {
|
||||
* @since 1.0.0.RELEASE
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> couponCallback(ResponseSignVerifyParams params, Consumer<CouponConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> couponCallback(ResponseSignVerifyParams params, Consumer<CouponConsumeData> consumeDataConsumer) {
|
||||
String data = this.callback(params, EventType.COUPON_USE);
|
||||
CouponConsumeData consumeData = MAPPER.readValue(data, CouponConsumeData.class);
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
Map<String, Object> responseBody = new HashMap<>(2);
|
||||
responseBody.put("code", 200);
|
||||
responseBody.put("message", "SUCCESS");
|
||||
return responseBody;
|
||||
return response();
|
||||
|
||||
}
|
||||
|
||||
@@ -143,12 +137,11 @@ public class WechatPayCallback {
|
||||
* @since 1.0.0.RELEASE
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> transactionCallback(ResponseSignVerifyParams params, Consumer<TransactionConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> transactionCallback(ResponseSignVerifyParams params, Consumer<TransactionConsumeData> consumeDataConsumer) {
|
||||
String data = this.callback(params, EventType.TRANSACTION);
|
||||
TransactionConsumeData consumeData = MAPPER.readValue(data, TransactionConsumeData.class);
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,12 +155,11 @@ public class WechatPayCallback {
|
||||
* @since 1.0.0.RELEASE
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> combineTransactionCallback(ResponseSignVerifyParams params, Consumer<CombineTransactionConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> combineTransactionCallback(ResponseSignVerifyParams params, Consumer<CombineTransactionConsumeData> consumeDataConsumer) {
|
||||
String data = this.callback(params, EventType.TRANSACTION);
|
||||
CombineTransactionConsumeData consumeData = MAPPER.readValue(data, CombineTransactionConsumeData.class);
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +173,7 @@ public class WechatPayCallback {
|
||||
* @since 1.0.2.RELEASE
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> payscoreUserOrderCallback(ResponseSignVerifyParams params, PayScoreConsumer payScoreConsumer) {
|
||||
public Map<String, String> payscoreUserOrderCallback(ResponseSignVerifyParams params, PayScoreConsumer payScoreConsumer) {
|
||||
CallbackParams callbackParams = resolve(params);
|
||||
String eventType = callbackParams.getEventType();
|
||||
|
||||
@@ -197,8 +189,7 @@ public class WechatPayCallback {
|
||||
log.error("wechat pay event type is not matched, callbackParams {}", callbackParams);
|
||||
throw new PayException(" wechat pay event type is not matched");
|
||||
}
|
||||
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +204,7 @@ public class WechatPayCallback {
|
||||
* @return the map
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> permissionCallback(ResponseSignVerifyParams params, Consumer<PayScoreUserPermissionConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> permissionCallback(ResponseSignVerifyParams params, Consumer<PayScoreUserPermissionConsumeData> consumeDataConsumer) {
|
||||
CallbackParams callbackParams = resolve(params);
|
||||
String eventType = callbackParams.getEventType();
|
||||
boolean closed;
|
||||
@@ -229,7 +220,7 @@ public class WechatPayCallback {
|
||||
PayScoreUserPermissionConsumeData consumeData = MAPPER.readValue(data, PayScoreUserPermissionConsumeData.class);
|
||||
consumeData.setClosed(closed);
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,7 +256,7 @@ public class WechatPayCallback {
|
||||
log.error("wechat pay event type is not matched, callbackParams {}", callbackParams);
|
||||
throw new PayException(" wechat pay event type is not matched");
|
||||
}
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,7 +271,7 @@ public class WechatPayCallback {
|
||||
* @return the map
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> busiFavorReceiveCallback(ResponseSignVerifyParams params, Consumer<BusiFavorReceiveConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> busiFavorReceiveCallback(ResponseSignVerifyParams params, Consumer<BusiFavorReceiveConsumeData> consumeDataConsumer) {
|
||||
CallbackParams callbackParams = resolve(params);
|
||||
String eventType = callbackParams.getEventType();
|
||||
|
||||
@@ -292,7 +283,7 @@ public class WechatPayCallback {
|
||||
BusiFavorReceiveConsumeData consumeData = MAPPER.readValue(data, BusiFavorReceiveConsumeData.class);
|
||||
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,10 +293,10 @@ public class WechatPayCallback {
|
||||
*
|
||||
* @param params the params
|
||||
* @param consumeDataConsumer the consume data consumer
|
||||
* @return map
|
||||
* @return map map
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, ?> refundCallback(ResponseSignVerifyParams params, Consumer<RefundConsumeData> consumeDataConsumer) {
|
||||
public Map<String, String> refundCallback(ResponseSignVerifyParams params, Consumer<RefundConsumeData> consumeDataConsumer) {
|
||||
CallbackParams callbackParams = resolve(params);
|
||||
String eventType = callbackParams.getEventType();
|
||||
|
||||
@@ -319,9 +310,23 @@ public class WechatPayCallback {
|
||||
RefundConsumeData consumeData = MAPPER.readValue(data, RefundConsumeData.class);
|
||||
|
||||
consumeDataConsumer.accept(consumeData);
|
||||
return Collections.singletonMap("code", "SUCCESS");
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付分账V3动账通知
|
||||
*
|
||||
* @param params the params
|
||||
* @param profitsharingConsumeDataConsumer the profitsharing consume data consumer
|
||||
* @return map map
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Map<String, String> profitsharingCallback(ResponseSignVerifyParams params, Consumer<ProfitsharingConsumeData> profitsharingConsumeDataConsumer) {
|
||||
String callback = this.callback(params, EventType.TRANSACTION);
|
||||
ProfitsharingConsumeData consumeData = MAPPER.readValue(callback, ProfitsharingConsumeData.class);
|
||||
profitsharingConsumeDataConsumer.accept(consumeData);
|
||||
return response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback.
|
||||
@@ -373,6 +378,18 @@ public class WechatPayCallback {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调应答
|
||||
*
|
||||
* @return response
|
||||
*/
|
||||
private Map<String, String> response() {
|
||||
Map<String, String> responseBody = new HashMap<>(2);
|
||||
responseBody.put("code", "SUCCESS");
|
||||
responseBody.put("message", "SUCCESS");
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 事件类型用于处理回调.
|
||||
@@ -450,7 +467,7 @@ public class WechatPayCallback {
|
||||
COUPON_SEND("COUPON.SEND"),
|
||||
|
||||
/**
|
||||
* 支付成功事件.
|
||||
* 支付成功、分账、分账回退事件.
|
||||
*
|
||||
* @since 1.0.0.RELEASE
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
package cn.felord.payment.wechat.v3;
|
||||
|
||||
import cn.felord.payment.wechat.WechatPayProperties;
|
||||
import cn.felord.payment.wechat.enumeration.WeChatServer;
|
||||
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
|
||||
import cn.felord.payment.wechat.v3.model.profitsharing.*;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 微信V3直联商户分账
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
public class WechatProfitsharingApi extends AbstractApi {
|
||||
|
||||
/**
|
||||
* Instantiates a new Abstract api.
|
||||
*
|
||||
* @param wechatPayClient the wechat pay client
|
||||
* @param tenantId the tenant id
|
||||
*/
|
||||
public WechatProfitsharingApi(WechatPayClient wechatPayClient, String tenantId) {
|
||||
super(wechatPayClient, tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求分账API
|
||||
* <p>
|
||||
* 微信订单支付成功后,商户发起分账请求,将结算后的资金分到分账接收方
|
||||
* <p>
|
||||
* 注意:
|
||||
* <ul>
|
||||
* <li>对同一笔订单最多能发起20次分账请求,每次请求最多分给50个接收方</li>
|
||||
* <li>此接口采用异步处理模式,即在接收到商户请求后,优先受理请求再异步处理,最终的分账结果可以通过查询分账接口获取</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param profitSharingOrder the profit sharing order
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> profitsharingOrders(ProfitSharingOrder profitSharingOrder) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_ORDERS, profitSharingOrder)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate();
|
||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
||||
params.setAppid(v3.getAppId());
|
||||
List<Receiver> receivers = params.getReceivers();
|
||||
if (!CollectionUtils.isEmpty(receivers)) {
|
||||
List<Receiver> encrypted = receivers.stream()
|
||||
.peek(receiversItem -> {
|
||||
String name = receiversItem.getName();
|
||||
if (StringUtils.hasText(name)) {
|
||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
||||
receiversItem.setName(encryptedName);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
params.setReceivers(encrypted);
|
||||
}
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.toUri();
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
||||
return Post(uri, params, httpHeaders);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分账结果API
|
||||
* <p>
|
||||
* 发起分账请求后,可调用此接口查询分账结果
|
||||
* <p>
|
||||
* 注意:
|
||||
* <ul>
|
||||
* <li>发起解冻剩余资金请求后,可调用此接口查询解冻剩余资金的结果</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param queryOrderParams the query order params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryProfitsharingOrder(QueryOrderParams queryOrderParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_ORDERS_RESULT, queryOrderParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.queryParam("transaction_id", params.getTransactionId())
|
||||
.build()
|
||||
.expand(params.getOutOrderNo())
|
||||
.toUri();
|
||||
return Get(uri);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求分账回退API
|
||||
* <p>
|
||||
* 如果订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款
|
||||
* <p>
|
||||
* 注意:
|
||||
* <ul>
|
||||
* <li>分账回退以原分账单为依据,支持多次回退,申请回退总金额不能超过原分账单分给该接收方的金额</li>
|
||||
* <li>此接口采用同步处理模式,即在接收到商户请求后,会实时返回处理结果</li>
|
||||
* <li>对同一笔分账单最多能发起20次分账回退请求</li>
|
||||
* <li>退款和分账回退没有耦合,分账回退可以先于退款请求,也可以后于退款请求</li>
|
||||
* <li>此功能需要接收方在商户平台-交易中心-分账-分账接收设置下,开启同意分账回退后,才能使用</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param returnOrdersParams the return orders params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> returnOrders(ReturnOrdersParams returnOrdersParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_RETURN_ORDERS, returnOrdersParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.toUri();
|
||||
return Post(uri, params);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询分账回退结果API
|
||||
* <p>
|
||||
* 商户需要核实回退结果,可调用此接口查询回退结果
|
||||
* <p>
|
||||
* 注意:
|
||||
* <ul>
|
||||
* <li>如果分账回退接口返回状态为处理中,可调用此接口查询回退结果</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param queryReturnOrderParams the query return order params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryReturnOrders(QueryReturnOrderParams queryReturnOrderParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_RETURN_ORDERS_RESULT, queryReturnOrderParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.queryParam("out_order_no", params.getOutOrderNo())
|
||||
.build()
|
||||
.expand(params.getOutReturnNo())
|
||||
.toUri();
|
||||
return Get(uri);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解冻剩余资金API
|
||||
* <p>
|
||||
* 不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给特约商户
|
||||
* <p>
|
||||
* 注意:
|
||||
* <ul>
|
||||
* <li>调用分账接口后,需要解冻剩余资金时,调用本接口将剩余的分账金额全部解冻给特约商户</li>
|
||||
* <li>此接口采用异步处理模式,即在接收到商户请求后,优先受理请求再异步处理,最终的分账结果可以通过查询分账接口获取</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param unfreezeParams the unfreeze params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> unfreeze(UnfreezeParams unfreezeParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_ORDERS_UNFREEZE, unfreezeParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.toUri();
|
||||
return Post(uri, params);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询剩余待分金额API
|
||||
* <p>
|
||||
* 可调用此接口查询订单剩余待分金额
|
||||
*
|
||||
* @param transactionId the transaction id
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryAmounts(String transactionId) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_AMOUNTS, transactionId)
|
||||
.function((wechatPayV3Type, id) -> {
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.expand(id)
|
||||
.toUri();
|
||||
return Get(uri);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分账接收方API
|
||||
* <p>
|
||||
* 商户发起添加分账接收方请求,建立分账接收方列表。后续可通过发起分账请求,将分账方商户结算后的资金,分到该分账接收方
|
||||
*
|
||||
* @param addReceiversParams the add receivers params
|
||||
* @return wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> addReceivers(AddReceiversParams addReceiversParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_RECEIVERS_ADD, addReceiversParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||
SignatureProvider signatureProvider = this.client().signatureProvider();
|
||||
X509WechatCertificateInfo certificate = signatureProvider.getCertificate();
|
||||
final X509Certificate x509Certificate = certificate.getX509Certificate();
|
||||
params.setAppid(v3.getAppId());
|
||||
String name = params.getName();
|
||||
if (StringUtils.hasText(name)) {
|
||||
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
|
||||
params.setName(encryptedName);
|
||||
}
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.toUri();
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
|
||||
return Post(uri, params, httpHeaders);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分账接收方API
|
||||
* <p>
|
||||
* 商户发起删除分账接收方请求。删除后,不支持将分账方商户结算后的资金,分到该分账接收方
|
||||
*
|
||||
* @param delReceiversParams the del receivers params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> deleteReceivers(DelReceiversParams delReceiversParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.PROFITSHARING_RECEIVERS_DELETE, delReceiversParams)
|
||||
.function((wechatPayV3Type, params) -> {
|
||||
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
|
||||
params.setAppid(v3.getAppId());
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
|
||||
.build()
|
||||
.toUri();
|
||||
return Post(uri, params);
|
||||
})
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import cn.felord.payment.wechat.enumeration.ReceiverType;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 添加分账接收方API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class AddReceiversParams {
|
||||
/**
|
||||
* 应用ID,自动注入
|
||||
*/
|
||||
private String appid;
|
||||
/**
|
||||
* 分账接收方类型,必填
|
||||
*/
|
||||
private ReceiverType type;
|
||||
/**
|
||||
* 分账接收方帐号,必填
|
||||
*/
|
||||
private String account;
|
||||
/**
|
||||
* 分账个人接收方姓名,选填
|
||||
* <p>
|
||||
* 分账接收方类型是{@code MERCHANT_ID}时,是商户全称(必传),当商户是小微商户或个体户时,是开户人姓名 分账接收方类型是{@code PERSONAL_OPENID}时,是个人姓名(选传,传则校验)
|
||||
* <ol>
|
||||
* <li>分账接收方类型是{@code PERSONAL_OPENID},是个人姓名的密文(选传,传则校验) 此字段的加密方法详见:敏感信息加密说明</li>
|
||||
* <li>使用微信支付平台证书中的公钥</li>
|
||||
* <li>使用RSAES-OAEP算法进行加密</li>
|
||||
* <li>将请求中HTTP头部的Wechatpay-Serial设置为证书序列号</li>
|
||||
* </ol>
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 与分账方的关系类型,必填
|
||||
*/
|
||||
private RelationType relationType;
|
||||
/**
|
||||
* 自定义的分账关系,选填
|
||||
*/
|
||||
private String customRelation;
|
||||
|
||||
/**
|
||||
* 子商户与接收方的关系
|
||||
*/
|
||||
public enum RelationType {
|
||||
/**
|
||||
* 门店.
|
||||
*/
|
||||
STORE,
|
||||
/**
|
||||
* 员工.
|
||||
*/
|
||||
STAFF,
|
||||
/**
|
||||
* 店主.
|
||||
*/
|
||||
STORE_OWNER,
|
||||
/**
|
||||
* 合作伙伴.
|
||||
*/
|
||||
PARTNER,
|
||||
/**
|
||||
* 总部.
|
||||
*/
|
||||
HEADQUARTER,
|
||||
/**
|
||||
* 品牌方.
|
||||
*/
|
||||
BRAND,
|
||||
/**
|
||||
* 分销商.
|
||||
*/
|
||||
DISTRIBUTOR,
|
||||
/**
|
||||
* 用户.
|
||||
*/
|
||||
USER,
|
||||
/**
|
||||
* 供应商.
|
||||
*/
|
||||
SUPPLIER,
|
||||
/**
|
||||
* 自定义.
|
||||
*/
|
||||
CUSTOM
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import cn.felord.payment.wechat.enumeration.ReceiverType;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 删除分账接收方API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class DelReceiversParams {
|
||||
/**
|
||||
* 应用ID,自动注入
|
||||
*/
|
||||
private String appid;
|
||||
/**
|
||||
* 分账接收方类型,必填
|
||||
*/
|
||||
private ReceiverType type;
|
||||
/**
|
||||
* 分账接收方帐号,必填
|
||||
*/
|
||||
private String account;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 直连商户请求分账API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class ProfitSharingOrder {
|
||||
/**
|
||||
* 应用ID,自动注入
|
||||
*/
|
||||
private String appid;
|
||||
/**
|
||||
* 微信订单号,必填
|
||||
*/
|
||||
private String transactionId;
|
||||
/**
|
||||
* 商户分账单号,必填
|
||||
* <p>
|
||||
* 商户系统内部的分账单号,在商户系统内部唯一,同一分账单号多次请求等同一次。
|
||||
* 只能是数字、大小写字母_-|*@
|
||||
*/
|
||||
private String outOrderNo;
|
||||
/**
|
||||
* 分账接收方列表,选填
|
||||
* <p>
|
||||
* 可以设置出资商户作为分账接受方,最多可有50个分账接收方
|
||||
*/
|
||||
private List<Receiver> receivers;
|
||||
/**
|
||||
* 是否解冻剩余未分资金,必填
|
||||
* <p>
|
||||
* <ol>
|
||||
* <li>如果为{@code true},该笔订单剩余未分账的金额会解冻回分账方商户;</li>
|
||||
* <li>如果为{@code false},该笔订单剩余未分账的金额不会解冻回分账方商户,可以对该笔订单再次进行分账。</li>
|
||||
* </ol>
|
||||
*/
|
||||
private Boolean unfreezeUnsplit;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2019-2020 felord.cn
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* Website:
|
||||
* https://felord.cn
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import cn.felord.payment.wechat.v2.model.allocation.Receiver;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 微信支付分账通知参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class ProfitsharingConsumeData {
|
||||
|
||||
/**
|
||||
* 直连商户号.
|
||||
* <p>
|
||||
* 直连模式分账发起和出资商户
|
||||
*/
|
||||
private String mchid;
|
||||
|
||||
/**
|
||||
* 微信订单号.
|
||||
* <p>
|
||||
* 微信支付订单号
|
||||
*/
|
||||
private String transactionId;
|
||||
|
||||
/**
|
||||
* 微信分账/回退单号.
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 商户分账/回退单号.
|
||||
* <p>
|
||||
* 分账方系统内部的分账/回退单号
|
||||
*/
|
||||
private String outOrderNo;
|
||||
|
||||
/**
|
||||
* 分账接收方.
|
||||
* <p>
|
||||
* 分账接收方对象
|
||||
*/
|
||||
private List<Receiver> receivers;
|
||||
|
||||
/**
|
||||
* 成功时间.
|
||||
* <p>
|
||||
* Rfc3339标准
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
|
||||
private LocalDateTime successTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 查询分账结果API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class QueryOrderParams {
|
||||
/**
|
||||
* 商户分账单号,必填
|
||||
*/
|
||||
private String outOrderNo;
|
||||
/**
|
||||
* 微信订单号,必填
|
||||
*/
|
||||
private String transactionId;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 查询分账回退结果API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class QueryReturnOrderParams {
|
||||
/**
|
||||
* 商户回退单号,必填
|
||||
*/
|
||||
private String outReturnNo;
|
||||
/**
|
||||
* 商户分账单号,必填
|
||||
*/
|
||||
private String outOrderNo;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import cn.felord.payment.wechat.enumeration.ReceiverType;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 分账接收方信息
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class Receiver {
|
||||
/**
|
||||
* 分账接收方类型,必填
|
||||
*/
|
||||
private ReceiverType type;
|
||||
/**
|
||||
* 分账接收方帐号,必填
|
||||
*/
|
||||
private String account;
|
||||
/**
|
||||
* 分账个人接收方姓名,选填
|
||||
* <p>
|
||||
* 在接收方类型为个人的时可选填,若有值,会检查与 name 是否实名匹配,不匹配会拒绝分账请求
|
||||
* <ol>
|
||||
* <li>分账接收方类型是{@code PERSONAL_OPENID},是个人姓名的密文(选传,传则校验) 此字段的加密方法详见:敏感信息加密说明</li>
|
||||
* <li>使用微信支付平台证书中的公钥</li>
|
||||
* <li>使用RSAES-OAEP算法进行加密</li>
|
||||
* <li>将请求中HTTP头部的Wechatpay-Serial设置为证书序列号</li>
|
||||
* </ol>
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 分账金额,必填
|
||||
* <p>
|
||||
* 单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
|
||||
*/
|
||||
private Integer amount;
|
||||
/**
|
||||
* 分账的原因描述,必填。分账账单中需要体现
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 请求分账回退API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class ReturnOrdersParams {
|
||||
/**
|
||||
* 微信分账单号,同{@link #outOrderNo} 二选一
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 商户分账单号,同{@link #orderId} 二选一
|
||||
*/
|
||||
private String outOrderNo;
|
||||
/**
|
||||
* 商户回退单号,必填
|
||||
*/
|
||||
private String outReturnNo;
|
||||
/**
|
||||
* 回退商户号,必填
|
||||
* <p>
|
||||
* 分账回退的出资商户,只能对原分账请求中成功分给商户接收方进行回退
|
||||
*/
|
||||
private String returnMchid;
|
||||
/**
|
||||
* 回退金额,必填
|
||||
* <p>
|
||||
* 需要从分账接收方回退的金额,单位为分,只能为整数,不能超过原始分账单分出给该接收方的金额
|
||||
*/
|
||||
private Integer amount;
|
||||
/**
|
||||
* 回退描述,必填
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.felord.payment.wechat.v3.model.profitsharing;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 解冻剩余资金API-请求参数
|
||||
*
|
||||
* @author felord.cn
|
||||
* @since 1.0.11.RELEASE
|
||||
*/
|
||||
@Data
|
||||
public class UnfreezeParams {
|
||||
/**
|
||||
* 微信订单号,必填
|
||||
*/
|
||||
private String transactionId;
|
||||
/**
|
||||
* 商户分账单号,必填
|
||||
*/
|
||||
private String outOrderNo;
|
||||
/**
|
||||
* 分账描述,必填
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
Reference in New Issue
Block a user