mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-13 21:33:41 +08:00
分页查询商户下的优惠券批次
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.enongm.dianji.payment.wechat;
|
||||
|
||||
|
||||
import com.enongm.dianji.payment.wechat.oauth2.OAuth2AuthorizationRequestRedirectProvider;
|
||||
import com.enongm.dianji.payment.wechat.v3.*;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -66,4 +67,18 @@ public class WechatPayConfiguration {
|
||||
public WechatPayV3Api wechatPayV3Api(WechatPayV3Client wechatPayV3Client,WechatMetaBean wechatMetaBean) {
|
||||
return new WechatPayV3Api(wechatPayV3Client,wechatMetaBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号授权工具用于获取用户openId,需要配置{@link WechatPayProperties.Mp}.
|
||||
*
|
||||
* @param wechatPayProperties the wechat pay properties
|
||||
* @return the o auth 2 authorization request redirect provider
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "wechat.pay", name = "v3.mp.app-id")
|
||||
public OAuth2AuthorizationRequestRedirectProvider oAuth2Provider(WechatPayProperties wechatPayProperties){
|
||||
WechatPayProperties.Mp mp = wechatPayProperties.getV3().getMp();
|
||||
return new OAuth2AuthorizationRequestRedirectProvider(mp.getAppId(), mp.getAppSecret());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@ public class WechatPayProperties {
|
||||
@NestedConfigurationProperty
|
||||
private V3 v3;
|
||||
|
||||
/**
|
||||
* wechat pay v3 properties.
|
||||
*/
|
||||
@Data
|
||||
public static class V3 {
|
||||
/**
|
||||
@@ -27,7 +30,7 @@ public class WechatPayProperties {
|
||||
*/
|
||||
private boolean partnerMode;
|
||||
/**
|
||||
* app id for wechat pay is required
|
||||
* app id for wechat pay is required
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
@@ -47,13 +50,34 @@ public class WechatPayProperties {
|
||||
*/
|
||||
private String partnerKey;
|
||||
/**
|
||||
* wechat pay certificate Path
|
||||
* wechat pay certificate Path
|
||||
*/
|
||||
private String certPath;
|
||||
/**
|
||||
* your pay server domain
|
||||
*/
|
||||
private String domain;
|
||||
/**
|
||||
* wechat mp binding with mch
|
||||
*/
|
||||
private Mp mp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wechat mp for send coupons and notification.
|
||||
*/
|
||||
@Data
|
||||
public static class Mp {
|
||||
/**
|
||||
* app id for wechat pay is required
|
||||
*/
|
||||
private String appId;
|
||||
/**
|
||||
* app secret for wechat pay is required
|
||||
*/
|
||||
private String appSecret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.enongm.dianji.payment.wechat.enumeration;
|
||||
|
||||
/**
|
||||
* The enum Stock status.
|
||||
*
|
||||
* @author Dax
|
||||
* @since 15 :17
|
||||
*/
|
||||
public enum StockStatus {
|
||||
/**
|
||||
* Unactivated stock status.
|
||||
*/
|
||||
UNACTIVATED("unactivated", "未激活"),
|
||||
/**
|
||||
* Audit stock status.
|
||||
*/
|
||||
AUDIT("audit", "审核中"),
|
||||
/**
|
||||
* Running stock status.
|
||||
*/
|
||||
RUNNING("running", "运行中"),
|
||||
/**
|
||||
* Stoped stock status.
|
||||
*/
|
||||
STOPED("stoped", "已停止"),
|
||||
/**
|
||||
* Paused stock status.
|
||||
*/
|
||||
PAUSED("paused", "暂停发放");
|
||||
|
||||
private final String value;
|
||||
private final String description;
|
||||
|
||||
StockStatus(String value, String description) {
|
||||
this.value = value;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value string.
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public String value() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description string.
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public String description() {
|
||||
return this.description;
|
||||
}
|
||||
}
|
||||
@@ -40,13 +40,17 @@ public enum WechatPayV3Type {
|
||||
*/
|
||||
MARKETING_FAVOR_STOCKS_START(HttpMethod.POST,"%s/v3/marketing/favor/stocks/{stock_id}/start"),
|
||||
/**
|
||||
* 发放代金券API.
|
||||
* 发放代金券API & 根据商户号查用户的券.
|
||||
*/
|
||||
MARKETING_FAVOR_USERS_COUPONS(HttpMethod.POST,"%s/v3/marketing/favor/users/{openid}/coupons"),
|
||||
/**
|
||||
* 查询代金券可用商户
|
||||
*/
|
||||
MARKETING_FAVOR_STOCKS_MERCHANTS(HttpMethod.GET, "%s/v3/marketing/favor/stocks/{stock_id}/merchants");
|
||||
MARKETING_FAVOR_STOCKS_MERCHANTS(HttpMethod.GET, "%s/v3/marketing/favor/stocks/{stock_id}/merchants"),
|
||||
/**
|
||||
* 条件查询批次列表API.
|
||||
*/
|
||||
MARKETING_FAVOR_STOCKS(HttpMethod.GET, "%s/v3/marketing/favor/stocks");
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.enongm.dianji.payment.wechat.oauth2;
|
||||
|
||||
|
||||
import com.enongm.dianji.payment.PayException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* OAuth2 获取用户的公众号授权openid.
|
||||
*
|
||||
* @author Dax
|
||||
* @since 11 :39
|
||||
*/
|
||||
public class OAuth2AuthorizationRequestRedirectProvider {
|
||||
private static final String AUTHORIZATION_URI = "https://open.weixin.qq.com/connect/oauth2/authorize";
|
||||
private static final String TOKEN_URI = "https://api.weixin.qq.com/sns/oauth2/access_token";
|
||||
private final RestOperations restOperations = new RestTemplate();
|
||||
private final String appId;
|
||||
private final String secret;
|
||||
|
||||
/**
|
||||
* Instantiates a new O auth 2 authorization request redirect provider.
|
||||
*
|
||||
* @param appId the app id
|
||||
* @param secret the secret
|
||||
*/
|
||||
public OAuth2AuthorizationRequestRedirectProvider(String appId, String secret) {
|
||||
this.appId = appId;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接微信公众号授权的url,用以触发用户点击跳转微信授权.
|
||||
*
|
||||
* @param phoneNumber the phone number
|
||||
* @param redirectUri the redirect uri
|
||||
* @return uri components
|
||||
*/
|
||||
public UriComponents redirect(String phoneNumber, String redirectUri) {
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("appid", appId);
|
||||
queryParams.add("redirect_uri", redirectUri);
|
||||
queryParams.add("response_type", "code");
|
||||
queryParams.add("scope", "snsapi_base");
|
||||
queryParams.add("state", phoneNumber);
|
||||
return UriComponentsBuilder.fromHttpUrl(AUTHORIZATION_URI).queryParams(queryParams).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 微信服务器授权成功后调用redirectUri的处理逻辑.
|
||||
*
|
||||
* @param code the code
|
||||
* @return the string
|
||||
*/
|
||||
public String openId(String code) {
|
||||
Assert.hasText(code, "wechat pay oauth2 code is required");
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("appid", appId);
|
||||
queryParams.add("secret", secret);
|
||||
queryParams.add("code", code);
|
||||
queryParams.add("grant_type", "authorization_code");
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(TOKEN_URI)
|
||||
.queryParams(queryParams)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
RequestEntity<Void> requestEntity = RequestEntity.get(uri).build();
|
||||
ResponseEntity<ObjectNode> responseEntity = restOperations.exchange(requestEntity, ObjectNode.class);
|
||||
ObjectNode body = responseEntity.getBody();
|
||||
if (Objects.nonNull(body)) {
|
||||
JsonNode openid = body.get("openid");
|
||||
return openid.asText();
|
||||
}
|
||||
throw new PayException("OpenId Not Available");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -2,10 +2,11 @@ package com.enongm.dianji.payment.wechat.v3;
|
||||
|
||||
import com.enongm.dianji.payment.PayException;
|
||||
import com.enongm.dianji.payment.wechat.WechatPayProperties;
|
||||
import com.enongm.dianji.payment.wechat.enumeration.StockStatus;
|
||||
import com.enongm.dianji.payment.wechat.enumeration.WeChatServer;
|
||||
import com.enongm.dianji.payment.wechat.enumeration.WechatPayV3Type;
|
||||
import com.enongm.dianji.payment.wechat.v3.model.AppPayParams;
|
||||
import com.enongm.dianji.payment.wechat.v3.model.StocksMchQueryParams;
|
||||
import com.enongm.dianji.payment.wechat.v3.model.StocksQueryParams;
|
||||
import com.enongm.dianji.payment.wechat.v3.model.StocksSendParams;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -15,11 +16,17 @@ 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.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The type Wechat pay v 3 api.
|
||||
@@ -85,15 +92,15 @@ public class WechatPayV3Api {
|
||||
|
||||
|
||||
/**
|
||||
* 查询代金券可用商户API
|
||||
* 查询该代金券可用的商户
|
||||
*
|
||||
* @param params the params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryMerchantsByStockId(StocksMchQueryParams params) {
|
||||
public WechatResponseEntity<ObjectNode> queryMerchantsByStockId(StocksQueryParams params) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
wechatPayV3Client.withType(WechatPayV3Type.MARKETING_FAVOR_STOCKS_MERCHANTS, params)
|
||||
.function(this::queryMerchantsFunction)
|
||||
.function(this::queryStocksFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
|
||||
@@ -102,22 +109,63 @@ public class WechatPayV3Api {
|
||||
}
|
||||
|
||||
|
||||
private RequestEntity<?> queryMerchantsFunction(WechatPayV3Type type, StocksMchQueryParams params) {
|
||||
/**
|
||||
* 分页查询商户下的代金券批次.
|
||||
*
|
||||
* @param params the params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryStocksByMch(StocksQueryParams params) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
wechatPayV3Client.withType(WechatPayV3Type.MARKETING_FAVOR_STOCKS, params)
|
||||
.function(this::queryStocksFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
|
||||
private RequestEntity<?> queryStocksFunction(WechatPayV3Type type, StocksQueryParams params) {
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("offset", String.valueOf(params.getOffset()));
|
||||
queryParams.add("limit", String.valueOf(params.getLimit()));
|
||||
queryParams.add("stock_creator_mchid", params.getStockCreatorMchid());
|
||||
String httpUrl = type.uri(WeChatServer.CHINA);
|
||||
WechatPayProperties.V3 v3 = wechatMetaBean.getWechatPayProperties().getV3();
|
||||
queryParams.add("stock_creator_mchid", v3.getMchId());
|
||||
LocalDateTime createStartTime = params.getCreateStartTime();
|
||||
if (Objects.nonNull(createStartTime)) {
|
||||
//rfc 3339 YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE
|
||||
queryParams.add("create_start_time", createStartTime.atOffset(ZoneOffset.ofHours(8))
|
||||
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
|
||||
}
|
||||
LocalDateTime createEndTime = params.getCreateEndTime();
|
||||
if (Objects.nonNull(createEndTime)) {
|
||||
//rfc 3339 YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE
|
||||
queryParams.add("create_end_time", createEndTime.atOffset(ZoneOffset.ofHours(8))
|
||||
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
|
||||
}
|
||||
StockStatus status = params.getStatus();
|
||||
if (Objects.nonNull(status)) {
|
||||
queryParams.add("status", status.value());
|
||||
}
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl)
|
||||
String stockId = params.getStockId();
|
||||
|
||||
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParams(queryParams)
|
||||
.build()
|
||||
.expand(params.getStockId()).toUri();
|
||||
.build();
|
||||
|
||||
if (StringUtils.hasText(stockId)) {
|
||||
uriComponents = uriComponents.expand(stockId);
|
||||
}
|
||||
|
||||
URI uri = uriComponents
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发放代金券API.
|
||||
*
|
||||
@@ -134,7 +182,7 @@ public class WechatPayV3Api {
|
||||
}
|
||||
|
||||
|
||||
private RequestEntity<?> sendStocksFunction(WechatPayV3Type type,StocksSendParams params){
|
||||
private RequestEntity<?> sendStocksFunction(WechatPayV3Type type, StocksSendParams params) {
|
||||
|
||||
String httpUrl = type.uri(WeChatServer.CHINA);
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(httpUrl).build().expand(params.getOpenid()).toUri();
|
||||
|
||||
@@ -20,77 +20,10 @@ import java.util.function.Consumer;
|
||||
* @since 14 :01
|
||||
*/
|
||||
@Getter
|
||||
public class WechatRequestEntity<T> extends RequestEntity<T> {
|
||||
public class WechatRequestEntity<T> extends RequestEntity<T> {
|
||||
|
||||
private final Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer;
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
* @param method the method
|
||||
* @param url the url
|
||||
* @param responseBodyConsumer the response body consumer
|
||||
*/
|
||||
public WechatRequestEntity(HttpMethod method, URI url, Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer) {
|
||||
super(method, url);
|
||||
this.responseBodyConsumer = responseBodyConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
* @param body the body
|
||||
* @param method the method
|
||||
* @param url the url
|
||||
* @param responseBodyConsumer the response body consumer
|
||||
*/
|
||||
public WechatRequestEntity(T body, HttpMethod method, URI url, Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer) {
|
||||
super(body, method, url);
|
||||
this.responseBodyConsumer = responseBodyConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
* @param body the body
|
||||
* @param method the method
|
||||
* @param url the url
|
||||
* @param type the type
|
||||
* @param responseBodyConsumer the response body consumer
|
||||
*/
|
||||
public WechatRequestEntity(T body, HttpMethod method, URI url, Type type, Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer) {
|
||||
super(body, method, url, type);
|
||||
this.responseBodyConsumer = responseBodyConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
* @param headers the headers
|
||||
* @param method the method
|
||||
* @param url the url
|
||||
* @param responseBodyConsumer the response body consumer
|
||||
*/
|
||||
public WechatRequestEntity(MultiValueMap<String, String> headers, HttpMethod method, URI url, Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer) {
|
||||
super(headers, method, url);
|
||||
this.responseBodyConsumer = responseBodyConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
* @param body the body
|
||||
* @param headers the headers
|
||||
* @param method the method
|
||||
* @param url the url
|
||||
* @param responseBodyConsumer the response body consumer
|
||||
*/
|
||||
public WechatRequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url, Consumer<ResponseEntity<ObjectNode>> responseBodyConsumer) {
|
||||
super(body, headers, method, url);
|
||||
this.responseBodyConsumer = responseBodyConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat request entity.
|
||||
*
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.enongm.dianji.payment.wechat.v3.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Dax
|
||||
* @since 16:22
|
||||
*/
|
||||
@Data
|
||||
public class StocksMchQueryParams {
|
||||
private int offset =1;
|
||||
private int limit = 10;
|
||||
private String stockCreatorMchid;
|
||||
private String stockId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.enongm.dianji.payment.wechat.v3.model;
|
||||
|
||||
import com.enongm.dianji.payment.wechat.enumeration.StockStatus;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author Dax
|
||||
* @since 15:16
|
||||
*/
|
||||
@Data
|
||||
public class StocksQueryParams {
|
||||
private int offset =0;
|
||||
private int limit = 10;
|
||||
private String stockId;
|
||||
private LocalDateTime createStartTime;
|
||||
private LocalDateTime createEndTime;
|
||||
private StockStatus status;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user