feat: 实现电商收付通功能,补充优化一些接口,增加了部分缺失回调

- 实现电商收付通
- 兼容较低版本的jackson
- 服务商分账新增下载账单
- 增加服务商退款回调
- 一些其它问题
This commit is contained in:
Fang
2022-06-20 10:26:57 +08:00
parent 89f12df44a
commit d8ada58822
54 changed files with 2779 additions and 29 deletions

View File

@@ -48,6 +48,9 @@
- `WechatBatchTransferApi` 微信支付V3批量转账到零钱
- `WechatPartnerSpecialMchApi` 微信支付V3服务商商户进件
- `WechatMediaApi` 微信支付V3媒体上传
- `WechatEcommerceApi` 电商收付通
- `WechatSmartGuideApi` 服务商或者直连商户-经营能力-支付即服务
- `WechatGoldPlanApi` 服务商-经营能力-点金计划
> 随着版本迭代功能会增加。

View File

@@ -767,9 +767,196 @@ public enum WechatPayV3Type {
* @since 1.0.14.RELEASE
*/
GOLD_PLAN_ADV_CLOSE(HttpMethod.POST, "%s/v3/goldplan/merchants/close-advertising-show"),
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 行业方案-电商收付通-商户进件-二级商户进件申请API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_APPLYMENT(HttpMethod.POST, "%s/v3/ecommerce/applyments/"),
/**
* 行业方案-电商收付通-商户进件-查询申请状态-通过申请单ID查询申请状态API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_APPLYMENT_ID(HttpMethod.GET, "%s/v3/ecommerce/applyments/{applyment_id}"),
/**
* 行业方案-电商收付通-商户进件-查询申请状态-通过业务申请编号查询申请状态API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_APPLYMENT_OUT_REQUEST_NO(HttpMethod.GET, "%s/v3/ecommerce/applyments/out-request-no/{out_request_no}"),
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 行业方案-电商收付通-分账-请求分账API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_ORDERS(HttpMethod.POST, "%s/v3/ecommerce/profitsharing/orders"),
/**
* 行业方案-电商收付通-分账-查询分账结果API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_RESULT(HttpMethod.GET, "%s/v3/ecommerce/profitsharing/orders"),
/**
* 行业方案-电商收付通-分账-请求分账回退API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_RETURN_ORDERS(HttpMethod.POST, "%s/v3/ecommerce/profitsharing/returnorders"),
/**
* 行业方案-电商收付通-分账-查询分账回退结果API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_RETURN_ORDERS_RESULT(HttpMethod.GET, "%s/v3/ecommerce/profitsharing/returnorders"),
/**
* 行业方案-电商收付通-分账-完结分账API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_FINISH_ORDER(HttpMethod.POST, "%s/v3/ecommerce/profitsharing/finish-order"),
/**
* 行业方案-电商收付通-分账-查询订单剩余待分金额API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_ORDER_AMOUNTS(HttpMethod.GET, "%s/v3/ecommerce/profitsharing/orders/{transaction_id}/amounts"),
/**
* 行业方案-电商收付通-分账-添加分账接收方API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_RECEIVERS_ADD(HttpMethod.POST, "%s/v3/ecommerce/profitsharing/receivers/add"),
/**
* 行业方案-电商收付通-分账-添加分账接收方API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_PROFITSHARING_RECEIVERS_DELETE(HttpMethod.POST, "%s/v3/ecommerce/profitsharing/receivers/delete"),
/**
* 行业方案-电商收付通-补差-请求补差API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_SUBSIDIES_CREATE(HttpMethod.POST, "%s/v3/ecommerce/subsidies/create"),
/**
* 行业方案-电商收付通-补差-请求补差回退API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_SUBSIDIES_RETURN(HttpMethod.POST, "%s/v3/ecommerce/subsidies/return"),
/**
* 行业方案-电商收付通-补差-取消补差API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_SUBSIDIES_CANCEL(HttpMethod.POST, "%s/v3/ecommerce/subsidies/cancel"),
/**
* 行业方案-电商收付通-退款-申请退款API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_REFUNDS_APPLY(HttpMethod.POST, "%s/v3/ecommerce/refunds/apply"),
/**
* 行业方案-电商收付通-退款-查询退款API-通过微信支付退款单号查询退款.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_REFUNDS_ID(HttpMethod.GET, "%s/v3/ecommerce/refunds/id/{refund_id}"),
/**
* 行业方案-电商收付通-退款-查询退款API-通过商户退款单号查询退款.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_REFUNDS_OUT_REFUND_NO(HttpMethod.GET, "%s/v3/ecommerce/refunds/out-refund-no/{out_refund_no}"),
/**
* 行业方案-电商收付通-退款-垫付退款回补API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_REFUNDS_RETURN_ADVANCE(HttpMethod.POST, "%s/v3/ecommerce/refunds/{refund_id}/return-advance"),
/**
* 行业方案-电商收付通-退款-查询垫付回补结果API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_REFUNDS_RETURN_ADVANCE_RESULT(HttpMethod.GET, "%s/v3/ecommerce/refunds/{refund_id}/return-advance"),
/**
* 行业方案-电商收付通-余额查询-查询二级商户账户实时余额API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_BALANCE_REAL_TIME(HttpMethod.GET, "%s/v3/ecommerce/fund/balance/{sub_mchid}"),
/**
* 行业方案-电商收付通-余额查询-查询二级商户账户日终余额API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_BALANCE_END_DAY(HttpMethod.GET, "%s/v3/ecommerce/fund/enddaybalance/{sub_mchid}"),
/**
* 行业方案-电商收付通-余额查询-查询电商平台账户实时余额API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_BALANCE_TYPE_REAL_TIME(HttpMethod.GET, "%s/v3/merchant/fund/balance/{account_type}"),
/**
* 行业方案-电商收付通-余额查询-查询电商平台账户日终余额API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_BALANCE_TYPE_END_DAY(HttpMethod.GET, "%s/v3/merchant/fund/dayendbalance/{account_type}"),
/**
* 行业方案-电商收付通-商户提现-二级商户预约提现.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_WITHDRAW(HttpMethod.POST, "%s/v3/ecommerce/fund/withdraw"),
/**
* 行业方案-电商收付通-商户提现-二级商户查询预约提现状态API-微信支付预约提现单号查询.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_WITHDRAW_ID(HttpMethod.GET, "%s/v3/ecommerce/fund/withdraw/{withdraw_id}"),
/**
* 行业方案-电商收付通-商户提现-二级商户查询预约提现状态API-商户预约提现单号查询.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_WITHDRAW_OUT_REQUEST_NO(HttpMethod.GET, "%s/v3/ecommerce/fund/withdraw/out-request-no/{out_request_no}"),
/**
* 行业方案-电商收付通-商户提现-电商平台预约提现API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_MERCHANT_WITHDRAW(HttpMethod.POST, "%s/v3/merchant/fund/withdraw"),
/**
* 行业方案-电商收付通-商户提现-电商平台查询预约提现状态API-微信支付预约提现单号查询.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_MERCHANT_WITHDRAW_ID(HttpMethod.GET, "%s/v3/merchant/fund/withdraw/withdraw-id/{withdraw_id}"),
/**
* 行业方案-电商收付通-商户提现-电商平台查询预约提现状态API-商户预约提现单号查询.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_WITHDRAW_MERCHANT_OUT_REQUEST_NO(HttpMethod.GET, "%s/v3/merchant/fund/withdraw/out-request-no/{out_request_no}"),
/**
* 行业方案-电商收付通-商户提现-按日下载提现异常文件API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_WITHDRAW_ERROR_BILL(HttpMethod.GET, "%s/v3/merchant/fund/withdraw/bill-type/{bill_type}"),
/**
* 行业方案-电商收付通-下载账单-申请二级商户资金账单API.
*
* @since 1.0.14.RELEASE
*/
ECOMMERCE_FUND_FLOW_BILL(HttpMethod.GET, "%s/v3/ecommerce/bill/fundflowbill")
;
/**
* The Pattern.
*

View File

@@ -24,7 +24,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -38,8 +38,10 @@ import java.util.List;
*
* @author felord.cn
* @since 1.0.10.RELEASE
* @deprecated since 1.0.14.RELEASE 直连使用{@link cn.felord.payment.wechat.v3.WechatProfitsharingApi}、服务商使用{@link cn.felord.payment.wechat.v3.WechatPartnerProfitsharingApi}
*/
@Slf4j
@Deprecated
public class WechatAllocationApi {
/**
* The constant MAPPER.
@@ -47,7 +49,7 @@ public class WechatAllocationApi {
private static final ObjectMapper MAPPER = new ObjectMapper();
static {
MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
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)

View File

@@ -24,7 +24,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import lombok.Getter;
import lombok.SneakyThrows;
@@ -79,11 +79,11 @@ public abstract class BaseModel {
// 忽略null
XML_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL)
// 属性使用 驼峰首字母小写
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
OBJECT_MAPPER
// .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
}

View File

@@ -30,7 +30,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.core.io.Resource;
@@ -94,7 +94,7 @@ public abstract class AbstractApi {
* @param mapper the mapper
*/
private void applyObjectMapper(ObjectMapper mapper) {
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE
)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// empty string error

View File

@@ -22,6 +22,7 @@ import cn.felord.payment.wechat.v2.WechatAllocationApi;
import cn.felord.payment.wechat.v2.WechatPayRedpackApi;
import cn.felord.payment.wechat.v2.WechatPayTransfersApi;
import cn.felord.payment.wechat.v2.WechatV2Client;
import cn.felord.payment.wechat.v3.ecommerce.WechatEcommerceApi;
/**
* 微信支付工具.
@@ -195,7 +196,9 @@ public class WechatApiProvider {
* @param tenantId the tenant id
* @return wechat allocation api
* @since 1.0.10.RELEASE
* @deprecated since 1.0.14.RELEASE 直连使用{@link WechatApiProvider#profitsharingApi(String)}、服务商使用{@link WechatApiProvider#partnerProfitsharingApi(String)}
*/
@Deprecated
public WechatAllocationApi allocationApi(String tenantId) {
WechatMetaBean wechatMeta = wechatPayClient.signatureProvider()
.wechatMetaContainer()
@@ -229,6 +232,7 @@ public class WechatApiProvider {
*
* @param tenantId the tenant id
* @return wechat partner special mch api
* @since 1.0.14.RELEASE
*/
public WechatPartnerSpecialMchApi partnerSpecialMchApi(String tenantId) {
return new WechatPartnerSpecialMchApi(wechatPayClient, tenantId);
@@ -239,6 +243,7 @@ public class WechatApiProvider {
*
* @param tenantId the tenant id
* @return wechat smart guide api
* @since 1.0.14.RELEASE
*/
public WechatSmartGuideApi smartGuideApi(String tenantId) {
return new WechatSmartGuideApi(wechatPayClient, tenantId);
@@ -249,16 +254,29 @@ public class WechatApiProvider {
*
* @param tenantId the tenant id
* @return the wechat gold plan api
* @since 1.0.14.RELEASE
*/
public WechatGoldPlanApi goldPlanApi(String tenantId) {
return new WechatGoldPlanApi(wechatPayClient, tenantId);
}
/**
* 服务商-行业方案-电商收付通
*
* @param tenantId the tenant id
* @return the wechat ecommerce api
* @since 1.0.14.RELEASE
*/
public WechatEcommerceApi ecommerceApi(String tenantId) {
return new WechatEcommerceApi(wechatPayClient, tenantId);
}
/**
* 其它能力-媒体上传
*
* @param tenantId the tenant id
* @return the wechat media api
* @since 1.0.14.RELEASE
*/
public WechatMediaApi mediaApi(String tenantId) {
return new WechatMediaApi(wechatPayClient, tenantId);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 felord.cn
* Copyright 2019-2022 felord.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -17,11 +17,15 @@
package cn.felord.payment.wechat.v3;
import cn.felord.payment.wechat.WechatPayProperties;
import cn.felord.payment.wechat.enumeration.ReceiverType;
import cn.felord.payment.wechat.enumeration.TarType;
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.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -30,7 +34,10 @@ import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.security.cert.X509Certificate;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -117,9 +124,8 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
this.client().withType(WechatPayV3Type.PROFITSHARING_ORDERS_RESULT, queryOrderParams)
.function((wechatPayV3Type, params) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("sub_mchid", params.getSubMchid());
queryParams.add("transaction_id", params.getTransactionId());
Optional.ofNullable(params.getSubMchid())
.ifPresent(mchId -> queryParams.add("sub_mchid", params.getSubMchid()));
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
@@ -291,9 +297,9 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
final X509Certificate x509Certificate = certificate.getX509Certificate();
params.setAppid(v3.getAppId());
String name = params.getName();
if (StringUtils.hasText(name)) {
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
if (ReceiverType.MERCHANT_ID.equals(params.getType())) {
String encryptedName = signatureProvider.encryptRequestMessage(params.getName(), x509Certificate);
params.setName(encryptedName);
}
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
@@ -331,4 +337,42 @@ public class WechatPartnerProfitsharingApi extends AbstractApi {
.request();
return wechatResponseEntity;
}
/**
* 申请分账账单API
*
* @param billParams the bill params
* @return the response entity
*/
public ResponseEntity<Resource> downloadMerchantBills(PartnerProfitsharingBillParams billParams){
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.PROFITSHARING_BILLS,billParams)
.function(((wechatPayV3Type, params) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
String subMchid = params.getSubMchid();
if (subMchid !=null){
queryParams.add("sub_mchid",subMchid);
}
LocalDate billDate = params.getBillDate();
queryParams.add("bill_date", billDate.format(DateTimeFormatter.ISO_DATE));
TarType tarType = params.getTarType();
if (Objects.nonNull(tarType)) {
queryParams.add("tar_type", tarType.name());
}
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.toUri();
return Get(uri);
})).consumer(wechatResponseEntity::convert)
.request();
String downloadUrl = Objects.requireNonNull(wechatResponseEntity.getBody())
.get("download_url")
.asText();
String ext = Objects.equals(TarType.GZIP, billParams.getTarType()) ? ".gzip" : ".txt";
String filename = "profitsharingbill-" + billParams.getBillDate().toString() + ext;
return this.downloadBillResponse(downloadUrl, filename);
}
}

View File

@@ -20,6 +20,7 @@ package cn.felord.payment.wechat.v3;
import cn.felord.payment.PayException;
import cn.felord.payment.wechat.v3.model.CallbackParams;
import cn.felord.payment.wechat.v3.model.CouponConsumeData;
import cn.felord.payment.wechat.v3.model.PartnerRefundConsumeData;
import cn.felord.payment.wechat.v3.model.ProfitSharingConsumeData;
import cn.felord.payment.wechat.v3.model.RefundConsumeData;
import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams;
@@ -36,12 +37,13 @@ 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.payscore.parking.ParkingCallback;
import cn.felord.payment.wechat.v3.model.payscore.parking.TransParkingCallback;
import cn.felord.payment.wechat.v3.model.profitsharing.PartnerProfitsharingConsumeData;
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;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -78,7 +80,7 @@ public class WechatPayCallback {
private final String tenantId;
static {
MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
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)
@@ -243,7 +245,8 @@ public class WechatPayCallback {
* <li>如果在所有通知频率后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。</li>
* </ul>
* 特别提醒:商户系统对于支付成功通知的内容一定要做签名验证,并校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。
* @param params the params
*
* @param params the params
* @param transParkingCallbackConsumer the transParkingCallbackConsumer
* @return the map
* @since 1.0.13.RELEASE
@@ -388,7 +391,35 @@ public class WechatPayCallback {
}
/**
* 微信支付分账V3动账通知
* 服务商退款结果通知API电商收付通复用
* <p>
* 退款状态改变后,微信会把相关退款结果发送给商户。
*
* @param params the params
* @param consumeDataConsumer the consume data consumer
* @return map map
*/
@SneakyThrows
public Map<String, String> partnerRefundCallback(ResponseSignVerifyParams params, Consumer<PartnerRefundConsumeData> consumeDataConsumer) {
CallbackParams callbackParams = resolve(params);
String eventType = callbackParams.getEventType();
if (!(Objects.equals(eventType, EventType.REFUND_CLOSED.event) ||
Objects.equals(eventType, EventType.REFUND_ABNORMAL.event) ||
Objects.equals(eventType, EventType.REFUND_SUCCESS.event))) {
log.error("wechat pay event type is not matched, callbackParams {}", callbackParams);
throw new PayException(" wechat pay event type is not matched");
}
String data = this.decrypt(callbackParams);
PartnerRefundConsumeData consumeData = MAPPER.readValue(data, PartnerRefundConsumeData.class);
consumeDataConsumer.accept(consumeData);
return response();
}
/**
* 直连商户-微信支付分账V3动账通知
*
* @param params the params
* @param profitsharingConsumeDataConsumer the profitsharing consume data consumer
@@ -402,6 +433,22 @@ public class WechatPayCallback {
return response();
}
/**
* 服务商-微信支付分账V3动账通知电商收付通复用
*
* @param params the params
* @param profitsharingConsumeDataConsumer the profitsharing consume data consumer
* @return map map
* @since 1.0.14.RELEASE
*/
@SneakyThrows
public Map<String, String> partnerProfitsharingCallback(ResponseSignVerifyParams params, Consumer<PartnerProfitsharingConsumeData> profitsharingConsumeDataConsumer) {
String callback = this.callback(params, EventType.TRANSACTION_SUCCESS);
PartnerProfitsharingConsumeData consumeData = MAPPER.readValue(callback, PartnerProfitsharingConsumeData.class);
profitsharingConsumeDataConsumer.accept(consumeData);
return response();
}
/**
* Callback.
*

View File

@@ -22,7 +22,9 @@ 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.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -316,7 +318,7 @@ public class WechatProfitsharingApi extends AbstractApi {
* @return the wechat response entity
* @since 1.0.13.RELEASE
*/
public WechatResponseEntity<ObjectNode> downloadMerchantBills(ProfitsharingBillParams billParams){
public ResponseEntity<Resource> downloadMerchantBills(ProfitsharingBillParams billParams){
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.PROFITSHARING_BILLS,billParams)
.function(((wechatPayV3Type, params) -> {
@@ -335,7 +337,13 @@ public class WechatProfitsharingApi extends AbstractApi {
return Get(uri);
})).consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
String downloadUrl = Objects.requireNonNull(wechatResponseEntity.getBody())
.get("download_url")
.asText();
String ext = Objects.equals(TarType.GZIP, billParams.getTarType()) ? ".gzip" : ".txt";
String filename = "profitsharingbill-" + billParams.getBillDate().toString() + ext;
return this.downloadBillResponse(downloadUrl, filename);
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.SignatureProvider;
import cn.felord.payment.wechat.v3.WechatPartnerSpecialMchApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.X509WechatCertificateInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.AccountInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceApplymentParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceContactInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceIdCardInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceIdDocInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.UboInfo;
import cn.felord.payment.wechat.v3.model.specmch.SubMchModifyParams;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.http.HttpHeaders;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.security.cert.X509Certificate;
/**
* 电商收付通-商户进件
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class ApplymentApi extends AbstractApi {
private final WechatPartnerSpecialMchApi wechatPartnerSpecialMchApi;
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
ApplymentApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
this.wechatPartnerSpecialMchApi = new WechatPartnerSpecialMchApi(wechatPayClient, tenantId);
}
/**
* 二级商户进件申请API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> apply(EcommerceApplymentParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_APPLYMENT, params)
.function((wechatPayV3Type, applymentParams) -> {
SignatureProvider signatureProvider = this.client().signatureProvider();
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
final X509Certificate x509Certificate = certificate.getX509Certificate();
EcommerceApplymentParams applyRequestParams = this.convert(applymentParams, signatureProvider, x509Certificate);
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Wechatpay-Serial", certificate.getWechatPaySerial());
return Post(uri, applyRequestParams, httpHeaders);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 通过申请单ID查询申请状态API
*
* @param applymentId the applyment id
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByApplymentId(String applymentId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_APPLYMENT_ID, applymentId)
.function((type, id) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(id)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 通过业务申请编号查询申请状态API
*
* @param outRequestNo the outRequestNo
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByBusinessCode(String outRequestNo) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_APPLYMENT_OUT_REQUEST_NO, outRequestNo)
.function((type, id) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(id)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 修改结算账号API
*
* @param params the params
* @return wechat response entity
* @see WechatPartnerSpecialMchApi#modify(SubMchModifyParams)
*/
public WechatResponseEntity<ObjectNode> modify(SubMchModifyParams params) {
return this.wechatPartnerSpecialMchApi.modify(params);
}
/**
* 查询结算账户API
* <p>
* 服务商/电商平台(不包括支付机构、银行),可使用本接口,查询其进件且已签约特约商户/二级商户的结算账户信息(敏感信息掩码)。
* 该接口可用于核实是否成功修改结算账户信息、及查询系统汇款验证结果。
*
* @param subMchid the sub mchid
* @return the wechat response entity
* @see WechatPartnerSpecialMchApi#querySettlement(String)
*/
public WechatResponseEntity<ObjectNode> querySettlement(String subMchid) {
return this.wechatPartnerSpecialMchApi.querySettlement(subMchid);
}
private EcommerceApplymentParams convert(EcommerceApplymentParams applymentParams, SignatureProvider signatureProvider, X509Certificate x509Certificate) {
EcommerceIdCardInfo idCardInfo = applymentParams.getIdCardInfo();
if (idCardInfo != null) {
idCardInfo.setIdCardName(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardName(), x509Certificate));
idCardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(idCardInfo.getIdCardNumber(), x509Certificate));
}
EcommerceIdDocInfo idDocInfo = applymentParams.getIdDocInfo();
if (idDocInfo != null) {
idDocInfo.setIdDocName(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocName(), x509Certificate));
idDocInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(idDocInfo.getIdDocNumber(), x509Certificate));
}
UboInfo uboInfo = applymentParams.getUboInfo();
if (uboInfo != null) {
UboInfo.IdCardInfo cardInfo = uboInfo.getIdCardInfo();
if (cardInfo != null) {
cardInfo.setIdCardName(signatureProvider.encryptRequestMessage(cardInfo.getIdCardName(), x509Certificate));
cardInfo.setIdCardNumber(signatureProvider.encryptRequestMessage(cardInfo.getIdCardNumber(), x509Certificate));
}
UboInfo.IdDocInfo docInfo = uboInfo.getIdDocInfo();
if (docInfo != null) {
docInfo.setIdDocName(signatureProvider.encryptRequestMessage(docInfo.getIdDocName(), x509Certificate));
docInfo.setIdDocNumber(signatureProvider.encryptRequestMessage(docInfo.getIdDocNumber(), x509Certificate));
}
}
AccountInfo accountInfo = applymentParams.getAccountInfo();
if (accountInfo != null) {
accountInfo.setAccountName(signatureProvider.encryptRequestMessage(accountInfo.getAccountName(), x509Certificate));
accountInfo.setAccountNumber(signatureProvider.encryptRequestMessage(accountInfo.getAccountNumber(), x509Certificate));
}
EcommerceContactInfo contactInfo = applymentParams.getContactInfo();
contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), x509Certificate));
contactInfo.setContactIdCardNumber(signatureProvider.encryptRequestMessage(contactInfo.getContactIdCardNumber(), x509Certificate));
String contactEmail = contactInfo.getContactEmail();
if (contactEmail != null) {
contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactEmail, x509Certificate));
}
return applymentParams;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.FundFlowAccountType;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceFundEndDay;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceFundSubMch;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.time.format.DateTimeFormatter;
/**
* 电商收付通余额查询
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class BalanceApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
BalanceApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 查询二级商户账户实时余额API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryBySubMchid(EcommerceFundSubMch params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_BALANCE_REAL_TIME, params)
.function((type, fundSubMch) -> {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA));
if (params.getAccountType() != null) {
builder.queryParam("account_type", fundSubMch.getAccountType().name());
}
URI uri = builder
.build()
.expand(fundSubMch.getSubMchid())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询二级商户账户日终余额API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryAtEndDay(EcommerceFundEndDay params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_BALANCE_END_DAY, params)
.function((type, fundEndDay) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.queryParam("account_type", fundEndDay.getDate().format(DateTimeFormatter.ISO_DATE))
.build()
.expand(fundEndDay.getSubMchid())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询电商平台账户实时余额API
*
* @param type the type
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryBalanceAtRealTime(FundFlowAccountType type) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_BALANCE_TYPE_REAL_TIME, type)
.function((wechatPayV3Type, accountType) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.expand(accountType.name())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询电商平台账户实时余额API
*
* @param type the type
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryBalanceAtEndDay(FundFlowAccountType type) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_BALANCE_TYPE_END_DAY, type)
.function((wechatPayV3Type, accountType) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.expand(accountType.name())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.FundFlowAccountType;
import cn.felord.payment.wechat.enumeration.TarType;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.WechatPartnerProfitsharingApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.FundFlowBillParams;
import cn.felord.payment.wechat.v3.model.profitsharing.PartnerProfitsharingBillParams;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.Optional;
/**
* 电商收付通下载账单
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class DownloadApi extends AbstractApi {
private final WechatPartnerProfitsharingApi wechatPartnerProfitsharingApi;
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
DownloadApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
this.wechatPartnerProfitsharingApi = new WechatPartnerProfitsharingApi(wechatPayClient, tenantId);
}
/**
* 申请分账账单API
*
* @param params the params
* @return the response entity
*/
public ResponseEntity<Resource> downloadProfitsharingBills(PartnerProfitsharingBillParams params) {
return this.wechatPartnerProfitsharingApi.downloadMerchantBills(params);
}
/**
* 申请二级商户资金账单API
* <p>
* 过于复杂,需要合并文件并自行解密
*
* @param fundFlowBillParams the fund flow bill params
* @return response entity
*/
public WechatResponseEntity<ObjectNode> downloadMchFundFlowBill(FundFlowBillParams fundFlowBillParams) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_FLOW_BILL, fundFlowBillParams)
.function((wechatPayV3Type, params) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
LocalDate billDate = params.getBillDate();
queryParams.add("bill_date", billDate.format(DateTimeFormatter.ISO_DATE));
FundFlowAccountType accountType = Optional.ofNullable(params.getAccountType())
.orElse(FundFlowAccountType.BASIC);
queryParams.add("account_type", accountType.name());
TarType tarType = params.getTarType();
if (Objects.nonNull(tarType)) {
queryParams.add("tar_type", tarType.name());
}
queryParams.add("algorithm", "AEAD_AES_256_GCM");
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build().toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
}

View File

@@ -0,0 +1,303 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.WechatPayProperties;
import cn.felord.payment.wechat.enumeration.ReceiverType;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.SignatureProvider;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.X509WechatCertificateInfo;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceFinishOrder;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceProfitsharingOrder;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceReceiver;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceReceiverDeleteParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceReturnOrderParams;
import cn.felord.payment.wechat.v3.model.ecommerce.Receiver;
import cn.felord.payment.wechat.v3.model.profitsharing.PartnerQueryOrderParams;
import cn.felord.payment.wechat.v3.model.profitsharing.PartnerReturnOrdersParams;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.security.cert.X509Certificate;
import java.util.List;
/**
* 电商收付通分账
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class ProfitsharingApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
ProfitsharingApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 请求分账API
* <p>
* 微信订单支付成功后,商户发起分账请求,将结算后的资金分到分账接收方
*
* @param profitSharingOrder the profit sharing order
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> profitsharingOrders(EcommerceProfitsharingOrder profitSharingOrder) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_ORDERS, profitSharingOrder)
.function((wechatPayV3Type, params) -> {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
SignatureProvider signatureProvider = this.client().signatureProvider();
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
final X509Certificate x509Certificate = certificate.getX509Certificate();
params.setAppid(v3.getAppId());
List<Receiver> receivers = params.getReceivers();
if (!CollectionUtils.isEmpty(receivers)) {
receivers.forEach(receiversItem -> {
String name = receiversItem.getReceiverName();
if (StringUtils.hasText(name)) {
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
receiversItem.setReceiverName(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>
* 发起分账请求后,可调用此接口查询分账结果
* <p>
* 注意:
* <ul>
* <li>发起解冻剩余资金请求后,可调用此接口查询解冻剩余资金的结果</li>
* </ul>
*
* @param queryOrderParams the query order params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryProfitsharingOrder(PartnerQueryOrderParams queryOrderParams) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_RESULT, queryOrderParams)
.function((wechatPayV3Type, params) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("sub_mchid", params.getSubMchid());
queryParams.add("transaction_id", params.getTransactionId());
queryParams.add("out_order_no", params.getOutOrderNo());
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 请求分账回退API
* <p>
* 如果订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款
*
* @param returnOrdersParams the return orders params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> returnOrders(PartnerReturnOrdersParams returnOrdersParams) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_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(EcommerceReturnOrderParams queryReturnOrderParams) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_RETURN_ORDERS_RESULT, queryReturnOrderParams)
.function((wechatPayV3Type, params) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("sub_mchid", params.getSubMchid());
String orderId = params.getOrderId();
if (orderId != null) {
queryParams.add("out_order_no", orderId);
}
String outOrderNo = params.getOutOrderNo();
if (outOrderNo != null) {
queryParams.add("out_order_no", outOrderNo);
}
queryParams.add("out_return_no", params.getOutReturnNo());
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 完结分账API
* <p>
* 不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给二级商户。
*
* @param finishOrder the finish order
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> finishOrder(EcommerceFinishOrder finishOrder) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_FINISH_ORDER, finishOrder)
.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> queryOrderAmounts(String transactionId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_ORDER_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 ecommerceReceiver the ecommerce receiver
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> addReceivers(EcommerceReceiver ecommerceReceiver) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_PROFITSHARING_RECEIVERS_ADD, ecommerceReceiver)
.function((wechatPayV3Type, params) -> {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
params.setAppid(v3.getAppId());
SignatureProvider signatureProvider = this.client().signatureProvider();
X509WechatCertificateInfo certificate = signatureProvider.getCertificate(this.wechatMetaBean().getTenantId());
final X509Certificate x509Certificate = certificate.getX509Certificate();
String name = params.getName();
if (ReceiverType.PERSONAL_OPENID.equals(params.getType()) && StringUtils.hasText(name)) {
// 个人应该必传
String encryptedName = signatureProvider.encryptRequestMessage(name, x509Certificate);
params.setEncryptedName(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(EcommerceReceiverDeleteParams delReceiversParams) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_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;
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2019-2022 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.ecommerce;
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.AbstractApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceRefundParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceReturnAdvance;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.Collections;
/**
* 电商收付通退款
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class RefundsApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
RefundsApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 申请退款API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> apply(EcommerceRefundParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_REFUNDS_APPLY, params)
.function((wechatPayV3Type, refundParams) -> {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
refundParams.setSpAppid(v3.getAppId());
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, refundParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询退款API-通过微信支付退款单号查询退款
*
* @param refundId the refund id
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByRefundId(String refundId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_REFUNDS_ID, refundId)
.function((type, id) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(id)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询退款API-通过商户退款单号查询退款
*
* @param outRefundNo the out refund no
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByOutRefundNo(String outRefundNo) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_REFUNDS_OUT_REFUND_NO, outRefundNo)
.function((type, no) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(no)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 垫付退款回补API
* <p>
* 提交垫付退款后,发起退款方可通过该接口发起垫付退款资金回补,把退款垫付的资金从二级商户回补到电商平台账户。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> returnAdvance(EcommerceReturnAdvance params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_REFUNDS_RETURN_ADVANCE, params)
.function((wechatPayV3Type, advanceParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.expand(advanceParams.getRefundId())
.toUri();
return Post(uri, Collections.singletonMap("sub_mchid", advanceParams.getSubMchid()));
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询垫付回补结果API
* <p>
* 提交垫付退款回补后,通过调用该接口查询垫付回补结果。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryAdvanceResult(EcommerceReturnAdvance params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_REFUNDS_RETURN_ADVANCE_RESULT, params)
.function((type, returnAdvance) -> {
LinkedMultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("refund_id",returnAdvance.getRefundId());
queryParams.add("sub_mchid",returnAdvance.getSubMchid());
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceSubsidiesCancelParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceSubsidiesCreateParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceSubsidiesReturnParams;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
/**
* 电商收付通-补差
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
class SubsidiesApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
SubsidiesApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 请求补差API
* <p>
* 服务商下单的时候带上补差标识,微信订单支付成功并结算完成后,发起分账前,调用该口进行补差。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> create(EcommerceSubsidiesCreateParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_SUBSIDIES_CREATE, params)
.function((wechatPayV3Type, createParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, createParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 请求补差回退API
* <p>
* 订单发送退款的时候,可以对补贴成功的补差单发起回退。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> spreadBack(EcommerceSubsidiesReturnParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_SUBSIDIES_RETURN, params)
.function((wechatPayV3Type, returnParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, returnParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 取消补差API
* <p>
* 对带有补差标识的订单,如果不需要补差,可在发起分账前,可调用这个接口进行取消补差。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> cancel(EcommerceSubsidiesCancelParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_SUBSIDIES_CANCEL, params)
.function((wechatPayV3Type, returnParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, returnParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.v3.WechatCombinePayApi;
import cn.felord.payment.wechat.v3.WechatPartnerPayApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
/**
* 电商收付通.
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
public class WechatEcommerceApi {
private final WechatPayClient wechatPayClient;
private final String tenantId;
/**
* Instantiates a new Wechat ecommerce api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
public WechatEcommerceApi(WechatPayClient wechatPayClient, String tenantId) {
this.wechatPayClient = wechatPayClient;
this.tenantId = tenantId;
}
/**
* 商户进件
*
* @return the applyment api
*/
public ApplymentApi applyment() {
return new ApplymentApi(this.wechatPayClient, this.tenantId);
}
/**
* 普通支付
*
* @return the wechat partner pay api
*/
public WechatPartnerPayApi partnerPay() {
return new WechatPartnerPayApi(this.wechatPayClient, this.tenantId);
}
/**
* 合单支付
*
* @return the WechatCombinePayApi
*/
public WechatCombinePayApi combinePay() {
return new WechatCombinePayApi(this.wechatPayClient, this.tenantId);
}
/**
* 分账
*
* @return the profitsharing api
*/
public ProfitsharingApi profitsharing() {
return new ProfitsharingApi(this.wechatPayClient, this.tenantId);
}
/**
* 补差
*
* @return the subsidies api
*/
public SubsidiesApi subsidies() {
return new SubsidiesApi(this.wechatPayClient, this.tenantId);
}
/**
* 退款
*
* @return the refunds api
*/
public RefundsApi refunds() {
return new RefundsApi(this.wechatPayClient, this.tenantId);
}
/**
* 余额查询
*
* @return the balance api
*/
public BalanceApi balance() {
return new BalanceApi(this.wechatPayClient, this.tenantId);
}
/**
* 商户提现
*
* @return the withdraw api
*/
public WithDrawApi withDraw() {
return new WithDrawApi(this.wechatPayClient, this.tenantId);
}
/**
* 下载账单
*
* @return the withdraw api
*/
public DownloadApi download() {
return new DownloadApi(this.wechatPayClient, this.tenantId);
}
}

View File

@@ -0,0 +1,223 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.TarType;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.AbstractApi;
import cn.felord.payment.wechat.v3.WechatPayClient;
import cn.felord.payment.wechat.v3.WechatResponseEntity;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceErrorBillParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceMchReserveParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceOutRequestNo;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceReserveParams;
import cn.felord.payment.wechat.v3.model.ecommerce.EcommerceWithdraw;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
/**
* 电商收付通-商户提现
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
public class WithDrawApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
public WithDrawApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 二级商户预约提现API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> ecommerceReserve(EcommerceReserveParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_WITHDRAW, params)
.function((wechatPayV3Type, refundParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, refundParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 二级商户查询预约提现状态API-微信支付预约提现单号查询
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByWithdrawId(EcommerceWithdraw params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_WITHDRAW_ID, params)
.function((type, ecommerceWithdraw) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.queryParam("sub_mchid", ecommerceWithdraw.getSubMchid())
.build()
.expand(ecommerceWithdraw.getWithdrawId())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 二级商户查询预约提现状态API-商户预约提现单号查询
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryByOutRequestNo(EcommerceOutRequestNo params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_WITHDRAW_OUT_REQUEST_NO, params)
.function((type, ecommerceWithdraw) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.queryParam("sub_mchid", ecommerceWithdraw.getSubMchid())
.build()
.expand(ecommerceWithdraw.getOutRequestNo())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 电商平台预约提现API
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> ecommerceMchReserve(EcommerceMchReserveParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_MERCHANT_WITHDRAW, params)
.function((wechatPayV3Type, refundParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, refundParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 电商平台查询预约提现状态API-微信支付预约提现单号查询
*
* @param withdrawId the withdraw id
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryMchByWithdrawId(String withdrawId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_MERCHANT_WITHDRAW_ID, withdrawId)
.function((type, id) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(withdrawId)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 电商平台查询预约提现状态API-商户预约提现单号查询
*
* @param outRequestNo the out request no
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryMchByOutRequestNo(String outRequestNo) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_WITHDRAW_MERCHANT_OUT_REQUEST_NO, outRequestNo)
.function((type, no) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(no)
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 按日下载提现异常文件API
* <p>
* 电商服务商按日查询并下载提现状态为异常的提现单,提现异常包括提现失败和银行退票。
*
* @param params the params
* @return the response entity
*/
public ResponseEntity<Resource> downloadErrorBill(EcommerceErrorBillParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.ECOMMERCE_FUND_WITHDRAW_ERROR_BILL, params)
.function((wechatPayV3Type, errorBillParams) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
LocalDate billDate = params.getBillDate();
queryParams.add("bill_date", billDate.format(DateTimeFormatter.ISO_DATE));
TarType tarType = params.getTarType();
if (Objects.nonNull(tarType)) {
queryParams.add("tar_type", tarType.name());
}
URI uri = UriComponentsBuilder.fromHttpUrl(wechatPayV3Type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.expand("NO_SUCC")
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
String downloadUrl = Objects.requireNonNull(wechatResponseEntity.getBody())
.get("download_url")
.asText();
String ext = Objects.equals(TarType.GZIP, params.getTarType()) ? ".gzip" : ".txt";
String filename = "errorbill-" + params.getBillDate().toString() + ext;
return downloadBillResponse(downloadUrl, filename);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2019-2022 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;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class PartnerRefundConsumeData {
private String transactionId;
private Amount amount;
private String outTradeNo;
private String refundStatus;
private String outRefundNo;
private String refundAccount;
private String spMchid;
private String subMchid;
private String successTime;
private String userReceivedAccount;
private String refundId;
/**
* 微信支付退款金额信息
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public static class Amount {
/**
* 订单金额,单位为分
*/
private Integer total;
/**
* 退款金额,单位为分
*/
private Integer refund;
/**
* 用户实际支付金额,单位为分
*/
private Integer payerTotal;
/**
* 退款给用户的金额,单位为分,不包含所有优惠券金额
*/
private Integer payerRefund;
}
}

View File

@@ -18,7 +18,7 @@
*/
package cn.felord.payment.wechat.v3.model;
import cn.felord.payment.wechat.v2.model.allocation.Receiver;
import cn.felord.payment.wechat.v3.model.profitsharing.Receiver;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.v3.model.specmch.AccountCertInfo;
import lombok.Data;
/**
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class AccountInfo{
private String bankAccountType;
private String accountBank;
private String accountName;
private String bankAddressCode;
private String bankBranchId;
private String bankName;
private String accountNumber;
private AccountCertInfo accountCertInfo;
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
@Data
public class EcommerceAmount {
private Integer total;
private String currency;
private Integer refund;
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.ContactType;
import cn.felord.payment.wechat.enumeration.IdDocType;
import cn.felord.payment.wechat.v3.model.specmch.FinanceInstitutionInfo;
import lombok.Data;
/**
* 二级商户进件申请API请求参数
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceApplymentParams{
private String outRequestNo;
private String organizationType;
private Boolean financeInstitution;
private EcommerceBusinessLicenseInfo businessLicenseInfo;
private FinanceInstitutionInfo financeInstitutionInfo;
private ContactType idHolderType;
private IdDocType idDocType;
private String authorizeLetterCopy;
private EcommerceIdCardInfo idCardInfo;
private EcommerceIdDocInfo idDocInfo;
private Boolean owner;
private UboInfo uboInfo;
private Boolean needAccountInfo;
private AccountInfo accountInfo;
private EcommerceContactInfo contactInfo;
private SalesSceneInfo salesSceneInfo;
private EcommerceSettlementInfo settlementInfo;
private String merchantShortname;
private String qualifications;
private String businessAdditionPics;
private String businessAdditionDesc;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceBusinessLicenseInfo {
private String businessLicenseCopy;
private String businessLicenseNumber;
private String merchantName;
private String legalPerson;
private String companyAddress;
private String businessTime;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
@Data
public class EcommerceContactInfo {
private String contactType;
private String contactName;
private String contactIdCardNumber;
private String mobilePhone;
private String contactEmail;
}

View File

@@ -0,0 +1,45 @@
/*
*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.TarType;
import lombok.Data;
import java.time.LocalDate;
/**
* 按日下载提现异常文件API
*
* @author felord.cn
* @since 1.0.3.RELEASE
*/
@Data
public class EcommerceErrorBillParams {
/**
* 账单日期,必传。
* <p>
* 格式yyyy-MM-DD仅支持三个月内的账单下载申请。
*/
private LocalDate billDate;
/**
* 压缩类型,不填默认值为数据流
*
* @see TarType
*/
private TarType tarType;
}

View File

@@ -0,0 +1,11 @@
package cn.felord.payment.wechat.v3.model.ecommerce;
import lombok.Data;
@Data
public class EcommerceFinishOrder{
private String subMchid;
private String transactionId;
private String outOrderNo;
private String description;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
import java.time.LocalDate;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceFundEndDay {
private String subMchid;
private LocalDate date;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.FundFlowAccountType;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceFundSubMch {
private String subMchid;
private FundFlowAccountType accountType;
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
import java.time.LocalDate;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceIdCardInfo {
private String idCardCopy;
private String idCardNational;
private String idCardName;
private String idCardNumber;
private LocalDate idCardValidTime;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
import java.time.LocalDate;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceIdDocInfo {
private String idDocName;
private String idDocNumber;
private String idDocCopy;
private LocalDate docPeriodEnd;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.FundFlowAccountType;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceMchReserveParams {
private String outRequestNo;
private Integer amount;
private String remark;
private String bankMemo;
private FundFlowAccountType accountType;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceOutRequestNo {
private String subMchid;
private String outRequestNo;
}

View File

@@ -0,0 +1,15 @@
package cn.felord.payment.wechat.v3.model.ecommerce;
import lombok.Data;
import java.util.List;
@Data
public class EcommerceProfitsharingOrder {
private String appid;
private String subMchid;
private String transactionId;
private String outOrderNo;
private List<Receiver> receivers;
private Boolean finish;
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.ReceiverType;
import lombok.Data;
/**
* The type Ecommerce receiver.
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceReceiver {
private String appid;
private ReceiverType type;
private String account;
private String name;
private String encryptedName;
private RelationType relationType;
/**
* The enum Relation type.
*/
public enum RelationType {
/**
* 供应商
*/
SUPPLIER,
/**
* 分销商
*/
DISTRIBUTOR,
/**
* 服务商
*/
SERVICE_PROVIDER,
/**
* 平台
*/
PLATFORM,
/**
* 其它
*/
OTHERS, }
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.ReceiverType;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceReceiverDeleteParams {
private String appid;
private ReceiverType type;
private String account;
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceRefundParams {
private String subMchid;
private String spAppid;
private String subAppid;
private String transactionId;
private String outTradeNo;
private String outRefundNo;
private String reason;
private EcommerceAmount amount;
private String notifyUrl;
private String refundAccount;
private String fundsAccount;
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.FundFlowAccountType;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceReserveParams {
private String subMchid;
private String outRequestNo;
private Integer amount;
private String remark;
private String bankMemo;
private FundFlowAccountType accountType;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceReturnAdvance {
private String refundId;
private String subMchid;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceReturnOrderParams {
/**
* 子商户号,选填
*/
private String subMchid;
/**
* 微信分账单号,同{@link #outOrderNo} 二选一
*/
private String orderId;
/**
* 商户分账单号,同{@link #orderId} 二选一
*/
private String outOrderNo;
/**
* 商户回退单号,必填
*/
private String outReturnNo;
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
@Data
public class EcommerceSettlementInfo {
private String settlementId;
private String qualificationType;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceSubsidiesCancelParams {
private String subMchid;
private String transactionId;
private String description;
}

View File

@@ -0,0 +1,13 @@
package cn.felord.payment.wechat.v3.model.ecommerce;
import lombok.Data;
@Data
public class EcommerceSubsidiesCreateParams{
private String subMchid;
private String transactionId;
private String outSubsidyNo;
private Integer amount;
private String description;
private String refundId;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceSubsidiesReturnParams {
private String subMchid;
private String outOrderNo;
private String transactionId;
private String refundId;
private Integer amount;
private String description;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class EcommerceWithdraw {
private String subMchid;
private String withdrawId;
}

View File

@@ -0,0 +1,44 @@
package cn.felord.payment.wechat.v3.model.ecommerce;
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 receiverAccount;
/**
* 分账金额,必填
* <p>
* 单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
*/
private Integer amount;
/**
* 分账的原因描述,必填。分账账单中需要体现
*/
private String description;
/**
* 分账个人接收方姓名,选填
* <p>
* 在接收方类型为个人的时可选填,若有值,会检查与 name 是否实名匹配,不匹配会拒绝分账请求
* <ol>
* <li>分账接收方类型是{@code PERSONAL_OPENID},是个人姓名的密文(选传,传则校验) 此字段的加密方法详见:敏感信息加密说明</li>
* <li>使用微信支付平台证书中的公钥</li>
* <li>使用RSAES-OAEP算法进行加密</li>
* <li>将请求中HTTP头部的Wechatpay-Serial设置为证书序列号</li>
* </ol>
*/
private String receiverName;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2019-2022 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.ecommerce;
import lombok.Data;
@Data
public class SalesSceneInfo{
private String storeName;
private String storeUrl;
private String storeQrCode;
private String miniProgramSubAppid;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2019-2022 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.ecommerce;
import cn.felord.payment.wechat.enumeration.IdDocType;
import lombok.Data;
import java.time.LocalDate;
/**
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class UboInfo {
private IdDocType idDocType;
private IdCardInfo idCardInfo;
private IdDocInfo idDocInfo;
/**
* The type Id card info.
*/
@Data
public static class IdCardInfo {
private String idCardCopy;
private String idCardNational;
private String idCardName;
private String idCardNumber;
private LocalDate idCardPeriodBegin;
private LocalDate idCardPeriodEnd;
}
/**
* The type Id doc info.
*/
@Data
public static class IdDocInfo {
private String idDocCopy;
private String idDocName;
private String idDocNumber;
private LocalDate idDocPeriodBegin;
private LocalDate idDocPeriodEnd;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 felord.cn
* Copyright 2019-2022 felord.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 felord.cn
* Copyright 2019-2022 felord.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2019-2022 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.enumeration.TarType;
import lombok.Data;
import java.time.LocalDate;
/**
* 服务商-申请分账账单API参数
*
* @author felord.cn
* @since 1.0.14.RELEASE
*/
@Data
public class PartnerProfitsharingBillParams {
/**
* 子商户号,非必传。
*/
private String subMchid;
/**
* 账单日期,必传。
* <p>
* 格式yyyy-MM-DD仅支持三个月内的账单下载申请。
*/
private LocalDate billDate;
/**
* 压缩类型,不填默认值为数据流
*
* @see TarType
*/
private TarType tarType;
}

View File

@@ -18,7 +18,6 @@
*/
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;
@@ -39,7 +38,7 @@ public class PartnerProfitsharingConsumeData {
* <p>
* 服务商模式分账发起商户
*/
private String mchid;
private String spMchid;
/**
* 子商户号
* <p>
@@ -71,7 +70,7 @@ public class PartnerProfitsharingConsumeData {
* <p>
* 分账接收方对象
*/
private List<Receiver> receivers;
private List<Receiver> receiver;
/**
* 成功时间.

View File

@@ -18,7 +18,6 @@
*/
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;

View File

@@ -19,6 +19,8 @@ package cn.felord.payment.wechat.v3.model.specmch;
import lombok.Data;
import java.time.LocalDate;
/**
* @author felord.cn
* @since 1.0.14.RELEASE
@@ -30,6 +32,6 @@ public class IdDocInfo {
private String idDocName;
private String idDocNumber;
private String idDocAddress;
private String docPeriodBegin;
private String docPeriodEnd;
private LocalDate docPeriodBegin;
private LocalDate docPeriodEnd;
}