From 1e62944b3f9043de99288a2cc2ff6ea4a25e0293 Mon Sep 17 00:00:00 2001 From: yang_shj Date: Sat, 26 Feb 2022 15:13:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:0=20=E6=94=AF=E4=BB=98=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- payment-base-app/pom.xml | 25 +- .../aspect/annotation/BusinessException.java | 29 ++ .../springcloud/aspect/annotation/Rlock.java | 42 +++ .../aspect/BusinessExceptionHandler.java | 24 ++ .../aspect/aspect/RlockAspect.java | 118 ++++++ .../base/springcloud/base/CommonResult.java | 8 + .../springcloud/constant/ErrorConstant.java | 10 +- .../FastJson2JsonRedisSerializer.java | 59 +++ .../springcloud/constant/PaymentConstant.java | 5 + .../springcloud/constant/RedisConfig.java | 58 +++ .../controller/MerchantController.java | 2 +- .../springcloud/dto/MerchantConfigReqDTO.java | 33 +- .../springcloud/entity/CallbackBodyVo.java | 74 ++++ .../springcloud/entity/WxpayRefundVo.java | 57 +++ .../base/springcloud/entity/WxpayTradeVo.java | 119 ++++++ .../springcloud/handle/RBSQueueHandler.java | 6 + .../service/imp/MerchantServiceImp.java | 8 +- .../service/imp/OrderServiceImp.java | 12 +- .../service/imp/PaymentServiceImp.java | 19 +- .../base/springcloud/util/StringHelper.java | 21 ++ .../com/base/springcloud/util/WxpayUtils.java | 344 ++++++++++++++++++ .../src/main/resources/application.yml | 19 + .../payment/mapper/MerchantConfigMapper.xml | 6 + .../com/base/payment/mapper/OrderMapper.xml | 7 +- .../target/classes/application.yml | 34 +- pom.xml | 6 - 26 files changed, 1094 insertions(+), 51 deletions(-) create mode 100644 payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/BusinessException.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/Rlock.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/BusinessExceptionHandler.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/RlockAspect.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/constant/FastJson2JsonRedisSerializer.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/constant/RedisConfig.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/entity/CallbackBodyVo.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/entity/WxpayRefundVo.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/entity/WxpayTradeVo.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/util/StringHelper.java create mode 100644 payment-base-app/src/main/java/com/base/springcloud/util/WxpayUtils.java diff --git a/payment-base-app/pom.xml b/payment-base-app/pom.xml index c8e4ea1..004e5c8 100644 --- a/payment-base-app/pom.xml +++ b/payment-base-app/pom.xml @@ -73,11 +73,18 @@ 2.9.2 + + + com.google.code.gson + gson + 2.2.4 + + com.github.wechatpay-apiv3 wechatpay-apache-httpclient - 0.4.2 + 0.2.2 @@ -93,6 +100,22 @@ spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.redisson + redisson-spring-boot-starter + 3.15.1 + + + com.alibaba + fastjson + 1.2.47 + + org.apache.httpcomponents httpclient diff --git a/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/BusinessException.java b/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/BusinessException.java new file mode 100644 index 0000000..f5dff7a --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/BusinessException.java @@ -0,0 +1,29 @@ +package com.base.springcloud.aspect.annotation; + +import com.base.springcloud.constant.ErrorConstant; +import lombok.Getter; + +@Getter +public class BusinessException extends RuntimeException{ + + private String code; + + /** + * 使用已有的错误类型 + * @param type 枚举类中的错误类型 + */ + public BusinessException(ErrorConstant type){ + super(type.getMessage()); + this.code = type.getCode(); + } + + /** + * 自定义错误类型 + * @param code 自定义的错误码 + * @param msg 自定义的错误提示 + */ + public BusinessException(String code, String msg){ + super(msg); + this.code = code; + } +} diff --git a/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/Rlock.java b/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/Rlock.java new file mode 100644 index 0000000..7980e9c --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/aspect/annotation/Rlock.java @@ -0,0 +1,42 @@ +package com.base.springcloud.aspect.annotation; + +import java.lang.annotation.*; +import java.util.concurrent.TimeUnit; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface Rlock { + + /** + * 分布式锁的key前缀 + */ + String prefix() default "redisLockPrefix::"; + + /** + * 分布式锁的key动态参数 + */ + String suffix() default "lockDynamicKey"; + + /** + * 等待时间 默认五秒 + * + * @return + */ + long waitTime() default 5; + + /** + * 锁释放时间 默认十秒 + * + * @return + */ + long leaseTime() default 10; + + /** + * 时间格式 默认:秒 + * + * @return + */ + TimeUnit timeUnit() default TimeUnit.SECONDS; +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/BusinessExceptionHandler.java b/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/BusinessExceptionHandler.java new file mode 100644 index 0000000..9e0c885 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/BusinessExceptionHandler.java @@ -0,0 +1,24 @@ +package com.base.springcloud.aspect.aspect; + +import com.base.springcloud.aspect.annotation.BusinessException; +import com.base.springcloud.base.CommonResult; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@ControllerAdvice +public class BusinessExceptionHandler { + + /** + * @ExceptionHandler相当于controller的@RequestMapping + * 如果抛出的的是BusinessException,则调用该方法 + * @param se 业务异常 + * @return + */ + @ExceptionHandler(BusinessException.class) + @ResponseBody + public CommonResult handle(BusinessException se){ + return CommonResult.error(se.getCode(),se.getMessage()); + } +} + diff --git a/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/RlockAspect.java b/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/RlockAspect.java new file mode 100644 index 0000000..9279a75 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/aspect/aspect/RlockAspect.java @@ -0,0 +1,118 @@ +package com.base.springcloud.aspect.aspect; + +import com.base.springcloud.aspect.annotation.Rlock; +import com.base.springcloud.handle.RBSQueueHandler; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +@Aspect +@Component +@Slf4j +public class RlockAspect { + + Logger logger = LoggerFactory.getLogger(RBSQueueHandler.class); + + @Autowired + private RedissonClient redissonClient; + + /** + * 用于SpEL表达式解析. + */ + private SpelExpressionParser parser = new SpelExpressionParser(); + /** + * 用于获取方法参数定义名字. + */ + private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); + + + + @Pointcut("@annotation(com.base.springcloud.aspect.annotation.Rlock)") + public void RlockAspect() { + } + + @Around("RlockAspect()") + public Object arround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + Object object = null; + RLock lock = null; + try { + // 获取注解信息 + Rlock rlockInfo = getRlockInfo(proceedingJoinPoint); + String key = getLocalKey(proceedingJoinPoint, rlockInfo); + // 根据名字获取锁实例 + lock = redissonClient.getLock(key); + if (lock != null) { + final boolean status = lock.tryLock(rlockInfo.waitTime(), rlockInfo.leaseTime(), rlockInfo.timeUnit()); + if (status) { + logger.info("锁获取成功,加锁成功 : {}........",key); + object = proceedingJoinPoint.proceed(); + } else { + logger.info("锁被占用,加锁失败 : {} .........",key); + throw new RuntimeException("加锁失败"); + } + } + } finally { + // 方法执行完成释放锁 + if (lock != null && lock.isHeldByCurrentThread()) { + lock.unlock(); + } + } + return object; + } + + public Rlock getRlockInfo(ProceedingJoinPoint proceedingJoinPoint) { + MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature(); + return methodSignature.getMethod().getAnnotation(Rlock.class); + } + + /** + * @param proceedingJoinPoint + * @return + */ + public String getLocalKey(ProceedingJoinPoint proceedingJoinPoint, Rlock rlockInfo) { + StringBuilder localKey = new StringBuilder(); + //获取注解参数值 + String prefix = rlockInfo.prefix(); + String spELString = rlockInfo.suffix(); + String key = generateKeyBySpEL(spELString,proceedingJoinPoint); + localKey.append(prefix).append(key); + logger.info("加锁 key :{}",localKey.toString()); + return localKey.toString(); + } + + public String generateKeyBySpEL(String spELString, ProceedingJoinPoint joinPoint) { + // 通过joinPoint获取被注解方法 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + // 使用spring的DefaultParameterNameDiscoverer获取方法形参名数组 + String[] paramNames = nameDiscoverer.getParameterNames(method); + // 解析过后的Spring表达式对象 + Expression expression = parser.parseExpression(spELString); + // spring的表达式上下文对象 + EvaluationContext context = new StandardEvaluationContext(); + // 通过joinPoint获取被注解方法的形参 + Object[] args = joinPoint.getArgs(); + // 给上下文赋值 + for(int i = 0 ; i < args.length ; i++) { + context.setVariable(paramNames[i], args[i]); + } + // 表达式从上下文中计算出实际参数值 + return expression.getValue(context).toString(); + } +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/base/CommonResult.java b/payment-base-app/src/main/java/com/base/springcloud/base/CommonResult.java index e74764d..7344f08 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/base/CommonResult.java +++ b/payment-base-app/src/main/java/com/base/springcloud/base/CommonResult.java @@ -23,4 +23,12 @@ public class CommonResult { public CommonResult(String code, String message) { this(code,message,null); } + + public static CommonResult error(String code, String msg){ + CommonResult res = new CommonResult(); + res.setCode(code); + res.setMessage(msg); + return res; + } + } \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/constant/ErrorConstant.java b/payment-base-app/src/main/java/com/base/springcloud/constant/ErrorConstant.java index 0ecf6d1..d2d40fa 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/constant/ErrorConstant.java +++ b/payment-base-app/src/main/java/com/base/springcloud/constant/ErrorConstant.java @@ -8,7 +8,7 @@ public enum ErrorConstant { private String code; private String message; - private ErrorConstant(String code, String message) { + ErrorConstant(String code, String message) { this.setCode(code); this.setMessage(message); } @@ -28,12 +28,4 @@ public enum ErrorConstant { public void setMessage(String message) { this.message = message; } - - @Override - public String toString() { - return "ErrorConstant{" + - "code='" + code + '\'' + - ", message='" + message + '\'' + - '}'; - } } diff --git a/payment-base-app/src/main/java/com/base/springcloud/constant/FastJson2JsonRedisSerializer.java b/payment-base-app/src/main/java/com/base/springcloud/constant/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..1da92d8 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/constant/FastJson2JsonRedisSerializer.java @@ -0,0 +1,59 @@ +package com.base.springcloud.constant; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import org.springframework.util.Assert; + +import java.nio.charset.Charset; + +/** + * FastJson2JsonRedisSerializer + * Redis使用FastJson序列化 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + private ObjectMapper objectMapper = new ObjectMapper(); + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().setAutoTypeSupport(true); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz); + } + + public void setObjectMapper(ObjectMapper objectMapper) { + Assert.notNull(objectMapper, "'objectMapper' must not be null"); + this.objectMapper = objectMapper; + } + + protected JavaType getJavaType(Class clazz) { + return TypeFactory.defaultInstance().constructType(clazz); + } + +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/constant/PaymentConstant.java b/payment-base-app/src/main/java/com/base/springcloud/constant/PaymentConstant.java index e9c52b2..b756fb1 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/constant/PaymentConstant.java +++ b/payment-base-app/src/main/java/com/base/springcloud/constant/PaymentConstant.java @@ -21,5 +21,10 @@ public interface PaymentConstant { String CP = "CP"; // 云闪付 String QRCCP = "QRCCP"; + String NATIVE = "Native"; // Native支付 + String H5 = "H5"; // H5支付 + String JSAPI = "Jsapi"; // JSAPI支付 + String ORDER_QUEUE = "order_queue"; // 订单队列 + String ORDER_LOCK_PREFIX = "ORDER_KEY:"; // 订单锁前缀 } diff --git a/payment-base-app/src/main/java/com/base/springcloud/constant/RedisConfig.java b/payment-base-app/src/main/java/com/base/springcloud/constant/RedisConfig.java new file mode 100644 index 0000000..da09b29 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/constant/RedisConfig.java @@ -0,0 +1,58 @@ +package com.base.springcloud.constant; + + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.redisson.Redisson; +import org.redisson.config.Config; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private String port; + + @Value("${spring.redis.password}") + private String password; + + @Bean + @SuppressWarnings(value = {"unchecked", "rawtypes"}) + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(redisConnectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(mapper); + + template.setValueSerializer(serializer); + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + return template; + } + + @Bean + public Redisson redisson() { + Config config = new Config(); + config.useSingleServer().setAddress("redis://" + host + ":" + port); + config.useSingleServer().setPassword(password); + return (Redisson) Redisson.create(config); + } +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/controller/MerchantController.java b/payment-base-app/src/main/java/com/base/springcloud/controller/MerchantController.java index ef14364..e5fcb86 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/controller/MerchantController.java +++ b/payment-base-app/src/main/java/com/base/springcloud/controller/MerchantController.java @@ -29,7 +29,7 @@ public class MerchantController { @PostMapping("/merchantConfig") public CommonResult paymentConfigure(@RequestBody MerchantConfigReqDTO merchantConfigDTO) { MerchantConfigBO merchantConfigBO = new MerchantConfigBO(); - BeanUtils.copyProperties(merchantConfigBO, merchantConfigDTO); + BeanUtils.copyProperties(merchantConfigDTO, merchantConfigBO); merchantService.paymentConfigure(merchantConfigBO); return new CommonResult(ErrorConstant.NULL_OBJ.getCode(), ErrorConstant.NULL_OBJ.getMessage(), null); } diff --git a/payment-base-app/src/main/java/com/base/springcloud/dto/MerchantConfigReqDTO.java b/payment-base-app/src/main/java/com/base/springcloud/dto/MerchantConfigReqDTO.java index d5bd608..469d3d0 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/dto/MerchantConfigReqDTO.java +++ b/payment-base-app/src/main/java/com/base/springcloud/dto/MerchantConfigReqDTO.java @@ -7,29 +7,28 @@ import java.io.File; @Data public class MerchantConfigReqDTO { + /** + * 微信支付证书文件 + */ private File certFile; + /** + * 公众号 + */ private String appId; + /** + * 商户私钥 + */ private String appKey; - private String certPath; + /** + * 证书序列号 + */ + private String serialNo; + /** + * 商户号 + */ private String merchantId; - - private String merchantName; - - private String cityStoreName; - - private String storeBrandName; - - private String signType; - - private String privateKey; - - private String deviceInfo; - - private String spbillCreateIp; - - private String notifyUrl; } diff --git a/payment-base-app/src/main/java/com/base/springcloud/entity/CallbackBodyVo.java b/payment-base-app/src/main/java/com/base/springcloud/entity/CallbackBodyVo.java new file mode 100644 index 0000000..2fc670a --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/entity/CallbackBodyVo.java @@ -0,0 +1,74 @@ +package com.base.springcloud.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 支付、退款数据回调通用 + * + * @author shuaifengjie.com + */ +@Data +public class CallbackBodyVo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -3279905156049535047L; + + + /** + * 通知Id + */ + private String id; + /** + * 通知创建时间 + */ + private String create_time; + /** + * 通知类型 + * 支付成功:TRANSACTION.SUCCESS + * 退款成功:REFUND.SUCCESS + */ + private String resource_type; + /** + * 通知数据类型 + */ + private String event_type; + /** + * 回调摘要 + */ + private String summary; + /** + * 通知数据 + */ + private Resource resource; + + /** + * 通知数据 + */ + @Data + public static class Resource { + /** + * 对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM。 + */ + private String algorithm; + /** + * Base64编码后的开启/停用结果数据密文。 + */ + private String ciphertext; + /** + * 附加数据。 + */ + private String associated_data; + /** + * 加密使用的随机串。 + */ + private String nonce; + /** + * 原始回调类型。 + */ + private String original_type; + } +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayRefundVo.java b/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayRefundVo.java new file mode 100644 index 0000000..068d10e --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayRefundVo.java @@ -0,0 +1,57 @@ +package com.base.springcloud.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 微信退款预下单-主体信息 + * @author shuaifengjie.com + * v3 + */ +@Data +public class WxpayRefundVo implements Serializable { + + private static final long serialVersionUID = 8189139771687842957L; + // 原支付交易对应的微信订单号 + // 示例值:1217752501201407033233368018 + private String transaction_id; + // 若商户传入,会在下发给用户的退款消息中体现退款原因 + // 示例值:商品已售完 + private String reason; + // 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 + // 示例值:1217752501201407033233368018 + private String out_refund_no; + // 异步接收微信支付退款结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效,优先回调当前传的这个地址。 + // 示例值:https://weixin.qq.com + private String notify_url; + // 订单金额信息 + private WxRefundAmountVo amount; + + public WxpayRefundVo() { + super(); + } + + @Data + public static class WxRefundAmountVo { + // 退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。 + // 示例值:888 + private long refund; + // 原支付交易的订单总金额,币种的最小单位,只能为整数。 + // 示例值:888 + private long total; + // CNY:人民币,境内商户号仅支持人民币。 + // 示例值:CNY + private String currency = "CNY"; + + public WxRefundAmountVo() { + super(); + } + + public WxRefundAmountVo(long refund, long total) { + super(); + this.refund = refund; + this.total = total; + } + } +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayTradeVo.java b/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayTradeVo.java new file mode 100644 index 0000000..e57629f --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/entity/WxpayTradeVo.java @@ -0,0 +1,119 @@ +package com.base.springcloud.entity; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 微信支付预下单-主体信息 + * @author shuaifengjie.com + * v3 + */ +@Data +public class WxpayTradeVo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 8189139771687842957L; + + // 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,应为公众号的APPID + // 示例值:wxd678efh567hg6787 + private String appid; + + // 直连商户的商户号,由微信支付生成并下发。 + // 示例值:1230000109 + private String mchid; + + // 商品描述 + // 示例值:Image形象店-深圳腾大-QQ公仔 + private String description; + + // 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + // 示例值:1217752501201407033233368018 + private String out_trade_no; + + // 通知URL必须为直接可访问的URL,不允许携带查询串。 + // 示例值:https://www.weixin.qq.com/wxpay/pay.php + private String notify_url; + + // 订单金额信息 + private WxTradeAmountVo amount; + + // 支付者信息 - JSAPI,必传 + private WxPayerVo payer; + + // 支付场景描述 - H5,必传 + private WxSceneInfoVo scene_info; + + public WxpayTradeVo() { + super(); + } + + public WxpayTradeVo(String appid, String mchid, String description, String out_trade_no, String notify_url) { + super(); + this.appid = appid; + this.mchid = mchid; + this.description = description; + this.out_trade_no = out_trade_no; + this.notify_url = notify_url; + } + + @Data + public static class WxTradeAmountVo { + // 订单总金额,单位为分。 + // 示例值:100 + private long total; + // CNY:人民币,境内商户号仅支持人民币。 + // 示例值:CNY + private String currency = "CNY"; + + public WxTradeAmountVo() { + super(); + } + public WxTradeAmountVo(long total) { + super(); + this.total = total; + } + } + + @Data + public static class WxPayerVo { + // 用户在直连商户appid下的唯一标识。 下单前需获取到用户的Openid,Openid获取详见 + // 示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o + private String openid; + + public WxPayerVo() { + super(); + } + public WxPayerVo(String openid) { + super(); + this.openid = openid; + } + } + + @Data + public static class WxSceneInfoVo { + // 用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。 + // 示例值:14.23.150.211 + private String payer_client_ip; + // H5场景信息 + private WxH5InfoVo h5_info; + + public WxSceneInfoVo() { + super(); + } + public WxSceneInfoVo(String payer_client_ip) { + super(); + this.payer_client_ip = payer_client_ip; + } + } + + @Data + public static class WxH5InfoVo { + // 场景类型 + // 示例值:iOS, Android, Wap + private String type = "Wap"; + } + +} \ No newline at end of file diff --git a/payment-base-app/src/main/java/com/base/springcloud/handle/RBSQueueHandler.java b/payment-base-app/src/main/java/com/base/springcloud/handle/RBSQueueHandler.java index b81d0a6..6777d2f 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/handle/RBSQueueHandler.java +++ b/payment-base-app/src/main/java/com/base/springcloud/handle/RBSQueueHandler.java @@ -1,7 +1,11 @@ package com.base.springcloud.handle; +import com.base.springcloud.aspect.annotation.Rlock; import com.base.springcloud.entity.Order; +import com.base.springcloud.schedule.OrderTask; import com.base.springcloud.service.PaymentService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -9,6 +13,8 @@ import org.springframework.stereotype.Component; @Component public class RBSQueueHandler { + Logger logger = LoggerFactory.getLogger(RBSQueueHandler.class); + @Autowired private PaymentService paymentService; diff --git a/payment-base-app/src/main/java/com/base/springcloud/service/imp/MerchantServiceImp.java b/payment-base-app/src/main/java/com/base/springcloud/service/imp/MerchantServiceImp.java index 4c3efe6..170472a 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/service/imp/MerchantServiceImp.java +++ b/payment-base-app/src/main/java/com/base/springcloud/service/imp/MerchantServiceImp.java @@ -16,6 +16,7 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; @Service @@ -34,11 +35,12 @@ public class MerchantServiceImp implements MerchantService { @Override public void paymentConfigure(MerchantConfigBO merchantConfigBO) { // 证书上传服务器 - String certPath = uplodWecPayCert(merchantConfigBO.getMerchantId(),merchantConfigBO.getCertfile()); + //String certPath = uplodWecPayCert(merchantConfigBO.getMerchantId(),merchantConfigBO.getCertfile()); // 商户支付信息保存 - merchantConfigBO.setCertPath(certPath); + //merchantConfigBO.setCertPath(certPath); MerchantConfig merchantConfig = new MerchantConfig(); - BeanUtils.copyProperties(merchantConfig,merchantConfigBO); + merchantConfig.setId(UUID.randomUUID().toString().replace("-", "")); + BeanUtils.copyProperties(merchantConfigBO,merchantConfig); merchantConfigMapper.insert(merchantConfig); } diff --git a/payment-base-app/src/main/java/com/base/springcloud/service/imp/OrderServiceImp.java b/payment-base-app/src/main/java/com/base/springcloud/service/imp/OrderServiceImp.java index d01b9d6..2f6a748 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/service/imp/OrderServiceImp.java +++ b/payment-base-app/src/main/java/com/base/springcloud/service/imp/OrderServiceImp.java @@ -12,10 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; -import java.util.Date; -import java.util.List; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; @Service @@ -51,11 +48,12 @@ public class OrderServiceImp implements OrderService { if(!Optional.ofNullable(orderList).isPresent()){ return null; } - List orderBOList = orderList.stream().map(o -> { + return orderList.stream().map(o -> { OrderBO orderBO = new OrderBO(); - BeanUtils.copyProperties(orderBO,o); + Order order = new Order(); + BeanUtils.copyProperties(o,order); + orderBO.setOrder(order); return orderBO; }).collect(Collectors.toList()); - return orderBOList; } } diff --git a/payment-base-app/src/main/java/com/base/springcloud/service/imp/PaymentServiceImp.java b/payment-base-app/src/main/java/com/base/springcloud/service/imp/PaymentServiceImp.java index 217a94b..907f2b3 100644 --- a/payment-base-app/src/main/java/com/base/springcloud/service/imp/PaymentServiceImp.java +++ b/payment-base-app/src/main/java/com/base/springcloud/service/imp/PaymentServiceImp.java @@ -1,5 +1,6 @@ package com.base.springcloud.service.imp; +import com.base.springcloud.aspect.annotation.Rlock; import com.base.springcloud.bo.OrderBO; import com.base.springcloud.constant.PaymentConstant; import com.base.springcloud.entity.Order; @@ -7,11 +8,12 @@ import com.base.springcloud.service.BillService; import com.base.springcloud.service.OrderService; import com.base.springcloud.service.PaymentService; import com.base.springcloud.service.WecPaymentService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import javax.xml.crypto.Data; import java.util.Date; import java.util.List; import java.util.Optional; @@ -19,6 +21,8 @@ import java.util.Optional; @Service public class PaymentServiceImp implements PaymentService { + Logger logger = LoggerFactory.getLogger(PaymentServiceImp.class); + @Autowired private OrderService orderService; @@ -52,12 +56,12 @@ public class PaymentServiceImp implements PaymentService { public void syncOrderInfo(Date date) { // 获取订单列表 List orderList = orderService.queryOrder(date); - if(Optional.ofNullable(orderList).isPresent()) return; + if(!Optional.ofNullable(orderList).isPresent()) return; // 遍历查询第三方订单信息 for (OrderBO orderBO : orderList){ // 异步处理数据 - amqpTemplate.convertSendAndReceive(PaymentConstant.ORDER_QUEUE,orderBO); + amqpTemplate.convertSendAndReceive(PaymentConstant.ORDER_QUEUE,orderBO.getOrder()); } } @@ -66,8 +70,15 @@ public class PaymentServiceImp implements PaymentService { * @param order */ @Override + @Rlock(prefix = PaymentConstant.ORDER_LOCK_PREFIX, suffix = "#order.orderNo",waitTime = 0,leaseTime = 60) public void queryOrder(Order order) { - + logger.info("线程 : {} 开始睡觉....",Thread.currentThread().getName()); + try { + Thread.sleep(10000); + }catch (Exception e){ + logger.info(e.getMessage()); + } + logger.info("线程 : {} 结束睡觉....",Thread.currentThread().getName()); } // 参数检查 diff --git a/payment-base-app/src/main/java/com/base/springcloud/util/StringHelper.java b/payment-base-app/src/main/java/com/base/springcloud/util/StringHelper.java new file mode 100644 index 0000000..89e5d40 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/util/StringHelper.java @@ -0,0 +1,21 @@ +package com.base.springcloud.util; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; + +import java.util.Map; + +public class StringHelper { + + public static Map json2map(String str_json) { + Map res = null; + try { + Gson gson = new Gson(); + res = gson.fromJson(str_json, new TypeToken>() { + }.getType()); + } catch (JsonSyntaxException e) { + } + return res; + } +} diff --git a/payment-base-app/src/main/java/com/base/springcloud/util/WxpayUtils.java b/payment-base-app/src/main/java/com/base/springcloud/util/WxpayUtils.java new file mode 100644 index 0000000..3546c82 --- /dev/null +++ b/payment-base-app/src/main/java/com/base/springcloud/util/WxpayUtils.java @@ -0,0 +1,344 @@ +package com.base.springcloud.util; + +import com.alibaba.fastjson.JSON; +import com.base.springcloud.constant.PaymentConstant; +import com.base.springcloud.entity.CallbackBodyVo; +import com.base.springcloud.entity.WxpayRefundVo; +import com.base.springcloud.entity.WxpayTradeVo; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; +import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.springframework.util.Base64Utils; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.cert.X509Certificate; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 微信支付帮助类 + * + * @author shuaifengjie.com + */ +@Slf4j +public class WxpayUtils { + + /** + * 发起支付 + * + * @param tradeVo + * @param scene + * @param privateKey + * @param certificate + * @param serialNo + * @return + */ + public static ObjectNode getWxpay(WxpayTradeVo tradeVo, String scene, String privateKey, String certificate, String serialNo) { + // ... + String responseBody = response(JSON.toJSONString(tradeVo), getUrl(scene), tradeVo.getMchid(), privateKey, certificate, serialNo); + log.info("======>>> wxpay response body: ", responseBody); + // parse + @SuppressWarnings("unchecked") + Map resultMap = StringHelper.json2map(responseBody); + // ... + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode objectNode = objectMapper.createObjectNode(); + // ... + if (PaymentConstant.NATIVE.equals(scene)) {// pc - 扫码支付(Native) + objectNode.put("code_url", resultMap.get("code_url")); + } else if (PaymentConstant.H5.equals(scene)) {// 手机网页(H5) + objectNode.put("h5_url", resultMap.get("h5_url")); + } else if (PaymentConstant.JSAPI.equals(scene)) {// 微信公众号(H5) + String prepayId = resultMap.get("prepay_id"); + objectNode.put("prepay_id", prepayId); + // ... + objectNode.put("appId", tradeVo.getAppid()); + String timestamp = getTimestamp(); + objectNode.put("timeStamp", timestamp); + String nonceStr = CreateNoncestr(); + objectNode.put("nonceStr", nonceStr); + String packageStr = "prepay_id=" + prepayId; + objectNode.put("package", packageStr); + // 签名 + String paySign = doRequestSign(privateKey, tradeVo.getAppid(), timestamp, nonceStr, packageStr); + objectNode.put("paySign", paySign); + objectNode.put("signType", "RSA"); + } + return objectNode; + } + + /** + * 发起退款 + * + * @param tradeVo + * @param mchid + * @param privateKey + * @param certificate + * @param serialNo + * @return + */ + public static void refund(WxpayRefundVo tradeVo, String mchid, String privateKey, String certificate, String serialNo) { + // ... + String responseBody = response(JSON.toJSONString(tradeVo), REFUND_URL, mchid, privateKey, certificate, serialNo); + log.info("======>>> wxrefund response body: ", responseBody); + } + + /** + * 公共请求 + * + * @param data + * @param url + * @param mchid + * @param privateKey + * @param certificate + * @param serialNo + * @return + */ + public static String response(String data, String url, String mchid, String privateKey, String certificate, String serialNo) { + log.info("====>>> wxpay response, mchid: {}, serialNo: {}, url: {}, privateKey: {}, certificate: {}, data: {}", + mchid, serialNo, url, privateKey, certificate, data); + // ... + HttpPost httpPost = new HttpPost(url); + StringEntity reqEntity = new StringEntity(data, ContentType.create("application/json", "utf-8")); + // ... + httpPost.setEntity(reqEntity); + httpPost.addHeader("Accept", "application/json"); + // ... + CloseableHttpResponse response = null; + // 返回 + String body = null; + try { + // 商户私钥 + PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8"))); + // ... + response = getClient(mchid, serialNo, merchantPrivateKey, certificate).execute(httpPost); + log.info("====>>> wxpay response, result: {}", JSON.toJSONString(response)); + // response = httpClient.execute(httpPost); + // assertTrue(response.getStatusLine().getStatusCode() != 401); + int statusCode = response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + body = EntityUtils.toString(entity); + log.info("====>>> wxpay response, success: {}, body: {}", statusCode, body); + if (statusCode != 200) { + @SuppressWarnings("unchecked") + Map errorMsg = StringHelper.json2map(body); + } + // 执行释放 + EntityUtils.consume(entity); + } catch (IOException e) { + log.error("======>>> wxpay response, client exception: {}", e); + } catch (Exception e) { + log.error("======>>> wxpay response, exception: {}", e); + } finally { + try { + response.close(); + } catch (IOException e) { + log.error("======>>> wxpay response, ioe exception: {}", e); + } + } + return body; + } + + /** + * 创建Client + * + * @param mchid + * @param serialNo + * @param privateKey + * @param certificate + * @return + * @throws UnsupportedEncodingException + */ + public static CloseableHttpClient getClient(String mchid, String serialNo, PrivateKey privateKey, String certificate) throws UnsupportedEncodingException { + + // 使用自动更新的签名验证器,不需要传入证书 +// AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( +// new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), apiV3Key.getBytes("utf-8")); + + // builder + WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create().withMerchant(mchid, serialNo, privateKey); +// .withValidator(new WechatPay2Validator(verifier)); + + List certs = new ArrayList<>(); + certs.add(PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8")))); + builder.withWechatpay(certs); + return builder.build(); + } + + private static final String JSAPI_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"; + + private static final String H5_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"; + + private static final String NATIVE_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/native"; + + private static final String REFUND_URL = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"; + + // 获取支付订单类型 + private static String getUrl(String scene) { + String url = ""; + switch (scene) { + case PaymentConstant.NATIVE: + url = NATIVE_URL; + break; + case PaymentConstant.H5: + url = H5_URL; + break; + case PaymentConstant.JSAPI: + url = JSAPI_URL; + break; + default: + } + return url; + } + + /** + * 字符串 + * + * @return + */ + public static String CreateNoncestr() { + String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + String res = ""; + for (int i = 0; i < 16; i++) { + Random rd = new Random(); + res += chars.charAt(rd.nextInt(chars.length() - 1)); + } + return res; + } + + /** + * 得到时间戳 + * + * @return + */ + public static String getTimestamp() { + long epochSecond = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")); + return String.valueOf(epochSecond); + } + + /** + * 加密算法提供方 - BouncyCastle + */ + private static final String BC_PROVIDER = "BC"; + + /** + * @param privateKey + * @param orderedComponents + * @return + */ + public static String doRequestSign(String privateKey, String... orderedComponents) { + try { + // 商户私钥 + PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8"))); + Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER); + signer.initSign(merchantPrivateKey); + final String signatureStr = createSign(true, orderedComponents); + signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + return Base64Utils.encodeToString(signer.sign()); + } catch (InvalidKeyException e) { + log.error("InvalidKeyException: {}", e); + } catch (SignatureException e) { + log.error("SignatureException: {}", e); + } catch (NoSuchProviderException e) { + log.error("NoSuchProviderException: {}", e); + } catch (NoSuchAlgorithmException e) { + log.error("NoSuchAlgorithmException: {}", e); + } catch (UnsupportedEncodingException e) { + log.error("UnsupportedEncodingException: {}", e); + } + return null; + } + + /** + * 请求时设置签名 组件 + * + * @param components the components + * @return string string + */ + private static String createSign(boolean newLine, String... components) { + String suffix = newLine ? "\n" : ""; + return Arrays.stream(components).collect(Collectors.joining("\n", "", suffix)); + } + + /** + * 使用微信平台证书,对微信回调数据验签,做应答签名比较 + * + * @param certificate + * @param wechatpaySignature + * @param wechatpayTimestamp + * @param wechatpayNonce + * @param body + * @return + */ + public static boolean responseSignVerify(String certificate, String wechatpaySignature, String wechatpayTimestamp, String wechatpayNonce, String body) { + try { + final String signatureStr = createSign(true, wechatpayTimestamp, wechatpayNonce, body); + Signature signer = Signature.getInstance("SHA256withRSA"); + signer.initVerify(PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8")))); + signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + // ... + return signer.verify(Base64Utils.decodeFromString(wechatpaySignature)); + } catch (UnsupportedEncodingException e) { + log.error("UnsupportedEncodingException: {}", e); + } catch (SignatureException e) { + log.error("SignatureException: {}", e); + } catch (NoSuchAlgorithmException e) { + log.error("NoSuchAlgorithmException: {}", e); + } catch (InvalidKeyException e) { + log.error("InvalidKeyException: {}", e); + } + return false; + } + + /** + * 微信V3密钥解密响应体 + * + * @param apiv3Key + * @param bodyVo + * @return + */ + public static String decryptResponseBody(String apiv3Key, CallbackBodyVo bodyVo) { + try { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + + SecretKeySpec key = new SecretKeySpec(apiv3Key.getBytes(StandardCharsets.UTF_8), "AES"); + GCMParameterSpec spec = new GCMParameterSpec(128, bodyVo.getResource().getNonce().getBytes(StandardCharsets.UTF_8)); + + cipher.init(Cipher.DECRYPT_MODE, key, spec); + cipher.updateAAD(bodyVo.getResource().getAssociated_data().getBytes(StandardCharsets.UTF_8)); + + byte[] bytes = cipher.doFinal(Base64Utils.decodeFromString(bodyVo.getResource().getCiphertext())); + return new String(bytes, StandardCharsets.UTF_8); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + log.error("NoSuchAlgorithmException: {}", e); + } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { + log.error("InvalidKeyException: {}", e); + } catch (IllegalBlockSizeException e) { + log.error("IllegalBlockSizeException: {}", e); + } catch (BadPaddingException e) { + log.error("BadPaddingException: {}", e); + } + return null; + } +} \ No newline at end of file diff --git a/payment-base-app/src/main/resources/application.yml b/payment-base-app/src/main/resources/application.yml index 6ef629c..93e1510 100644 --- a/payment-base-app/src/main/resources/application.yml +++ b/payment-base-app/src/main/resources/application.yml @@ -31,6 +31,25 @@ spring: port: 5672 username: rbs-payment password: pay123123 + # redis 配置 + redis: + # 地址 + host: 127.0.0.1 + # 端口,默认为6379 + port: 6379 + # 密码 + password: 123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms #mybatis:配置 mybatis: type-aliases-package: com.base.springcloud.dao #实体类包路径 diff --git a/payment-base-app/src/main/resources/com/base/payment/mapper/MerchantConfigMapper.xml b/payment-base-app/src/main/resources/com/base/payment/mapper/MerchantConfigMapper.xml index 8e91f10..003be95 100644 --- a/payment-base-app/src/main/resources/com/base/payment/mapper/MerchantConfigMapper.xml +++ b/payment-base-app/src/main/resources/com/base/payment/mapper/MerchantConfigMapper.xml @@ -58,6 +58,9 @@ cert_path, + + serial_no + merchant_id, @@ -102,6 +105,9 @@ #{certPath,jdbcType=VARCHAR}, + + #{serialNo,jdbcType=VARCHAR}, + #{merchantId,jdbcType=VARCHAR}, diff --git a/payment-base-app/src/main/resources/com/base/payment/mapper/OrderMapper.xml b/payment-base-app/src/main/resources/com/base/payment/mapper/OrderMapper.xml index 4794ad0..e9bb2cc 100644 --- a/payment-base-app/src/main/resources/com/base/payment/mapper/OrderMapper.xml +++ b/payment-base-app/src/main/resources/com/base/payment/mapper/OrderMapper.xml @@ -4,6 +4,8 @@ + + @@ -14,7 +16,7 @@ - id, order_no, create_time, expire_time, request_no, order_amount, good_name, good_id, + id, order_no,order_state,mch_id,create_time, expire_time, request_no, order_amount, good_name, good_id, order_type, reserved diff --git a/payment-base-app/target/classes/application.yml b/payment-base-app/target/classes/application.yml index f8cfdd3..93e1510 100644 --- a/payment-base-app/target/classes/application.yml +++ b/payment-base-app/target/classes/application.yml @@ -25,7 +25,39 @@ spring: url: jdbc:mysql://106.14.81.251:3306/rbs_erp_test?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false username: root password: hnrr%%360 + #rabbitmq 配置 + rabbitmq: + host: localhost + port: 5672 + username: rbs-payment + password: pay123123 + # redis 配置 + redis: + # 地址 + host: 127.0.0.1 + # 端口,默认为6379 + port: 6379 + # 密码 + password: 123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms #mybatis:配置 mybatis: type-aliases-package: com.base.springcloud.dao #实体类包路径 - mapper-locations: classpath*:com/base/payment/mapper/*.xml #mapper.xml路径 \ No newline at end of file + mapper-locations: classpath*:com/base/payment/mapper/*.xml #mapper.xml路径 + +ftp: + ftp_ip: 192.168.71.132 + ftp_prot : 21 + ftp_username : wangying + ftp_password : 123456 + ftp_basepath : /home/wangying \ No newline at end of file diff --git a/pom.xml b/pom.xml index f76cb41..4133b22 100644 --- a/pom.xml +++ b/pom.xml @@ -87,12 +87,6 @@ 1.2.3 - - mysql - mysql-connector-java - 5.1.38 - - org.mybatis.generator