mirror of
https://github.com/dromara/payment-spring-boot.git
synced 2026-03-13 21:33:41 +08:00
多租户
This commit is contained in:
22
README.md
22
README.md
@@ -1,5 +1,5 @@
|
||||
# 移动支付 Spring Boot 组件
|
||||
提供聚合支付能力。
|
||||
# 移动支付 Spring Boot 组件 多租户版
|
||||
为了满足业务中出现app支付、公众号支付、小程序支付等多appid并存的场景,对原有的进行了增强开发出了多租户版本。
|
||||
|
||||
## 支持类型
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
wechat:
|
||||
pay:
|
||||
v3:
|
||||
# 租户id
|
||||
<tentantID>:
|
||||
# 应用appId 必填
|
||||
app-id: xxxxxxxx
|
||||
# api 密钥 必填
|
||||
@@ -62,9 +64,7 @@ public class PayConfig {
|
||||
微信支付V3开放接口引入:
|
||||
```java
|
||||
@Autowired
|
||||
WechatPayApi wechatPayV3Api;
|
||||
@Autowired
|
||||
WechatMarketingFavorApi wechatMarketingFavorApi;
|
||||
WechatApiProvider wechatApiProvider;
|
||||
```
|
||||
###### V3
|
||||
例如V3 查询商户下的优惠券
|
||||
@@ -73,11 +73,13 @@ public class PayConfig {
|
||||
// 查询商户下的优惠券
|
||||
@Test
|
||||
public void v3MchStocks() {
|
||||
StocksQueryParams params = new StocksQueryParams();
|
||||
params.setOffset(0);
|
||||
params.setLimit(10);
|
||||
WechatResponseEntity<ObjectNode> objectNodeWechatResponseEntity = wechatMarketingFavorApi.queryStocksByMch(params);
|
||||
System.out.println("objectNodeWechatResponseEntity = " + objectNodeWechatResponseEntity);
|
||||
// 配置文件中对应的tenantID:
|
||||
String tenantId =<tenantID>;
|
||||
StocksQueryParams params = new StocksQueryParams();
|
||||
params.setOffset(0);
|
||||
params.setLimit(10);
|
||||
WechatResponseEntity<ObjectNode> objectNodeWechatResponseEntity = wechatApiProvider.favorApi(tenantId).queryStocksByMch(params);
|
||||
System.out.println("objectNodeWechatResponseEntity = " + objectNodeWechatResponseEntity);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ public enum WechatPayV3Type {
|
||||
*/
|
||||
CERT(HttpMethod.GET, "%s/v3/certificates"),
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
*/
|
||||
FILE_DOWNLOAD(HttpMethod.GET,"%s/v3/billdownload/file"),
|
||||
|
||||
/**
|
||||
* 微信公众号支付或者小程序支付.
|
||||
*/
|
||||
@@ -33,6 +38,14 @@ public enum WechatPayV3Type {
|
||||
* H5支付.
|
||||
*/
|
||||
MWEB(HttpMethod.POST, "%s/v3/pay/transactions/h5"),
|
||||
/**
|
||||
* 微信支付订单号查询.
|
||||
*/
|
||||
TRANSACTION_TRANSACTION_ID(HttpMethod.GET, "%s/v3/pay/transactions/id/{transaction_id}"),
|
||||
/**
|
||||
* 商户订单号查询.
|
||||
*/
|
||||
TRANSACTION_OUT_TRADE_NO(HttpMethod.GET, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}"),
|
||||
|
||||
|
||||
/**
|
||||
@@ -53,7 +66,7 @@ public enum WechatPayV3Type {
|
||||
*/
|
||||
MARKETING_FAVOR_USERS_COUPONS(HttpMethod.POST,"%s/v3/marketing/favor/users/{openid}/coupons"),
|
||||
/**
|
||||
* 重启代金券API
|
||||
* 重启代金券API.
|
||||
*/
|
||||
MARKETING_FAVOR_STOCKS_RESTART(HttpMethod.POST,"%s/v3/marketing/favor/stocks/{stock_id}/restart"),
|
||||
/**
|
||||
|
||||
@@ -50,9 +50,9 @@ public abstract class AbstractApi {
|
||||
return wechatPayClient.signatureProvider().wechatMetaContainer();
|
||||
}
|
||||
|
||||
protected RequestEntity<?> post(URI uri, Object params) {
|
||||
protected RequestEntity<?> post(URI uri, Object params,String tenantId) {
|
||||
try {
|
||||
return RequestEntity.post(uri)
|
||||
return RequestEntity.post(uri).header("Pay-TenantId",tenantId)
|
||||
.body(mapper.writeValueAsString(params));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new PayException("wechat app pay json failed");
|
||||
|
||||
@@ -63,11 +63,10 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
|
||||
String mchId = v3.getMchId();
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.toUri();
|
||||
params.setBelongMerchant(mchId);
|
||||
return post(uri, params);
|
||||
return post(uri, params,tenantId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,12 +107,11 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
params.setAppid(v3.getMp().getAppId());
|
||||
params.setStockCreatorMchid(v3.getMchId());
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.expand(params.getOpenid())
|
||||
.toUri();
|
||||
params.setOpenid(null);
|
||||
return post(uri, params);
|
||||
return post(uri, params,tenantId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,11 +151,10 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
body.put("stock_creator_mchid", mchId);
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.expand(stockId)
|
||||
.toUri();
|
||||
return post(uri, body);
|
||||
return post(uri, body,tenantId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,7 +177,6 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
private RequestEntity<?> queryStocksFunction(WechatPayV3Type type, StocksQueryParams params) {
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("pay_tenantId", this.tenantId());
|
||||
queryParams.add("offset", String.valueOf(params.getOffset()));
|
||||
queryParams.add("limit", String.valueOf(params.getLimit()));
|
||||
WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3();
|
||||
@@ -215,7 +211,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
|
||||
URI uri = uriComponents
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,14 +236,13 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("stock_creator_mchid", v3.getMchId());
|
||||
queryParams.add("pay_tenantId", this.tenantId());
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParams(queryParams)
|
||||
.build()
|
||||
.expand(stockId)
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
|
||||
}
|
||||
|
||||
@@ -274,7 +269,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("appid", v3.getMp().getAppId());
|
||||
queryParams.add("pay_tenantId", this.tenantId());
|
||||
|
||||
|
||||
MultiValueMap<String, String> pathParams = new LinkedMultiValueMap<>();
|
||||
pathParams.add("openid", params.getOpenId());
|
||||
@@ -284,7 +279,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
.build()
|
||||
.expand(pathParams)
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
|
||||
}
|
||||
|
||||
@@ -339,10 +334,8 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
final String ignore = "available_mchid";
|
||||
WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3();
|
||||
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("appid", v3.getMp().getAppId());
|
||||
queryParams.add("pay_tenantId", this.tenantId());
|
||||
String stockId = params.getStockId();
|
||||
if (StringUtils.hasText(stockId)) {
|
||||
queryParams.add("stock_id", stockId);
|
||||
@@ -371,7 +364,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
.build()
|
||||
.expand(params.getOpenId())
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
|
||||
}
|
||||
|
||||
@@ -408,11 +401,10 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
|
||||
private RequestEntity<?> downloadFlowFunction(WechatPayV3Type type, String stockId) {
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.expand(stockId)
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).build();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,6 +444,7 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
return RequestEntity.post(uri)
|
||||
.header("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.header("Meta-Info", metaStr)
|
||||
.header("Pay-TenantId",tenantId())
|
||||
.body(body);
|
||||
}
|
||||
|
||||
@@ -479,10 +472,9 @@ public class WechatMarketingFavorApi extends AbstractApi {
|
||||
body.put("notify_url", notifyUrl);
|
||||
body.put("switch", true);
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.toUri();
|
||||
return post(uri, body);
|
||||
return post(uri, body,tenantId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package cn.felord.payment.wechat.v3;
|
||||
|
||||
import cn.felord.payment.PayException;
|
||||
import cn.felord.payment.wechat.enumeration.WeChatServer;
|
||||
import cn.felord.payment.wechat.WechatPayProperties;
|
||||
import cn.felord.payment.wechat.enumeration.WechatPayV3Type;
|
||||
import cn.felord.payment.wechat.v3.model.PayParams;
|
||||
import cn.felord.payment.wechat.v3.model.TransactionQueryParams;
|
||||
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.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -19,6 +21,12 @@ import java.net.URI;
|
||||
*/
|
||||
public class WechatPayApi extends AbstractApi {
|
||||
|
||||
/**
|
||||
* Instantiates a new Wechat pay api.
|
||||
*
|
||||
* @param wechatPayClient the wechat pay client
|
||||
* @param tenantId the tenant id
|
||||
*/
|
||||
public WechatPayApi(WechatPayClient wechatPayClient, String tenantId) {
|
||||
super(wechatPayClient, tenantId);
|
||||
}
|
||||
@@ -29,10 +37,10 @@ public class WechatPayApi extends AbstractApi {
|
||||
* @param payParams the pay params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> app(PayParams payParams) {
|
||||
public WechatResponseEntity<ObjectNode> appPay(PayParams payParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.APP, payParams)
|
||||
.function(this::appPayFunction)
|
||||
.function(this::payFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
@@ -44,23 +52,97 @@ public class WechatPayApi extends AbstractApi {
|
||||
* @param payParams the pay params
|
||||
* @return wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> js(PayParams payParams) {
|
||||
public WechatResponseEntity<ObjectNode> jsPay(PayParams payParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.JSAPI, payParams)
|
||||
.function(this::appPayFunction)
|
||||
.function(this::payFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
private RequestEntity<?> appPayFunction(WechatPayV3Type type, PayParams payParams) {
|
||||
/**
|
||||
* Native下单API
|
||||
*
|
||||
* @param payParams the pay params
|
||||
* @return wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> nativePay(PayParams payParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.NATIVE, payParams)
|
||||
.function(this::payFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* H5下单API
|
||||
*
|
||||
* @param payParams the pay params
|
||||
* @return wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> h5Pay(PayParams payParams) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.MWEB, payParams)
|
||||
.function(this::payFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
private RequestEntity<?> payFunction(WechatPayV3Type type, PayParams payParams) {
|
||||
WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3();
|
||||
payParams.setAppid(v3.getAppId());
|
||||
payParams.setMchid(v3.getMchId());
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParam("pay_tenantId", this.tenantId())
|
||||
.build()
|
||||
.toUri();
|
||||
return post(uri, payParams);
|
||||
return post(uri, payParams,tenantId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付订单号查询API
|
||||
*
|
||||
* @param params the params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryTransactionById(TransactionQueryParams params) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.TRANSACTION_TRANSACTION_ID, params)
|
||||
.function(this::queryTransactionFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户订单号查询API
|
||||
*
|
||||
* @param params the params
|
||||
* @return the wechat response entity
|
||||
*/
|
||||
public WechatResponseEntity<ObjectNode> queryTransactionByOutTradeNo(TransactionQueryParams params) {
|
||||
WechatResponseEntity<ObjectNode> wechatResponseEntity = new WechatResponseEntity<>();
|
||||
this.client().withType(WechatPayV3Type.TRANSACTION_OUT_TRADE_NO, params)
|
||||
.function(this::queryTransactionFunction)
|
||||
.consumer(wechatResponseEntity::convert)
|
||||
.request();
|
||||
return wechatResponseEntity;
|
||||
}
|
||||
|
||||
private RequestEntity<?> queryTransactionFunction(WechatPayV3Type type, TransactionQueryParams params) {
|
||||
WechatPayProperties.V3 v3 = this.container().getWechatMeta(tenantId()).getV3();
|
||||
|
||||
MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
queryParams.add("mchid", params.getMchId());
|
||||
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
|
||||
.queryParams(queryParams)
|
||||
.build()
|
||||
.expand(params.getTransactionIdOrOutTradeNo())
|
||||
.toUri();
|
||||
return RequestEntity.get(uri).header("Pay-TenantId",tenantId()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -158,9 +158,8 @@ public class WechatPayClient {
|
||||
if (WechatPayV3Type.MARKETING_IMAGE_UPLOAD.pattern().contains(canonicalUrl)) {
|
||||
body = Objects.requireNonNull(headers.get("Meta-Info")).get(0);
|
||||
}
|
||||
MultiValueMap<String, String> queryParams = uri.getQueryParams();
|
||||
String tenantId = queryParams.getFirst("pay_tenantId");
|
||||
Assert.notNull(tenantId, "tenantId is required");
|
||||
|
||||
String tenantId = Objects.requireNonNull(headers.get("Pay-TenantId")).get(0);
|
||||
String authorization = signatureProvider.requestSign(tenantId,httpMethod.name(), canonicalUrl, body);
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
@@ -172,7 +171,8 @@ public class WechatPayClient {
|
||||
}
|
||||
httpHeaders.add("Authorization", authorization);
|
||||
httpHeaders.add("User-Agent", "X-Pay-Service");
|
||||
|
||||
httpHeaders.remove("Meta-Info");
|
||||
httpHeaders.remove("Pay-TenantId");
|
||||
return requestEntity.headers(httpHeaders);
|
||||
|
||||
}
|
||||
|
||||
@@ -43,8 +43,17 @@ public class PayParams {
|
||||
* 支付金额
|
||||
*/
|
||||
private Amount amount;
|
||||
|
||||
/**
|
||||
* 支付者 JSAPI/小程序下单 必传
|
||||
*/
|
||||
private Payer payer;
|
||||
/**
|
||||
* 优惠功能
|
||||
*/
|
||||
private Detail detail;
|
||||
/**
|
||||
* 场景信息
|
||||
*/
|
||||
private SceneInfo sceneInfo;
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.felord.payment.wechat.v3.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Dax
|
||||
* @since 17:42
|
||||
*/
|
||||
@Data
|
||||
public class TransactionQueryParams {
|
||||
private String mchId;
|
||||
private String transactionIdOrOutTradeNo;
|
||||
}
|
||||
Reference in New Issue
Block a user