feat: 微信支付商家券

增加微信支付商家券所有接口的实现
This commit is contained in:
felord.cn
2021-01-18 11:37:42 +08:00
parent 22bdc4550d
commit 748ab7b4d0
37 changed files with 2195 additions and 34 deletions

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019-2021 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.enumeration;
/**
* code展示模式
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
public enum BusiFavorCodeDisplayMode {
/**
* 不展示code
*/
NOT_SHOW,
/**
* 一维码(条形码)
*/
BARCODE,
/**
* 二维码
*/
QRCODE
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2019-2021 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.enumeration;
/**
* 商家券核销方式
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
public enum BusiFavorUseMethod {
/**
* 线下滴码核销,点击券“立即使用”跳转展示券二维码详情。
*
* @since 1.0.4.RELEASE
*/
OFF_LINE,
/**
* 线上小程序核销点击券“立即使用”跳转至配置的商家小程序需要添加小程序appid和path
*
* @since 1.0.4.RELEASE
*/
MINI_PROGRAMS,
/**
* 微信支付付款码核销,点击券“立即使用”跳转至微信支付钱包付款码。
*
* @since 1.0.4.RELEASE
*/
PAYMENT_CODE,
/**
* 用户自助核销,点击券“立即使用”跳转至用户自助操作核销界面(当前暂不支持用户自助核销)。
*
* @since 1.0.4.RELEASE
*/
SELF_CONSUME;
}

View File

@@ -19,7 +19,7 @@
package cn.felord.payment.wechat.enumeration;
/**
* 代金券状态.
* 代金券、商家券状态.
*
* @author felord.cn
* @since 1.0.0.RELEASE

View File

@@ -20,6 +20,7 @@ package cn.felord.payment.wechat.enumeration;
/**
* 申请资金账单账户类型.
*
* @author felord.cn
* @since 1.0.3.RELEASE
*/
public enum FundFlowAccountType {

View File

@@ -40,5 +40,5 @@ public enum StockType {
*
* @since 1.0.4.RELEASE
*/
EXCHANGE;
EXCHANGE
}

View File

@@ -341,8 +341,93 @@ public enum WechatPayV3Type {
*
* @since 1.0.0.RELEASE
*/
MARKETING_FAVOR_CALLBACKS(HttpMethod.POST, "%s/v3/marketing/favor/callbacks");
MARKETING_FAVOR_CALLBACKS(HttpMethod.POST, "%s/v3/marketing/favor/callbacks"),
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 创建商家券API.
*
* @since 1.0.4.RELEASE
*/
MARKETING_BUSI_FAVOR_CREATE_STOCKS(HttpMethod.POST, "%s/v3/marketing/busifavor/stocks"),
/**
* 查询商家券详情API.
*
* @since 1.0.4.RELEASE
*/
MARKETING_BUSI_FAVOR_STOCKS_DETAIL(HttpMethod.GET, "%s/v3/marketing/busifavor/stocks/{stock_id}"),
/**
* 核销用户券API.
*
* @since 1.0.4.RELEASE
*/
MARKETING_BUSI_FAVOR_COUPON_USE(HttpMethod.POST, "%s/v3/marketing/busifavor/coupons/use"),
/**
* 根据过滤条件查询用户券API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_USER_COUPONS(HttpMethod.GET, "%s/v3/marketing/busifavor/users/{openid}/coupons"),
/**
* 查询用户单张券详情API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_USER_COUPON(HttpMethod.GET, "%s/v3/marketing/busifavor/users/{openid}/coupons/{coupon_code}/appids/{appid}"),
/**
* 商家券上传预存Code API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_UPLOAD_COUPON_CODES(HttpMethod.POST, "%s/v3/marketing/busifavor/stocks/{stock_id}/couponcodes"),
/**
* 设置商家券事件通知地址API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_SETTING_CALLBACKS(HttpMethod.POST, "%s/v3/marketing/busifavor/callbacks"),
/**
* 查询商家券事件通知地址API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_GET_CALLBACKS(HttpMethod.GET, "%s/v3/marketing/busifavor/callbacks"),
/**
* 关联订单信息API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_ASSOCIATE(HttpMethod.POST, "%s/v3/marketing/busifavor/coupons/associate"),
/**
* 取消关联订单信息API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_DISASSOCIATE(HttpMethod.POST, "%s/v3/marketing/busifavor/coupons/disassociate"),
/**
* 取消关联订单信息API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_BUDGET(HttpMethod.POST, "%s/v3/marketing/busifavor/stocks/{stock_id}/budget"),
/**
* 修改商家券基本信息API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_UPDATE(HttpMethod.POST, "%s/v3/marketing/busifavor/stocks/{stock_id}"),
/**
* 申请退券API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_RETURN(HttpMethod.POST, "%s/v3/marketing/busifavor/coupons/return"),
/**
* 使券失效API.
*
* @since 1.0.4.RELEASES
*/
MARKETING_BUSI_FAVOR_DEACTIVATE(HttpMethod.POST, "%s/v3/marketing/busifavor/coupons/deactivate");
/**
* The Pattern.

View File

@@ -55,36 +55,35 @@ final class ExtensionFormHttpMessageConverter extends FormHttpMessageConverter {
*/
private static final String BOUNDARY = "boundary";
/**
* The constant jaxb2Present.
*/
private static final boolean jaxb2Present;
private static final boolean JAXB_2_PRESENT;
/**
* The constant jackson2Present.
*/
private static final boolean jackson2Present;
private static final boolean JACKSON_2_PRESENT;
/**
* The constant jackson2XmlPresent.
*/
private static final boolean jackson2XmlPresent;
private static final boolean JACKSON_2_XML_PRESENT;
/**
* The constant jackson2SmilePresent.
*/
private static final boolean jackson2SmilePresent;
private static final boolean JACKSON_2_SMILE_PRESENT;
/**
* The constant gsonPresent.
*/
private static final boolean gsonPresent;
private static final boolean GSON_PRESENT;
/**
* The constant jsonbPresent.
*/
private static final boolean jsonbPresent;
private static final boolean JSONB_PRESENT;
/**
* The Part converters.
@@ -93,13 +92,13 @@ final class ExtensionFormHttpMessageConverter extends FormHttpMessageConverter {
static {
ClassLoader classLoader = AllEncompassingFormHttpMessageConverter.class.getClassLoader();
jaxb2Present = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
JAXB_2_PRESENT = ClassUtils.isPresent("javax.xml.bind.Binder", classLoader);
JACKSON_2_PRESENT = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
jackson2XmlPresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
jackson2SmilePresent = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
JACKSON_2_XML_PRESENT = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
JACKSON_2_SMILE_PRESENT = ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
GSON_PRESENT = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
JSONB_PRESENT = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);
}
/**
@@ -107,7 +106,8 @@ final class ExtensionFormHttpMessageConverter extends FormHttpMessageConverter {
*/
public ExtensionFormHttpMessageConverter() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316
// see SPR-7316
stringHttpMessageConverter.setWriteAcceptCharset(false);
this.partConverters.add(new ByteArrayHttpMessageConverter());
this.partConverters.add(stringHttpMessageConverter);
@@ -118,23 +118,23 @@ final class ExtensionFormHttpMessageConverter extends FormHttpMessageConverter {
// Ignore when no TransformerFactory implementation is available
}
if (jaxb2Present && !jackson2XmlPresent) {
if (JAXB_2_PRESENT && !JACKSON_2_XML_PRESENT) {
this.partConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
if (JACKSON_2_PRESENT) {
this.partConverters.add(new MappingJackson2HttpMessageConverter());
} else if (gsonPresent) {
} else if (GSON_PRESENT) {
this.partConverters.add(new GsonHttpMessageConverter());
} else if (jsonbPresent) {
} else if (JSONB_PRESENT) {
this.partConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2XmlPresent) {
if (JACKSON_2_XML_PRESENT) {
this.partConverters.add(new MappingJackson2XmlHttpMessageConverter());
}
if (jackson2SmilePresent) {
if (JACKSON_2_SMILE_PRESENT) {
this.partConverters.add(new MappingJackson2SmileHttpMessageConverter());
}
this.setPartConverters(this.partConverters);
@@ -205,7 +205,8 @@ final class ExtensionFormHttpMessageConverter extends FormHttpMessageConverter {
outputMessage.getHeaders().setContentType(contentType);
Charset charset = contentType.getCharset();
Assert.notNull(charset, "No charset"); // should never occur
// should never occur
Assert.notNull(charset, "No charset");
final byte[] bytes = serializeForm(formData, charset).getBytes(charset);
outputMessage.getHeaders().setContentLength(bytes.length);

View File

@@ -94,6 +94,17 @@ public class WechatApiProvider {
return new WechatDiscountCardApi(wechatPayClient, tenantId);
}
/**
* 微信支付商家券.
*
* @param tenantId the tenant id
* @return the wechat discount card api
* @since 1.0.4.RELEASE
*/
public WechatMarketingBusiFavorApi busiFavorApi(String tenantId) {
return new WechatMarketingBusiFavorApi(wechatPayClient, tenantId);
}
/**
* 回调.
* <p>

View File

@@ -0,0 +1,438 @@
/*
* Copyright 2019-2021 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;
import cn.felord.payment.wechat.WechatPayProperties;
import cn.felord.payment.wechat.enumeration.CouponStatus;
import cn.felord.payment.wechat.enumeration.WeChatServer;
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
import cn.felord.payment.wechat.v3.model.busifavor.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.http.RequestEntity;
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;
/**
* 微信支付商家券.
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
public class WechatMarketingBusiFavorApi extends AbstractApi {
/**
* Instantiates a new Abstract api.
*
* @param wechatPayClient the wechat pay client
* @param tenantId the tenant id
*/
public WechatMarketingBusiFavorApi(WechatPayClient wechatPayClient, String tenantId) {
super(wechatPayClient, tenantId);
}
/**
* 创建商家券券批次API
* <p>
* 商家券介绍详见 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/busifavor/chapter1_1.shtml">微信支付商家券</a>
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> createStock(BusiFavorCreateParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_CREATE_STOCKS, params)
.function(this::createStocksFunction)
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
private RequestEntity<?> createStocksFunction(WechatPayV3Type type, BusiFavorCreateParams busiFavorCreateParams) {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
if (!StringUtils.hasText(busiFavorCreateParams.getBelongMerchant())) {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
String mchId = v3.getMchId();
busiFavorCreateParams.setBelongMerchant(mchId);
}
return Post(uri, busiFavorCreateParams);
}
/**
* 查询商家券详情API
* <p>
* 商户可通过该接口查询已创建的商家券批次详情信息。
*
* @param stockId the stock id
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryStockDetail(String stockId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_STOCKS_DETAIL, stockId)
.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暂时appid需要手工在参数中传递
* <p>
* 在用户满足优惠门槛后,服务商可通过该接口核销用户微信卡包中具体某一张商家券。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> use(BusiFavorUseParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_COUPON_USE, params)
.function((type, useParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
if (!StringUtils.hasText(params.getAppid())) {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
String appId = v3.getAppId();
useParams.setAppid(appId);
}
return Post(uri, useParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 根据过滤条件查询用户券API
* <p>
* 商户自定义筛选条件(如创建商户号、归属商户号、发放商户号等),查询指定微信用户卡包中满足对应条件的所有商家券信息。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryUserStocks(UserBusiFavorQueryParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_USER_COUPONS, params)
.function((type, userBusiFavorQueryParams) -> {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
String appid = userBusiFavorQueryParams.getAppid();
if (StringUtils.hasText(appid)) {
queryParams.add("appid", appid);
}
queryParams.add("stock_id", userBusiFavorQueryParams.getStockId());
queryParams.add("coupon_state", userBusiFavorQueryParams.getCouponState().name());
queryParams.add("creator_merchant", userBusiFavorQueryParams.getCreatorMerchant());
queryParams.add("belong_merchant", userBusiFavorQueryParams.getBelongMerchant());
queryParams.add("sender_merchant", userBusiFavorQueryParams.getSenderMerchant());
queryParams.add("offset", String.valueOf(params.getOffset()));
queryParams.add("limit", String.valueOf(params.getLimit()));
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.queryParams(queryParams)
.build()
.expand(userBusiFavorQueryParams.getOpenid())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询用户单张券详情API
* <p>
* 服务商可通过该接口查询微信用户卡包中某一张商家券的详情信息。
*
* @param params the params
* @return the wechat response entity
*/
public WechatResponseEntity<ObjectNode> queryUserCoupon(UserBusiCouponQueryParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_USER_COUPON, params)
.function((type, queryParams) -> {
if (!StringUtils.hasText(params.getAppid())) {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
String appId = v3.getAppId();
queryParams.setAppid(appId);
}
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(queryParams.getOpenid(), queryParams.getCouponCode(), queryParams.getAppid())
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 上传预存code API
* <p>
* 商家券的Code码可由微信后台随机分配同时支持商户自定义。
* 如商家已有自己的优惠券系统,可直接使用自定义模式。
* 即商家预先向微信支付上传券Code当券在发放时微信支付自动从已导入的Code中随机取值不能指定派发给用户。
*
* @param params the params
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> uploadCouponCodes(BusiCouponCodeUploadParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_UPLOAD_COUPON_CODES, params)
.function((type, queryParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(queryParams.getStockId())
.toUri();
queryParams.setStockId(null);
return Post(uri, queryParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 设置商家券事件通知地址API
* <p>
* 用于设置接收商家券相关事件通知的URL可接收商家券相关的事件通知、包括发放通知等。
* 需要设置接收通知的URL并在商户平台开通 <a target= "_blank" href= "https://pay.weixin.qq.com/index.php/xphp/cmkt_product/index#/pages/product/product?pid=3">营销事件推送</a> 的能力,即可接收到相关通知。
* <p>
* 营销事件推送:<a target= "_blank" href= "https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2Findex.php%2Fxphp%2Fcmkt_product%2Findex#/pages/product/product?pid=3">点击开通产品权限</a>。由商家券批次创建方登录Pay平台操作开通
* <p>
* 注意:
* <ul>
* <li>仅可以收到由商户自己创建的批次相关的通知</li>
* <li>需要设置apiv3秘钥否则无法收到回调。</li>
* <li>如果需要领券回调中的参数openid。需要创券时候传入 notify_appid参数。</li>
* </ul>
*
* @param params the params
* @return callbacks callbacks
*/
public WechatResponseEntity<ObjectNode> setCallbacks(BusiFavorCallbackSettingParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_SETTING_CALLBACKS, params)
.function((type, queryParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, queryParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 查询商家券事件通知地址API
* <p>
* 通过调用此接口可查询设置的通知URL。
* <p>
* 注意:
* <ul>
* <li>仅可以查询由请求商户号设置的商家券通知url</li>
* </ul>
*
* @param mchId the mch id
* @return callbacks callbacks
*/
public WechatResponseEntity<ObjectNode> getCallbacks(String mchId) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_GET_CALLBACKS, mchId)
.function((type, id) -> {
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA));
if (StringUtils.hasText(id)) {
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
queryParams.add("mchid", id);
uriComponentsBuilder.queryParams(queryParams);
}
URI uri = uriComponentsBuilder
.build()
.toUri();
return Get(uri);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 商家券关联订单信息API
* <p>
* 将有效态(未核销)的商家券与订单信息关联,用于后续参与摇奖&返佣激励等操作的统计。
* <p>
* 注意:
* 仅对有关联订单需求的券进行该操作
*
* @param associateInfo the associate info
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> associate(BusiFavorAssociateInfo associateInfo) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_ASSOCIATE, associateInfo)
.function(this::associateFunction)
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 商家券取消关联订单信息API
* <p>
* 取消商家券与订单信息的关联关系。
* <p>
* 注意:
* 建议取消前调用查询接口,查到当前关联的商户单号并确认后,再进行取消操作
*
* @param associateInfo the associate info
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> disassociate(BusiFavorAssociateInfo associateInfo) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_DISASSOCIATE, associateInfo)
.function(this::associateFunction)
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* associate and disassociate function
*
* @param type WechatPayV3Type
* @param associateInfo the associateInfo
* @return RequestEntity
*/
private RequestEntity<?> associateFunction(WechatPayV3Type type, BusiFavorAssociateInfo associateInfo) {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, associateInfo);
}
/**
* 修改批次预算API
* <p>
* 商户可以通过该接口修改批次单天发放上限数量或者批次最大发放数量
*
* @param params the params
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> budget(BusiFavorBudgetParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_BUDGET, params)
.function((type, budgetParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(budgetParams.getStockId())
.toUri();
budgetParams.setStockId(null);
return Post(uri, budgetParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 修改商家券基本信息API
* <p>
* 商户可以通过该接口修改商家券基本信息
*
* @param params the params
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> updateStock(BusiFavorUpdateParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_UPDATE, params)
.function((type, updateParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.expand(updateParams.getStockId())
.toUri();
updateParams.setStockId(null);
return Post(uri, updateParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 申请退券API
* <p>
* 商户可以通过该接口为已核销的券申请退券
*
* @param params the params
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> refund(BusiFavorRefundParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_RETURN, params)
.function((type, refundParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, refundParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
/**
* 使券失效API
* <p>
* 前置条件:券的状态为{@link CouponStatus#SENDED}
* <p>
* 商户可以通过该接口将可用券进行失效处理,券被失效后无法再被核销
*
* @param params the params
* @return wechat response entity
*/
public WechatResponseEntity<ObjectNode> deactivate(BusiFavorDeactivateParams params) {
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.MARKETING_BUSI_FAVOR_DEACTIVATE, params)
.function((type, deactivateParams) -> {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
return Post(uri, deactivateParams);
})
.consumer(wechatResponseEntity::convert)
.request();
return wechatResponseEntity;
}
}

View File

@@ -92,10 +92,11 @@ public class WechatMarketingFavorApi extends AbstractApi {
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
if (!StringUtils.hasText(params.getBelongMerchant())){
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
String mchId = v3.getMchId();
params.setBelongMerchant(mchId);
}
return Post(uri, params);
}

View File

@@ -22,8 +22,12 @@ import cn.felord.payment.wechat.v3.model.CallbackParams;
import cn.felord.payment.wechat.v3.model.CouponConsumeData;
import cn.felord.payment.wechat.v3.model.ResponseSignVerifyParams;
import cn.felord.payment.wechat.v3.model.TransactionConsumeData;
import cn.felord.payment.wechat.v3.model.busifavor.BusiFavorReceiveConsumeData;
import cn.felord.payment.wechat.v3.model.combine.CombineTransactionConsumeData;
import cn.felord.payment.wechat.v3.model.discountcard.*;
import cn.felord.payment.wechat.v3.model.discountcard.DiscountCardAcceptedConsumeData;
import cn.felord.payment.wechat.v3.model.discountcard.DiscountCardAgreementEndConsumeData;
import cn.felord.payment.wechat.v3.model.discountcard.DiscountCardConsumer;
import cn.felord.payment.wechat.v3.model.discountcard.DiscountCardUserPaidConsumeData;
import cn.felord.payment.wechat.v3.model.payscore.PayScoreConsumer;
import cn.felord.payment.wechat.v3.model.payscore.PayScoreUserConfirmConsumeData;
import cn.felord.payment.wechat.v3.model.payscore.PayScoreUserPaidConsumeData;
@@ -95,7 +99,7 @@ public class WechatPayCallback {
*/
@SneakyThrows
public Map<String, ?> couponCallback(ResponseSignVerifyParams params, Consumer<CouponConsumeData> consumeDataConsumer) {
String data = this.callback(params, EventType.COUPON);
String data = this.callback(params, EventType.COUPON_USE);
CouponConsumeData consumeData = MAPPER.readValue(data, CouponConsumeData.class);
consumeDataConsumer.accept(consumeData);
Map<String, Object> responseBody = new HashMap<>(2);
@@ -241,6 +245,32 @@ public class WechatPayCallback {
return Collections.singletonMap("code", "SUCCESS");
}
/**
* 商家券领券事件回调通知API
* <p>
* 领券完成后,微信会把相关支付结果和用户信息发送给商户,商户需要接收处理,并按照文档规范返回应答。出于安全的考虑,我们对支付结果数据进行了加密,商户需要先对通知数据进行解密,才能得到支付结果数据。
* <p>
* 该链接是通过商户<a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/busifavor/chapter3_7.shtml">设置商家券事件通知地址API</a>中提交notify_url参数必须为https协议。如果链接无法访问商户将无法接收到微信通知。 通知url必须为直接可访问的url不能携带参数。示例 “https://pay.weixin.qq.com/wxpay/pay.action”
*
* @param params the params
* @param consumeDataConsumer the consume data consumer
* @return the map
*/
@SneakyThrows
public Map<String, ?> busiFavorReceiveCallback(ResponseSignVerifyParams params, Consumer<BusiFavorReceiveConsumeData> consumeDataConsumer) {
CallbackParams callbackParams = resolve(params);
String eventType = callbackParams.getEventType();
if (!Objects.equals(eventType, EventType.COUPON_SEND.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);
BusiFavorReceiveConsumeData consumeData = MAPPER.readValue(data, BusiFavorReceiveConsumeData.class);
consumeDataConsumer.accept(consumeData);
return Collections.singletonMap("code", "SUCCESS");
}
/**
* Callback.
@@ -352,10 +382,22 @@ public class WechatPayCallback {
/**
* 优惠券核销事件.
* <p>
* 代金券
*
* @since 1.0.0.RELEASE
*/
COUPON("COUPON.USE"),
COUPON_USE("COUPON.USE"),
/**
* 优惠券领券事件.
* <p>
* 商家券
*
* @since 1.0.0.RELEASE
*/
COUPON_SEND("COUPON.SEND"),
/**
* 支付成功事件.
*

View File

@@ -44,12 +44,12 @@ public class StocksCreateParams {
*/
private String belongMerchant;
/**
* 批次开始时间 rfc 3339 yyyy-mm-ddthh:mm:ss.sss+timezone
* 批次开始时间 rfc 3339 yyyy-MM-ddTHH:mm:ss+TIMEZONE
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "GMT+8")
private OffsetDateTime availableBeginTime;
/**
* 批次结束时间 rfc 3339 YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE
* 批次结束时间 rfc 3339 yyyy-MM-ddTHH:mm:ss+TIMEZONE
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "GMT+8")
private OffsetDateTime availableEndTime;

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 商家券当天可用时间段
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class AvailableDayTimeItem {
/**
* 当天可用开始时间单位1代表当天0点0分1秒。
*/
private Integer endTime;
/**
* 当天可用结束时间单位86399代表当天23点59分59秒。
*/
private Integer beginTime;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
import java.util.List;
/**
* 固定周期有效时间段
* <p>
* 可以设置多个星期下的多个可用时间段比如每周二10点到18点用户自定义字段。
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class AvailableWeek {
/**
* 当天可用时间段
* <p>
* 可以填写多个时间段最多不超过2个。
*/
private List<AvailableDayTimeItem> availableDayTime;
/**
* 可用星期数
* <p>
* 0代表周日1代表周一以此类推
* <p>
* 当填写{@link #availableDayTime}时,{@code weekDay}必填
*/
private List<Integer> weekDay;
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
import java.util.Set;
/**
* 商家券上传预存code API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiCouponCodeUploadParams {
/**
* 批次号
*/
private String stockId;
/**
* 券code列表
* <p>
* 特殊规则单个券code长度为【132】条目个数限制为【1200】。
*/
private Set<String> couponCodeList;
/**
* 请求业务单据号
*/
private String uploadRequestNo;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 商家券关联订单信息API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorAssociateInfo {
/**
* 批次号
*/
private String stockId;
/**
* 券code
*/
private String couponCode;
/**
* 关联的商户订单号
*/
private String outTradeNo;
/**
* 商户请求单号
* @see BusiFavorCreateParams#getOutRequestNo()
*/
private String outRequestNo;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 修改商家券批次预算API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorBudgetParams {
/**
* 批次号
*/
private String stockId;
/**
* 目标批次最大发放个数,同{@link #targetMaxCouponsByDay}二选一
*/
private Integer targetMaxCoupons;
/**
* 目标单天发放上限个数,同{@link #targetMaxCoupons}二选一
*/
private Integer targetMaxCouponsByDay;
/**
* 当前批次最大发放个数,当传入{@link #targetMaxCoupons}大于0时必传
*/
private Integer currentMaxCoupons;
/**
* 当前单天发放上限个数 ,当传入{@link #targetMaxCouponsByDay}大于0时必填
*/
private Integer currentMaxCouponsByDay;
/**
* 修改预算请求单据号
*/
private String modifyBudgetRequestNo;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 设置商家券事件通知地址API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorCallbackSettingParams {
/**
* 微信支付商户的商户号由微信支付生成并下发不填默认查询调用方商户的通知URL。
*/
private String mchid;
/**
* 商户提供的用于接收商家券事件通知的url地址必须支持https。
*/
private String notifyUrl;
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2019-2021 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.busifavor;
import cn.felord.payment.wechat.enumeration.StockType;
import lombok.Data;
/**
* 创建商家券请求参数.
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorCreateParams {
/**
* 商家券批次名称,[1,21],必填
*/
private String stockName;
/**
* 批次归属商户号,必填
*/
private String belongMerchant;
/**
* 批次备注,[1,20],选填
*/
private String comment;
/**
* 适用商品范围,必填
* <p>
* 用来描述批次在哪些商品可用会显示在微信卡包中。字数上限为15个一个中文汉字/英文字母/数字均占用一个字数。
*/
private String goodsName;
/**
* 批次类型
*/
private StockType stockType;
/**
* 核销规则
*/
private CouponUseRule couponUseRule;
/**
* 自定义入口
*/
private CustomEntrance customEntrance;
/**
* 商家券code模式枚举
*/
private CouponCodeMode couponCodeMode;
/**
* 样式信息
*/
private DisplayPatternInfo displayPatternInfo;
/**
* 券发放规则
*/
private StockSendRule stockSendRule;
/**
* 商户请求单号
* <p>
* 商户创建批次凭据号格式商户id+日期+流水号),商户侧需保持唯一性。
*/
private String outRequestNo;
/**
* 事件通知配置
*/
private BusiFavorNotifyConfig notifyConfig;
/**
* 商家券code模式枚举
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
public enum CouponCodeMode {
/**
* 系统分配券code。固定22位纯数字
*
* @since 1.0.4.RELEASE
*/
WECHATPAY_MODE,
/**
* 商户发放时接口指定券code。
*
* @since 1.0.4.RELEASE
*/
MERCHANT_API,
/**
* 商户上传自定义code发券时系统随机选取上传的券code。
*
* @since 1.0.4.RELEASE
*/
MERCHANT_UPLOAD
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 使券失效API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorDeactivateParams {
/**
* 券code
*/
private String couponCode;
/**
* 批次号
*/
private String stockId;
/**
* 失效请求单据号
*/
private String deactivateRequestNo;
/**
* 失效原因
*/
private String deactivateReason;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 事件通知配置
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorNotifyConfig {
/**
* 事件通知appid
* <p>
* 用于回调通知时计算返回操作用户的openid诸如领券用户支持小程序or公众号的APPID
* 如该字段不填写则回调通知中涉及到用户身份信息的openid与unionid都将为空。
*/
private String notifyAppid;
}

View File

@@ -0,0 +1,162 @@
/*
* Copyright 2019-2021 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.busifavor;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.OffsetDateTime;
/**
* 商家券领券事件回调通知解密
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorReceiveConsumeData {
/**
* 业务细分事件类型
* <p>
* 枚举值:
* EVENT_TYPE_BUSICOUPON_SEND商家券用户领券通知
*/
private String eventType;
/**
* 券code
*/
private String couponCode;
/**
* 批次号
*/
private String stockId;
/**
* 发放时间 rfc 3339 yyyy-MM-ddTHH:mm:ss+TIMEZONE
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime sendTime;
/**
* 微信用户在appid下的唯一标识。
*/
private String openid;
/**
* 微信用户在同一个微信开放平台账号下的唯一用户标识,
* unionid获取方式请参见 <a target= "_blank" href= "https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html">《UnionID机制说明》</a> 文档。
*/
private String unionid;
/**
* 发券商户号
*/
private String sendMerchant;
/**
* 发放渠道
*/
private SendChannel sendChannel;
/**
* 发券附加信息,仅在支付有礼、扫码领券(营销馆)、会员有礼发放渠道,才有该信息
*/
private AttachInfo attachInfo;
/**
* 发放渠道
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
public enum SendChannel {
/**
* 小程序
*/
BUSICOUPON_SEND_CHANNEL_MINIAPP,
/**
* API
*/
BUSICOUPON_SEND_CHANNEL_API,
/**
* 支付有礼
*/
BUSICOUPON_SEND_CHANNEL_PAYGIFT,
/**
* H5
*/
BUSICOUPON_SEND_CHANNEL_H5,
/**
* 面对面
*/
BUSICOUPON_SEND_CHANNEL_FTOF,
/**
* 会员卡活动
*/
BUSICOUPON_SEND_CHANNEL_MEMBER_CARD_ACT,
/**
* 扫码领券(营销馆)
*/
BUSICOUPON_SEND_CHANNEL_HALL
}
/**
* 商家券领券事件回调通知解密-发券附加信息
* <p>
* 仅在支付有礼、扫码领券(营销馆)、会员有礼发放渠道,才有该信息
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public static class AttachInfo {
/**
* 交易订单编号
* <p>
* 仅在支付有礼渠道,才有该信息,对应支付有礼曝光支付订单编号信息
*/
private String transactionId;
/**
* 支付有礼活动编号对应{@link SendChannel#BUSICOUPON_SEND_CHANNEL_PAYGIFT}
* <p>
* 营销馆活动ID对应{@link SendChannel#BUSICOUPON_SEND_CHANNEL_HALL}
* <p>
* 二选一,且只在对应场景下出现
*/
private String actCode;
/**
* 仅在扫码领券(营销馆)渠道,才有该信息,对应领券的营销馆 馆ID信息
*/
private String hallCode;
/**
* 仅在扫码领券(营销馆)渠道,才有该信息,对应领券的营销馆所属商户号信息
*/
private Integer hallBelongMchId;
/**
* 仅在会员卡活动渠道才有该信息对应会员卡Card_ID信息
*/
private String cardId;
/**
* 仅在会员卡活动渠道才有该信息对应用户卡包会员卡卡Code信息
*/
private String code;
/**
* 仅在会员卡活动渠道才有该信息对应会员有礼活动ID信息
*/
private String activityId;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 修改商家券基本信息API请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorRefundParams {
/**
* 券code
*/
private String couponCode;
/**
* 批次号
*/
private String stockId;
/**
* 退券请求单据号
*/
private String returnRequestNo;
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright 2019-2021 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.busifavor;
import cn.felord.payment.wechat.enumeration.BusiFavorCodeDisplayMode;
import cn.felord.payment.wechat.enumeration.BusiFavorUseMethod;
import lombok.Data;
/**
* 修改商家券基本信息API请求参数.
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorUpdateParams {
/**
* 商家券批次号,必传
*/
private String stockId;
/**
* 自定义入口
*/
private UpdateCustomEntrance customEntrance;
/**
* 商家券批次名称,[1,21]
*/
private String stockName;
/**
* 批次备注,[1,20]
*/
private String comment;
/**
* 适用商品范围
* <p>
* 用来描述批次在哪些商品可用会显示在微信卡包中。字数上限为15个一个中文汉字/英文字母/数字均占用一个字数。
*/
private String goodsName;
/**
* 商户请求单号
* <p>
* 商户创建批次凭据号格式商户id+日期+流水号),商户侧需保持唯一性。
*/
private String outRequestNo;
/**
* 样式信息
*/
private DisplayPatternInfo displayPatternInfo;
/**
* 核销规则
*/
private UpdateCouponUseRule couponUseRule;
/**
* 券发放规则
*/
private UpdateStockSendRule stockSendRule;
/**
* 事件通知配置
*/
private BusiFavorNotifyConfig notifyConfig;
/**
* 商家券核销规则-自定义入口修改参数
* <p>
* 卡详情页面,可选择多种入口引导用户。
*
* @author felord.cn
* @see CustomEntrance
* @since 1.0.4.RELEASE
*/
@Data
public static class UpdateCustomEntrance {
/**
* 营销馆id
*/
private String hallId;
/**
* 小程序入口
*/
private MiniProgramsInfo miniProgramsInfo;
/**
* 商户公众号appid
* <p>
* 从券详情可跳转至公众号
*/
private String appid;
/**
* code展示模式
*/
private BusiFavorCodeDisplayMode codeDisplayMode;
}
/**
* 商家券核销规则修改参数
*
* @author felord.cn
* @see CouponUseRule
* @since 1.0.4.RELEASE
*/
@Data
public static class UpdateCouponUseRule {
/**
* 核销方式
*/
private BusiFavorUseMethod useMethod;
/**
* 核销小程序appid
*
* @see BusiFavorUseMethod#MINI_PROGRAMS
*/
private String miniProgramsAppid;
/**
* 核销小程序path
*
* @see #miniProgramsAppid
*/
private String miniProgramsPath;
}
/**
* 商家券发放规则修改参数
*
* @author felord.cn
* @see StockSendRule
* @since 1.0.4.RELEASE
*/
@Data
public static class UpdateStockSendRule {
/**
* 是否开启自然人限制
*/
private Boolean naturalPersonLimit;
/**
* 可疑账号拦截
*/
private Boolean preventApiAbuse;
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2019-2021 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.busifavor;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.OffsetDateTime;
/**
* 核销用户券请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class BusiFavorUseParams {
/**
* 券code
*/
private String couponCode;
/**
* 批次号
*/
private String stockId;
/**
* 公众账号ID
*/
private String appid;
/**
* 请求核销时间
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime useTime;
/**
* 核销请求单据号,商户侧保证唯一
*/
private String useRequestNo;
/**
* 用户标识,用户的唯一标识,做安全校验使用
*/
private String openid;
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2019-2021 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.busifavor;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.OffsetDateTime;
import java.util.List;
/**
* 商家券核销规则-券可核销时间
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class CouponAvailableTime {
/**
* 领取后N天开始生效
* <p>
* 日期区间内用户领券后需等待x天开始生效。例如领券后当天开始生效则无需填写领券后第2天开始生效填1以此类推……
* <p>
* 用户在有效期开始前领取商家券则从有效期第1天开始计算天数用户在有效期内领取商家券则从领取当天开始计算天数。无论用户何时领取商家券商家券在活动有效期结束后均不可用。
* <p>
* 需配合{@link #availableDayAfterReceive} 一同填写,不可单独填写。
*/
private int waitDaysAfterReceive;
/**
* 生效后N天内有效
* <p>
* 日期区间内券生效后x天内有效。例如生效当天内有效填1生效后2天内有效填2以此类推……
* <p>
* 注意用户在有效期开始前领取商家券则从有效期第1天开始计算天数用户在有效期内领取商家券则从领取当天开始计算天数无论用户何时领取商家券商家券在活动有效期结束后均不可用。
* <p>
* 可配合{@link #waitDaysAfterReceive}一同填写也可单独填写。单独填写时有效期内领券后立即生效生效后x天内有效。
*/
private int availableDayAfterReceive;
/**
* 批次开始时间 rfc 3339 yyyy-MM-ddTHH:mm:ss+TIMEZONE
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime availableBeginTime;
/**
* 批次结束时间 rfc 3339 yyyy-MM-ddTHH:mm:ss+TIMEZONE
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime availableEndTime;
/**
* 固定周期有效时间段
*/
private AvailableWeek availableWeek;
/**
* 无规律的有效时间段
*/
private List<IrregularyAvaliableTimeItem> irregularyAvaliableTime;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2019-2021 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.busifavor;
import cn.felord.payment.wechat.enumeration.BusiFavorUseMethod;
import cn.felord.payment.wechat.enumeration.StockType;
import lombok.Data;
/**
* 商家券核销规则
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class CouponUseRule {
/**
* 核销方式
*/
private BusiFavorUseMethod useMethod;
/**
* 换购券使用规则
*
* @see StockType#EXCHANGE
*/
private ExchangeCoupon exchangeCoupon;
/**
* 券可核销时间
*/
private CouponAvailableTime couponAvailableTime;
/**
* 核销小程序appid
*
* @see BusiFavorUseMethod#MINI_PROGRAMS
*/
private String miniProgramsAppid;
/**
* 核销小程序path
*
* @see #miniProgramsAppid
*/
private String miniProgramsPath;
/**
* 固定面额满减券使用规则
*
* @see StockType#NORMAL
*/
private FixedNormalCoupon fixedNormalCoupon;
/**
* 折扣券使用规则
*
* @see StockType#DISCOUNT
*/
private DiscountCoupon discountCoupon;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2019-2021 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.busifavor;
import cn.felord.payment.wechat.enumeration.BusiFavorCodeDisplayMode;
import lombok.Data;
/**
* 商家券核销规则-自定义入口
* <p>
* 卡详情页面,可选择多种入口引导用户。
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class CustomEntrance {
/**
* 可用门店id
* <p>
* 不可修改项
*/
private String storeId;
/**
* 营销馆id
*/
private String hallId;
/**
* 小程序入口
*/
private MiniProgramsInfo miniProgramsInfo;
/**
* 商户公众号appid
* <p>
* 从券详情可跳转至公众号
*/
private String appid;
/**
* code展示模式
*/
private BusiFavorCodeDisplayMode codeDisplayMode;
}

View File

@@ -0,0 +1,25 @@
package cn.felord.payment.wechat.v3.model.busifavor;
import lombok.Data;
/**
* 商家券核销规则-折扣券使用规则
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class DiscountCoupon {
/**
* 折扣百分比例如88为八八折
*/
private Integer discountPercent;
/**
* 消费门槛,单位:分。
* <p>
* 特殊规则:取值范围 1 ≤ transactionMinimum ≤ 10000000
*/
private Integer transactionMinimum;
}

View File

@@ -0,0 +1,60 @@
package cn.felord.payment.wechat.v3.model.busifavor;
import cn.felord.payment.wechat.enumeration.CouponBgColor;
import cn.felord.payment.wechat.v3.WechatMarketingFavorApi;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
/**
* 商家券样式信息.
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class DisplayPatternInfo {
/**
* 背景颜色
*/
private CouponBgColor backgroundColor;
/**
* 商户logo
* <p>
* <ol>
* <li>商户logo大小需为120像素*120像素</li>
* <li>支持JPG/JPEG/PNG格式且图片小于1M</li>
* </ol>
* <p>
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
*
* @see WechatMarketingFavorApi#marketingImageUpload(MultipartFile)
*/
private String merchantLogoUrl;
/**
* 券详情图片
* <p>
* <ol>
* <li>需为850像素*350像素</li>
* <li>图片大小不超过2M</li>
* <li>支持JPG/PNG格式</li>
* </ol>
* <p>
* 仅支持通过 <a target= "_blank" href= "https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/chapter3_1.shtml">图片上传API</a> 接口获取的图片URL地址。
*
* @see WechatMarketingFavorApi#marketingImageUpload(MultipartFile)
*/
private String couponImageUrl;
/**
* 使用须知
* <p>
* 用于说明详细的活动规则,会展示在代金券详情页。
* <p>
* 示例值xxx门店可用
*/
private String description;
/**
* 商户名称,字数上限为16个
*/
private String merchantName;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 商家券核销规则-换购券使用规则
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class ExchangeCoupon {
/**
* 单品换购价,单位:分。
* <p>
* 特殊规则:取值范围 1 ≤ exchangePrice ≤ 10000000
*/
private Integer exchangePrice;
/**
* 消费门槛,单位:分。
* <p>
* 特殊规则:取值范围 1 ≤ transactionMinimum ≤ 10000000
*/
private Integer transactionMinimum;
}

View File

@@ -0,0 +1,26 @@
package cn.felord.payment.wechat.v3.model.busifavor;
import lombok.Data;
/**
* 商家券核销规则-固定面额满减券使用规则
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class FixedNormalCoupon {
/**
* 优惠金额,单位:分。
* <p>
* 特殊规则:取值范围 1 ≤ transactionMinimum ≤ 10000000
*/
private Integer discountAmount;
/**
* 消费门槛,单位:分。
* <p>
* 特殊规则:取值范围 1 ≤ transactionMinimum ≤ 10000000
*/
private Integer transactionMinimum;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2021 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.busifavor;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.OffsetDateTime;
/**
* 商家券核销规则-券可核销时间-无规律的有效时间段
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class IrregularyAvaliableTimeItem{
/**
* 开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime beginTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX", timezone = "GMT+8")
private OffsetDateTime endTime;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 商家券核销规则-自定义入口-小程序入口
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class MiniProgramsInfo{
/**
* 商家小程序appid
* <p>
* 商家小程序appid要与归属商户号有M-A or M-m-suba关系。
*/
private String miniProgramsAppid;
/**
* 商家小程序path
*/
private String miniProgramsPath;
/**
* 入口文案字数上限为5个一个中文汉字/英文字母/数字均占用一个字数。
*/
private String guidingWords;
/**
* 小程序入口引导文案用户自定义字段。字数上限为6个一个中文汉字/英文字母/数字均占用一个字数。
*/
private String entranceWords;
}

View File

@@ -0,0 +1,51 @@
package cn.felord.payment.wechat.v3.model.busifavor;
import cn.felord.payment.wechat.enumeration.StockType;
import lombok.Data;
/**
* 商家券发放规则.
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class StockSendRule {
/**
* 批次最大发放个数
* <p>
* 特殊规则:取值范围 1 ≤ maxCoupons ≤ 1000000000
*/
private Integer maxCoupons;
/**
* 用户最大可领个数
* <p>
* 每个用户最多100张券 。
*/
private Integer maxCouponsPerUser;
/**
* 单天发放上限个数
* <p>
* {@link StockType#DISCOUNT}或者{@link StockType#DISCOUNT}时可传入此字段控制单天发放上限
* <p>
* 特殊规则:取值范围 1 ≤ maxCouponsByDay ≤ 1000000000
*/
private Integer maxCouponsByDay;
/**
* 是否开启自然人限制
*/
private Boolean naturalPersonLimit;
/**
* 可疑账号拦截
*/
private Boolean preventApiAbuse;
/**
* 是否允许转赠
*/
private Boolean transferable;
/**
* 是否允许分享链接
*/
private Boolean shareable;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2021 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.busifavor;
import lombok.Data;
/**
* 查询用户单张券详情请求参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class UserBusiCouponQueryParams {
/**
* 券code
*/
private String couponCode;
/**
* 与当前调用接口商户号有绑定关系的appid。支持小程序appid与公众号appid。
*/
private String appid;
/**
* Openid信息用户在appid下的唯一标识。
*/
private String openid;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2019-2021 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.busifavor;
import cn.felord.payment.wechat.enumeration.CouponStatus;
import lombok.Data;
/**
* 根据过滤条件查询用户券API查询参数
*
* @author felord.cn
* @since 1.0.4.RELEASE
*/
@Data
public class UserBusiFavorQueryParams {
/**
* 用户标识用户在appid下的唯一标识。
*/
private String openid;
/**
* 与当前调用接口商户号有绑定关系的appid。支持小程序appid与公众号appid。
*/
private String appid;
/**
* 商户券批次号
*/
private String stockId;
/**
* 券状态
*/
private CouponStatus couponState;
/**
* 创建批次的商户号
*/
private String creatorMerchant;
/**
* 批次归属商户号
*/
private String belongMerchant;
/**
* 批次发放商户号
*/
private String senderMerchant;
/**
* 分页页码
*/
private String offset;
/**
* 分页大小
*/
private String limit;
}