✨ 添加新特性。灰度发布
♻️ 重构代码。 支付回调逻辑抽象 👽 由于外部API的改变而更新代码。 更新不在维护前端
This commit is contained in:
1 parent
b8121b20a4
commit
cebeb347bb
23 files changed
+232
-136
No files matched your search
@@ -19,15 +19,11 @@
|
||||
|
||||
package com.pig4cloud.pigx.auth.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.common.security.handler.MobileLoginSuccessHandler;
|
||||
import com.pig4cloud.pigx.common.security.mobile.MobileSecurityConfigurer;
|
||||
import com.pig4cloud.pigx.common.security.service.PigxUserDetailsService;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@@ -36,8 +32,6 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
|
||||
/**
|
||||
@@ -49,16 +43,6 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand
|
||||
@Order(90)
|
||||
@Configuration
|
||||
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
private ClientDetailsService clientDetailsService;
|
||||
@Autowired
|
||||
private PigxUserDetailsService userDetailsService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
protected void configure(HttpSecurity http) {
|
||||
@@ -96,19 +80,12 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public AuthenticationSuccessHandler mobileLoginSuccessHandler() {
|
||||
return MobileLoginSuccessHandler.builder()
|
||||
.objectMapper(objectMapper)
|
||||
.clientDetailsService(clientDetailsService)
|
||||
.passwordEncoder(passwordEncoder())
|
||||
.defaultAuthorizationServerTokenServices(defaultAuthorizationServerTokenServices).build();
|
||||
return new MobileLoginSuccessHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MobileSecurityConfigurer mobileSecurityConfigurer() {
|
||||
MobileSecurityConfigurer mobileSecurityConfigurer = new MobileSecurityConfigurer();
|
||||
mobileSecurityConfigurer.setMobileLoginSuccessHandler(mobileLoginSuccessHandler());
|
||||
mobileSecurityConfigurer.setUserDetailsService(userDetailsService);
|
||||
return mobileSecurityConfigurer;
|
||||
return new MobileSecurityConfigurer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@ public interface CommonConstants {
|
||||
/**
|
||||
* header 中租户ID
|
||||
*/
|
||||
String TENANT_ID = "TENANT_ID";
|
||||
String TENANT_ID = "TENANT-ID";
|
||||
|
||||
/**
|
||||
* header 中版本信息
|
||||
*/
|
||||
String VERSION = "VERSION";
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
|
||||
+22
-2
@@ -17,7 +17,8 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.gateway.configuration;
|
||||
|
||||
import com.pig4cloud.pigx.common.gateway.rule.DiscoveryEnabledRule;
|
||||
import com.pig4cloud.pigx.common.gateway.filter.GrayLoadBalancerClientFilter;
|
||||
import com.pig4cloud.pigx.common.gateway.rule.AbstractDiscoveryEnabledRule;
|
||||
import com.pig4cloud.pigx.common.gateway.rule.MetadataAwareRule;
|
||||
import com.pig4cloud.pigx.common.gateway.support.PigxRibbonRuleProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -28,7 +29,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
|
||||
import org.springframework.cloud.gateway.config.LoadBalancerProperties;
|
||||
import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@@ -50,7 +56,21 @@ public class PigxRibbonRuleAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public DiscoveryEnabledRule metadataAwareRule() {
|
||||
public AbstractDiscoveryEnabledRule metadataAwareRule() {
|
||||
return new MetadataAwareRule();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LoadBalancerClient.class)
|
||||
public LoadBalancerClient loadBalancerClient(SpringClientFactory springClientFactory) {
|
||||
return new RibbonLoadBalancerClient(springClientFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LoadBalancerClientFilter.class)
|
||||
public LoadBalancerClientFilter loadBalancerClientFilter(RibbonLoadBalancerClient client
|
||||
, LoadBalancerProperties properties) {
|
||||
return new GrayLoadBalancerClientFilter(client, properties);
|
||||
}
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: lengleng (wangiegie@gmail.com)
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.common.gateway.filter;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.gateway.config.LoadBalancerProperties;
|
||||
import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class GrayLoadBalancerClientFilter extends LoadBalancerClientFilter {
|
||||
private final RibbonLoadBalancerClient loadBalancer;
|
||||
|
||||
public GrayLoadBalancerClientFilter(RibbonLoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
|
||||
super(loadBalancer, properties);
|
||||
this.loadBalancer = loadBalancer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServiceInstance choose(ServerWebExchange exchange) {
|
||||
HttpHeaders headers = exchange.getRequest().getHeaders();
|
||||
return loadBalancer.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(), headers);
|
||||
}
|
||||
|
||||
}
|
||||
+7
-5
@@ -20,6 +20,7 @@ package com.pig4cloud.pigx.common.gateway.predicate;
|
||||
import com.netflix.loadbalancer.AbstractServerPredicate;
|
||||
import com.netflix.loadbalancer.PredicateKey;
|
||||
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public abstract class DiscoveryEnabledPredicate extends AbstractServerPredicate {
|
||||
public abstract class AbstractDiscoveryEnabledPredicate extends AbstractServerPredicate {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@@ -35,15 +36,16 @@ public abstract class DiscoveryEnabledPredicate extends AbstractServerPredicate
|
||||
@Override
|
||||
public boolean apply(@Nullable PredicateKey input) {
|
||||
return input != null
|
||||
&& input.getServer() instanceof NacosServer
|
||||
&& apply((NacosServer) input.getServer());
|
||||
&& input.getServer() instanceof NacosServer
|
||||
&& apply((NacosServer) input.getServer(), (HttpHeaders) input.getLoadBalancerKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the specific {@link NacosServer} matches this predicate.
|
||||
*
|
||||
* @param server the discovered server
|
||||
* @param server the discovered server
|
||||
* @param headers 请求头
|
||||
* @return whether the server matches the predicate
|
||||
*/
|
||||
protected abstract boolean apply(NacosServer server);
|
||||
abstract boolean apply(NacosServer server, HttpHeaders headers);
|
||||
}
|
||||
+26
-15
@@ -18,39 +18,50 @@
|
||||
package com.pig4cloud.pigx.common.gateway.predicate;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import com.pig4cloud.pigx.common.gateway.support.PigxRibbonRuleProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 基于 Metadata 的服务筛选
|
||||
* 基于 Metadata version 的服务筛选
|
||||
*
|
||||
* @author L.cm
|
||||
* @author lengleng
|
||||
*/
|
||||
public class MetadataAwarePredicate extends DiscoveryEnabledPredicate {
|
||||
@Slf4j
|
||||
public class GrayMetadataAwarePredicate extends AbstractDiscoveryEnabledPredicate {
|
||||
|
||||
@Override
|
||||
protected boolean apply(NacosServer server) {
|
||||
final Map<String, String> metadata = server.getMetadata();
|
||||
protected boolean apply(NacosServer server, HttpHeaders headers) {
|
||||
PigxRibbonRuleProperties ribbonProperties = SpringContextHolder.getBean(PigxRibbonRuleProperties.class);
|
||||
|
||||
// 获取配置
|
||||
PigxRibbonRuleProperties properties = SpringContextHolder.getBean(PigxRibbonRuleProperties.class);
|
||||
// 服务里的配置
|
||||
String localTag = properties.getTag();
|
||||
|
||||
if (StrUtil.isBlank(localTag)) {
|
||||
if (!ribbonProperties.isGrayEnabled()) {
|
||||
log.debug("gray closed,GrayMetadataAwarePredicate return true");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 本地有 tag,服务没有,返回 false
|
||||
String metaDataTag = metadata.get("tag");
|
||||
if (StrUtil.isBlank(metaDataTag)) {
|
||||
return false;
|
||||
final Map<String, String> metadata = server.getMetadata();
|
||||
String version = metadata.get(CommonConstants.VERSION);
|
||||
// 判断Nacos服务是否有版本标签
|
||||
if (StrUtil.isBlank(version)) {
|
||||
log.debug("nacos server tag is blank ,GrayMetadataAwarePredicate return true");
|
||||
return true;
|
||||
}
|
||||
|
||||
return metaDataTag.equals(localTag);
|
||||
// 判断请求中是否有版本
|
||||
String target = headers.getFirst(CommonConstants.VERSION);
|
||||
if (StrUtil.isBlank(target)) {
|
||||
log.debug("request headers version is blank,GrayMetadataAwarePredicate return true");
|
||||
return true;
|
||||
}
|
||||
|
||||
log.debug("请求版本:{} ,当前服务版本:{}", target, version);
|
||||
return target.equals(version);
|
||||
}
|
||||
|
||||
}
|
||||
+5
-5
@@ -19,7 +19,7 @@ package com.pig4cloud.pigx.common.gateway.rule;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.netflix.loadbalancer.*;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.DiscoveryEnabledPredicate;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.AbstractDiscoveryEnabledPredicate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
@@ -29,10 +29,10 @@ import java.util.List;
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public abstract class DiscoveryEnabledRule extends PredicateBasedRule {
|
||||
public abstract class AbstractDiscoveryEnabledRule extends PredicateBasedRule {
|
||||
private final CompositePredicate predicate;
|
||||
|
||||
public DiscoveryEnabledRule(DiscoveryEnabledPredicate discoveryEnabledPredicate) {
|
||||
public AbstractDiscoveryEnabledRule(AbstractDiscoveryEnabledPredicate discoveryEnabledPredicate) {
|
||||
Assert.notNull(discoveryEnabledPredicate, "Parameter 'discoveryEnabledPredicate' can't be null");
|
||||
this.predicate = createCompositePredicate(discoveryEnabledPredicate, new AvailabilityPredicate(this, null));
|
||||
}
|
||||
@@ -69,8 +69,8 @@ public abstract class DiscoveryEnabledRule extends PredicateBasedRule {
|
||||
*/
|
||||
public abstract List<Server> filterServers(List<Server> serverList);
|
||||
|
||||
private CompositePredicate createCompositePredicate(DiscoveryEnabledPredicate discoveryEnabledPredicate, AvailabilityPredicate availabilityPredicate) {
|
||||
private CompositePredicate createCompositePredicate(AbstractDiscoveryEnabledPredicate discoveryEnabledPredicate, AvailabilityPredicate availabilityPredicate) {
|
||||
return CompositePredicate.withPredicates(discoveryEnabledPredicate, availabilityPredicate)
|
||||
.build();
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -22,8 +22,8 @@ import cn.hutool.system.HostInfo;
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.pig4cloud.pigx.common.core.util.SpringContextHolder;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.DiscoveryEnabledPredicate;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.MetadataAwarePredicate;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.AbstractDiscoveryEnabledPredicate;
|
||||
import com.pig4cloud.pigx.common.gateway.predicate.GrayMetadataAwarePredicate;
|
||||
import com.pig4cloud.pigx.common.gateway.support.PigxRibbonRuleProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
@@ -38,13 +38,13 @@ import java.util.List;
|
||||
* @author dream.lu
|
||||
*/
|
||||
@Slf4j
|
||||
public class MetadataAwareRule extends DiscoveryEnabledRule {
|
||||
public class MetadataAwareRule extends AbstractDiscoveryEnabledRule {
|
||||
|
||||
public MetadataAwareRule() {
|
||||
this(new MetadataAwarePredicate());
|
||||
this(new GrayMetadataAwarePredicate());
|
||||
}
|
||||
|
||||
public MetadataAwareRule(DiscoveryEnabledPredicate predicate) {
|
||||
public MetadataAwareRule(AbstractDiscoveryEnabledPredicate predicate) {
|
||||
super(predicate);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,10 @@ public class MetadataAwareRule extends DiscoveryEnabledRule {
|
||||
PigxRibbonRuleProperties ribbonProperties = SpringContextHolder.getBean(PigxRibbonRuleProperties.class);
|
||||
List<String> priorIpPattern = ribbonProperties.getPriorIpPattern();
|
||||
|
||||
if (ribbonProperties.isGrayEnabled()) {
|
||||
return serverList;
|
||||
}
|
||||
|
||||
// 1. 查找是否有本机 ip
|
||||
HostInfo hostInfo = SystemUtil.getHostInfo();
|
||||
String hostIp = hostInfo.getAddress();
|
||||
|
||||
+3
-3
@@ -38,11 +38,11 @@ public class PigxRibbonRuleProperties {
|
||||
/**
|
||||
* 是否开启,默认:true
|
||||
*/
|
||||
private Boolean enabled = Boolean.TRUE;
|
||||
private boolean enabled = Boolean.TRUE;
|
||||
/**
|
||||
* 服务的tag,用于灰度,匹配:nacos.discovery.metadata.tag
|
||||
* 是否开启灰度路由,默认:false
|
||||
*/
|
||||
private String tag;
|
||||
private boolean grayEnabled;
|
||||
/**
|
||||
* 优先的ip列表,支持通配符,例如:10.20.0.8*、10.20.0.*
|
||||
*/
|
||||
|
||||
+8
-3
@@ -20,8 +20,9 @@ import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.pig4cloud.pigx.common.security.util.AuthUtils;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
@@ -46,12 +47,16 @@ import java.io.PrintWriter;
|
||||
* 手机号登录成功,返回oauth token
|
||||
*/
|
||||
@Slf4j
|
||||
@Builder
|
||||
public class MobileLoginSuccessHandler implements AuthenticationSuccessHandler {
|
||||
private static final String BASIC_ = "Basic ";
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Autowired
|
||||
private ClientDetailsService clientDetailsService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices;
|
||||
|
||||
/**
|
||||
@@ -98,7 +103,7 @@ public class MobileLoginSuccessHandler implements AuthenticationSuccessHandler {
|
||||
printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));
|
||||
} catch (IOException e) {
|
||||
throw new BadCredentialsException(
|
||||
"Failed to decode basic authentication token");
|
||||
"Failed to decode basic authentication token");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -30,7 +30,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -39,13 +38,14 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Component
|
||||
public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
private AuthenticationEventPublisher defaultAuthenticationEventPublisher;
|
||||
@Autowired
|
||||
private AuthenticationSuccessHandler mobileLoginSuccessHandler;
|
||||
@Autowired
|
||||
private PigxUserDetailsService userDetailsService;
|
||||
|
||||
@Override
|
||||
@@ -59,6 +59,6 @@ public class MobileSecurityConfigurer extends SecurityConfigurerAdapter<DefaultS
|
||||
MobileAuthenticationProvider mobileAuthenticationProvider = new MobileAuthenticationProvider();
|
||||
mobileAuthenticationProvider.setUserDetailsService(userDetailsService);
|
||||
http.authenticationProvider(mobileAuthenticationProvider)
|
||||
.addFilterAfter(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
.addFilterAfter(mobileAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,6 @@
|
||||
**/
|
||||
handleUpdate: function (row, index, done,loading) {
|
||||
putObj(row).then(data => {
|
||||
this.tableData.splice(index, 1, Object.assign({}, row))
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '修改成功',
|
||||
@@ -124,7 +123,6 @@
|
||||
**/
|
||||
handleSave: function (row, done,loading) {
|
||||
addObj(row).then(data => {
|
||||
this.tableData.push(Object.assign({}, row))
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
|
||||
+7
-1
@@ -36,6 +36,9 @@ public abstract class AbstractPayNotifyCallbakHandler implements PayNotifyCallba
|
||||
@Override
|
||||
public String handle(Map<String, String> params) {
|
||||
|
||||
// 初始化租户
|
||||
before(params);
|
||||
|
||||
// 去重处理
|
||||
if (duplicateChecker(params)) {
|
||||
return null;
|
||||
@@ -46,6 +49,9 @@ public abstract class AbstractPayNotifyCallbakHandler implements PayNotifyCallba
|
||||
return null;
|
||||
}
|
||||
|
||||
return parse(params);
|
||||
String result = parse(params);
|
||||
// 保存处理结果
|
||||
saveNotifyRecord(params, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+31
-2
@@ -19,16 +19,22 @@ package com.pig4cloud.pigx.pay.handler;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.jpay.alipay.AliPayApiConfig;
|
||||
import com.jpay.alipay.AliPayApiConfigKit;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
|
||||
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
|
||||
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
|
||||
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
|
||||
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
|
||||
import com.pig4cloud.pigx.pay.utils.PayConstants;
|
||||
import com.pig4cloud.pigx.pay.utils.TradeStatusEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -50,6 +56,17 @@ public class AlipayPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHand
|
||||
private final PayGoodsOrderService goodsOrderService;
|
||||
private final PayNotifyRecordService recordService;
|
||||
|
||||
/**
|
||||
* 维护租户信息
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
@Override
|
||||
public void before(Map<String, String> params) {
|
||||
Integer tenant = MapUtil.getInt(params, "tenant");
|
||||
TenantContextHolder.setTenantId(tenant);
|
||||
}
|
||||
|
||||
/**
|
||||
* 去重处理
|
||||
*
|
||||
@@ -107,9 +124,21 @@ public class AlipayPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHand
|
||||
*/
|
||||
@Override
|
||||
public String parse(Map<String, String> params) {
|
||||
String tradeStatus = EnumUtil.fromString(TradeStatusEnum.class, params.get("trade_status")).getStatus();
|
||||
|
||||
goodsOrderService.updateOrder(params);
|
||||
tradeOrderService.updateOrder(params);
|
||||
String orderNo = params.get("out_trade_no");
|
||||
PayGoodsOrder goodsOrder = goodsOrderService.getOne(Wrappers.<PayGoodsOrder>lambdaQuery()
|
||||
.eq(PayGoodsOrder::getPayOrderId, orderNo));
|
||||
goodsOrder.setStatus(tradeStatus);
|
||||
goodsOrderService.updateById(goodsOrder);
|
||||
|
||||
PayTradeOrder tradeOrder = tradeOrderService.getOne(Wrappers.<PayTradeOrder>lambdaQuery()
|
||||
.eq(PayTradeOrder::getOrderId, orderNo));
|
||||
Long succTime = MapUtil.getLong(params, "time_end");
|
||||
tradeOrder.setPaySuccTime(succTime);
|
||||
tradeOrder.setStatus(TradeStatusEnum.TRADE_SUCCESS.getStatus());
|
||||
tradeOrder.setChannelOrderNo(params.get("transaction_id"));
|
||||
tradeOrderService.updateById(tradeOrder);
|
||||
|
||||
return "success";
|
||||
}
|
||||
|
||||
+7
@@ -27,6 +27,13 @@ import java.util.Map;
|
||||
*/
|
||||
public interface PayNotifyCallbakHandler {
|
||||
|
||||
/**
|
||||
* 初始化执行
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
void before(Map<String, String> params);
|
||||
|
||||
/**
|
||||
* 去重处理
|
||||
*
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import cn.hutool.extra.servlet.ServletUtil;
|
||||
import com.jpay.ext.kit.PaymentKit;
|
||||
import com.jpay.weixin.api.WxPayApi;
|
||||
import com.jpay.weixin.api.WxPayApiConfigKit;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.pay.config.PayCommonProperties;
|
||||
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
|
||||
@@ -67,7 +68,7 @@ public class WeChatMpPayOrderHandler extends AbstractPayOrderHandler {
|
||||
public Object pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) {
|
||||
String ip = ServletUtil.getClientIP(request);
|
||||
Map<String, String> params = WxPayApiConfigKit.getWxPayApiConfig()
|
||||
.setAttach(goodsOrder.getGoodsId())
|
||||
.setAttach(TenantContextHolder.getTenantId().toString())
|
||||
.setBody(goodsOrder.getGoodsName())
|
||||
.setSpbillCreateIp(ip)
|
||||
.setTotalFee(goodsOrder.getAmount())
|
||||
|
||||
+33
-4
@@ -18,10 +18,15 @@
|
||||
package com.pig4cloud.pigx.pay.handler;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.jpay.ext.kit.PaymentKit;
|
||||
import com.jpay.weixin.api.WxPayApiConfigKit;
|
||||
import com.pig4cloud.pigx.common.data.tenant.TenantContextHolder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
|
||||
import com.pig4cloud.pigx.pay.entity.PayNotifyRecord;
|
||||
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
|
||||
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
|
||||
import com.pig4cloud.pigx.pay.service.PayNotifyRecordService;
|
||||
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
|
||||
@@ -49,6 +54,17 @@ public class WeChatPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHand
|
||||
private final PayGoodsOrderService goodsOrderService;
|
||||
private final PayNotifyRecordService recordService;
|
||||
|
||||
/**
|
||||
* 维护租户信息
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
@Override
|
||||
public void before(Map<String, String> params) {
|
||||
Integer tenant = MapUtil.getInt(params, "attach");
|
||||
TenantContextHolder.setTenantId(tenant);
|
||||
}
|
||||
|
||||
/**
|
||||
* 去重处理
|
||||
*
|
||||
@@ -90,10 +106,23 @@ public class WeChatPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHand
|
||||
*/
|
||||
@Override
|
||||
public String parse(Map<String, String> params) {
|
||||
params.put("trade_status", TradeStatusEnum.TRADE_SUCCESS.getDescription());
|
||||
String orderNo = params.get("out_trade_no");
|
||||
String tradeStatus = EnumUtil.fromString(TradeStatusEnum.class, params.get("result_code")).getStatus();
|
||||
|
||||
goodsOrderService.updateOrder(params);
|
||||
tradeOrderService.updateOrder(params);
|
||||
PayGoodsOrder goodsOrder = goodsOrderService.getOne(Wrappers.<PayGoodsOrder>lambdaQuery()
|
||||
.eq(PayGoodsOrder::getPayOrderId, orderNo));
|
||||
goodsOrder.setStatus(tradeStatus);
|
||||
goodsOrderService.updateById(goodsOrder);
|
||||
|
||||
PayTradeOrder tradeOrder = tradeOrderService.getOne(Wrappers.<PayTradeOrder>lambdaQuery()
|
||||
.eq(PayTradeOrder::getOrderId, orderNo));
|
||||
Long succTime = MapUtil.getLong(params, "time_end");
|
||||
tradeOrder.setPaySuccTime(succTime);
|
||||
tradeOrder.setStatus(tradeStatus);
|
||||
tradeOrder.setChannelOrderNo(params.get("transaction_id"));
|
||||
tradeOrder.setErrMsg(params.get("err_code_des"));
|
||||
tradeOrder.setErrCode(params.get("err_code"));
|
||||
tradeOrderService.updateById(tradeOrder);
|
||||
|
||||
Map<String, String> xml = new HashMap<>(4);
|
||||
xml.put("return_code", "SUCCESS");
|
||||
@@ -110,7 +139,7 @@ public class WeChatPayNotifyCallbackHandler extends AbstractPayNotifyCallbakHand
|
||||
@Override
|
||||
public void saveNotifyRecord(Map<String, String> params, String result) {
|
||||
PayNotifyRecord record = new PayNotifyRecord();
|
||||
String notifyId = params.get("notify_id");
|
||||
String notifyId = params.get("transaction_id");
|
||||
record.setNotifyId(notifyId);
|
||||
String orderNo = params.get("out_trade_no");
|
||||
record.setOrderNo(orderNo);
|
||||
|
||||
-6
@@ -38,10 +38,4 @@ public interface PayGoodsOrderService extends IService<PayGoodsOrder> {
|
||||
*/
|
||||
Map<String, Object> buy(PayGoodsOrder goodsOrder);
|
||||
|
||||
/**
|
||||
* 更新订单
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
void updateOrder(Map<String, String> params);
|
||||
}
|
||||
-8
@@ -20,8 +20,6 @@ package com.pig4cloud.pigx.pay.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付
|
||||
*
|
||||
@@ -30,10 +28,4 @@ import java.util.Map;
|
||||
*/
|
||||
public interface PayTradeOrderService extends IService<PayTradeOrder> {
|
||||
|
||||
/**
|
||||
* 更新支付订单
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
void updateOrder(Map<String, String> params);
|
||||
}
|
||||
-23
@@ -16,20 +16,15 @@
|
||||
*/
|
||||
package com.pig4cloud.pigx.pay.service.impl;
|
||||
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.pig4cloud.pigx.pay.entity.PayGoodsOrder;
|
||||
import com.pig4cloud.pigx.pay.handler.PayOrderHandler;
|
||||
import com.pig4cloud.pigx.pay.mapper.PayGoodsOrderMapper;
|
||||
import com.pig4cloud.pigx.pay.service.PayGoodsOrderService;
|
||||
import com.pig4cloud.pigx.pay.utils.PayChannelNameEnum;
|
||||
import com.pig4cloud.pigx.pay.utils.PayConstants;
|
||||
import com.pig4cloud.pigx.pay.utils.TradeStatusEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -74,22 +69,4 @@ public class PayGoodsOrderServiceImpl extends ServiceImpl<PayGoodsOrderMapper, P
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步更新商品订单
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateOrder(Map<String, String> params) {
|
||||
PayGoodsOrder goodsOrder = new PayGoodsOrder();
|
||||
String tradeStatus = EnumUtil.fromString(TradeStatusEnum.class, params.get("trade_status")).getStatus();
|
||||
goodsOrder.setStatus(tradeStatus);
|
||||
this.baseMapper.update(goodsOrder, Wrappers.<PayGoodsOrder>lambdaQuery()
|
||||
.eq(PayGoodsOrder::getPayOrderId, params.
|
||||
get(PayConstants.OUT_TRADE_NO)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-20
@@ -20,13 +20,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.pig4cloud.pigx.pay.entity.PayTradeOrder;
|
||||
import com.pig4cloud.pigx.pay.mapper.PayTradeOrderMapper;
|
||||
import com.pig4cloud.pigx.pay.service.PayTradeOrderService;
|
||||
import com.pig4cloud.pigx.pay.utils.PayConstants;
|
||||
import com.pig4cloud.pigx.pay.utils.TradeStatusEnum;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 支付
|
||||
@@ -37,18 +31,4 @@ import java.util.Map;
|
||||
@Service
|
||||
public class PayTradeOrderServiceImpl extends ServiceImpl<PayTradeOrderMapper, PayTradeOrder> implements PayTradeOrderService {
|
||||
|
||||
/**
|
||||
* 更新支付订单
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateOrder(Map<String, String> params) {
|
||||
PayTradeOrder payTradeOrder = this.baseMapper.selectById(params.get(PayConstants.OUT_TRADE_NO));
|
||||
payTradeOrder.setStatus(TradeStatusEnum.TRADE_SUCCESS.getStatus());
|
||||
payTradeOrder.setChannelOrderNo(params.get("trade_no"));
|
||||
this.baseMapper.updateById(payTradeOrder);
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -28,7 +28,17 @@ public enum TradeStatusEnum {
|
||||
/**
|
||||
* 交易关闭
|
||||
*/
|
||||
TRADE_FINISHED("TRADE_FINISHED", OrderStatusEnum.COMPLETE.getStatus());
|
||||
TRADE_FINISHED("TRADE_FINISHED", OrderStatusEnum.COMPLETE.getStatus()),
|
||||
|
||||
/**
|
||||
* 微信支付成功
|
||||
*/
|
||||
SUCCESS("SUCCESS", OrderStatusEnum.SUCCESS.getStatus()),
|
||||
|
||||
/**
|
||||
* 微信支付失败
|
||||
*/
|
||||
FAIL("FAIL", OrderStatusEnum.FAIL.getStatus());
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<title>Pigx Pro 支付模块</title>
|
||||
</head>
|
||||
<script src="//cdn.jsdelivr.net/jquery/1.12.1/jquery.min.js"></script>
|
||||
|
||||
|
||||
Reference in new issue
Block a user