记得上下班打卡 | git大法好,push需谨慎

Commit 22c2b6b9 authored by 胡佳晨's avatar 胡佳晨

Merge remote-tracking branch 'origin/dev' into dev

parents 229cf56f 435c45cd
liquidnet:
system:
updating:
switch: false
info:
port: 9007
context: /dragon
name: liquidnet-service-notify
logfile:
path: /data/logs
name: service-notify
config: classpath:logback-spring.xml
file-max-size: 200MB
pattern-file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [ %-5level] %thread [%logger{96}:%line] - %msg%n'
pattern-console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [ %-5level] %thread [%logger{96}:%line] - %msg%n'
pattern-rolling-file-name: ${liquidnet.logfile.path}/${liquidnet.logfile.name}-%d{yyyy-MM-dd}.%i.log
level: debug
rabbitmq:
connection-timeout: 5000
mysql:
database-name: dev_ln_scene
mongodb:
sslEnabled: false
database: dev_ln_scene
dragon:
url: ${liquidnet.service.dragon.notifyUrl}
alipay:
gataway-url: https://openapi.alipay.com/gateway.do
appId: 2019082866535131
merchantPubKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmePaETscydypY3rV4mXa8MtcQIL5zjP1KxdusNkHpePeU61hAZxKn0Z8pDB1wNaTK72wgEWaORXeRp4YTbf4usHlW562Pe5wdiSutb3iT6EMJ5eBD4HLI9wWDgYBtwfHwS5JJFhf0eptP4R1XluLiMhmMynLwJvHepgkVrS3mN+jmoPRmKFhZHGIYDoWypBMbUKiFHWiToHK1n0NYHHIi4WgK2wt4Wj7nexQGD69W7ofRCirYmz35c/cNFUA1lqzOEKu2z7PpjA6jQV2GJolnJ4xXPJ8Dpgp4g/dgsGqRydlmFqZD71i/pDDpF0RfRKHL+WhWVhI1hqe6jLtvJE+zQIDAQAB
merchantPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCArhnBTpcAww8wSYBTwGp6oBvenzCCYFrugERgxJDZ7YnBZ3ZdiAaHjJ9PI0WymkpDr27FSg9czVbiH7G91zPq+8s9onrZi/l6cBZ2VjrwQ9BQPN2a8zHy8D6BfoKEV+PIicGz6hNPA7lgf04NgsXeWjeXnYD/IBTLZmnCxB2sPYo/0EN32mlSG9snO63HlPkoqn8ycw71a1cBrlQ+Y22fFnJAk/vrGoou8E0UHfL5zVE/up+ToOYW/eOKMFL/DSceCy32t9Za0RmpV3i2E9s8gBDewzT10Yf4+4mPUiTR6AhcLjqafAy2IaKPK57WZ6cGF9cGs9yq8bSTRpeNC4alAgMBAAECggEAH0Ms+qvPP94j6IVS6gYLWHNhkfp23JXwQZVkB2Z6EpgFKbmrJhoQDAp8Acv9+OBHPp52ePP/O3qfqxwsIIUSFfrKa9T3p7a8C6UDsAhPFWRETdobtLN05SK87NUBfImly2i8aKtruXycIveKzPmCfPzKGMmpN1Jh+vCMrUbcNqX8OUcxmhGvJwnQuBW4QEiepzl89Nl91iSwFmxaZoqLaB9lYUKke/z7FDHTpTWpZvtvxlZ0gvMVNLVp9NBNazolQ8eEjBG2PsQGD2cLUbM33mLTz+/VQjzZR3KXu5kQR9MloURILDsdxE1AyA4AkIXd4eMszEjA4Dv6CQK/jjrsgQKBgQDIiCt1OGmV2sqDBSn4nZNH7BzY3Hdnf+qsYUi+TXKhnQaT8XPKWZpKE/AcqsIKnANmO4sX0NL7ACBe7Rl1RcU9Mq5XuHhnkveFBVRRIHindzUfEN0WgdLy23qmJ2N+1i4FigelY0E5T2lojVb7wycAgAc6vflwE+eYf8W3968q0QKBgQCkRgsVCWWNMSLZeB0V9LV3Om2/UPWY/ovadTxAQtxg0Z75V6Wdu8u0hrYaPSeUK2ryaoE6HKgp7U8NiJGzgm2wpj7D2ysrPmhX5+CjiWkDMCuvWytVT7hLqhhLp7frZT39u8VhyfC8lE0xA67gAPsGSl1sBoZPwvvsmNAQ/h6rlQKBgQCtCtw9be2m88M3JnieYhOax8Po2u5qsLZoBBcKqLhXf7ISbhPWNFXwwJ29jxicoR5J1O3lIj09fVFxuLX0Pb3DXn2VksjLz8Wp0vx8eUHEeRis8xdleaf4C68du/WemOHjw8VvUWQSOVWjc/vwiumYA+K5LQAXWAXM0c1jP+e3UQKBgEWY/1z8TDATn0Yvo3MH6FIJSTIDJOqa/bmibdJ0AVZruUS+o4Y+aEGlyUU4n6og8wCdqv5p4b1Rs2pyb/hzy/FJndHw60s495A2x2/B6eHV6Mw0fhl42wYDnKOA/WUX0bnMcgXKPtpGoqWff9mb0L6LhyUbZpAodf95hr2MTIY5AoGBAIyPtYP6jRyR980h/Ud1MS0fBxymjQrR+kg3GWjnw0ZJJ8yFEXxDqLV8uLyXQKc89HGbI0cClWgZBTjfIPJ5U4Gl19Xlwx1SFrdgg5mGUqnMARTg7w1TG5QLSqNhZo2jgBM5FCJRbDUCO/MzLcFhTeGNva9yP7E7gW5/Dott9D7d
signtType: 2019082866535131
charset: 2019082866535131
wepay:
gataway-url: https://openapi.alipay.com/gateway.do
merchantId: 1551961491
appId: wx3498304dda39c5a1
partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK
liquidnet:
system:
updating:
switch: false
info:
port: 9007
context: /dragon
name: liquidnet-service-notify
logfile:
path: /data/logs
name: service-notify
config: classpath:logback-spring.xml
file-max-size: 200MB
pattern-file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [ %-5level] %thread [%logger{96}:%line] - %msg%n'
pattern-console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [ %-5level] %thread [%logger{96}:%line] - %msg%n'
pattern-rolling-file-name: ${liquidnet.logfile.path}/${liquidnet.logfile.name}-%d{yyyy-MM-dd}.%i.log
level: debug
rabbitmq:
connection-timeout: 5000
mysql:
database-name: test_ln_scene
mongodb:
sslEnabled: false
database: test_ln_scene
dragon:
url: ${liquidnet.service.dragon.notifyUrl}
alipay:
gataway-url: https://openapi.alipay.com/gateway.do
appId: 2019082866535131
merchantPubKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmePaETscydypY3rV4mXa8MtcQIL5zjP1KxdusNkHpePeU61hAZxKn0Z8pDB1wNaTK72wgEWaORXeRp4YTbf4usHlW562Pe5wdiSutb3iT6EMJ5eBD4HLI9wWDgYBtwfHwS5JJFhf0eptP4R1XluLiMhmMynLwJvHepgkVrS3mN+jmoPRmKFhZHGIYDoWypBMbUKiFHWiToHK1n0NYHHIi4WgK2wt4Wj7nexQGD69W7ofRCirYmz35c/cNFUA1lqzOEKu2z7PpjA6jQV2GJolnJ4xXPJ8Dpgp4g/dgsGqRydlmFqZD71i/pDDpF0RfRKHL+WhWVhI1hqe6jLtvJE+zQIDAQAB
merchantPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCArhnBTpcAww8wSYBTwGp6oBvenzCCYFrugERgxJDZ7YnBZ3ZdiAaHjJ9PI0WymkpDr27FSg9czVbiH7G91zPq+8s9onrZi/l6cBZ2VjrwQ9BQPN2a8zHy8D6BfoKEV+PIicGz6hNPA7lgf04NgsXeWjeXnYD/IBTLZmnCxB2sPYo/0EN32mlSG9snO63HlPkoqn8ycw71a1cBrlQ+Y22fFnJAk/vrGoou8E0UHfL5zVE/up+ToOYW/eOKMFL/DSceCy32t9Za0RmpV3i2E9s8gBDewzT10Yf4+4mPUiTR6AhcLjqafAy2IaKPK57WZ6cGF9cGs9yq8bSTRpeNC4alAgMBAAECggEAH0Ms+qvPP94j6IVS6gYLWHNhkfp23JXwQZVkB2Z6EpgFKbmrJhoQDAp8Acv9+OBHPp52ePP/O3qfqxwsIIUSFfrKa9T3p7a8C6UDsAhPFWRETdobtLN05SK87NUBfImly2i8aKtruXycIveKzPmCfPzKGMmpN1Jh+vCMrUbcNqX8OUcxmhGvJwnQuBW4QEiepzl89Nl91iSwFmxaZoqLaB9lYUKke/z7FDHTpTWpZvtvxlZ0gvMVNLVp9NBNazolQ8eEjBG2PsQGD2cLUbM33mLTz+/VQjzZR3KXu5kQR9MloURILDsdxE1AyA4AkIXd4eMszEjA4Dv6CQK/jjrsgQKBgQDIiCt1OGmV2sqDBSn4nZNH7BzY3Hdnf+qsYUi+TXKhnQaT8XPKWZpKE/AcqsIKnANmO4sX0NL7ACBe7Rl1RcU9Mq5XuHhnkveFBVRRIHindzUfEN0WgdLy23qmJ2N+1i4FigelY0E5T2lojVb7wycAgAc6vflwE+eYf8W3968q0QKBgQCkRgsVCWWNMSLZeB0V9LV3Om2/UPWY/ovadTxAQtxg0Z75V6Wdu8u0hrYaPSeUK2ryaoE6HKgp7U8NiJGzgm2wpj7D2ysrPmhX5+CjiWkDMCuvWytVT7hLqhhLp7frZT39u8VhyfC8lE0xA67gAPsGSl1sBoZPwvvsmNAQ/h6rlQKBgQCtCtw9be2m88M3JnieYhOax8Po2u5qsLZoBBcKqLhXf7ISbhPWNFXwwJ29jxicoR5J1O3lIj09fVFxuLX0Pb3DXn2VksjLz8Wp0vx8eUHEeRis8xdleaf4C68du/WemOHjw8VvUWQSOVWjc/vwiumYA+K5LQAXWAXM0c1jP+e3UQKBgEWY/1z8TDATn0Yvo3MH6FIJSTIDJOqa/bmibdJ0AVZruUS+o4Y+aEGlyUU4n6og8wCdqv5p4b1Rs2pyb/hzy/FJndHw60s495A2x2/B6eHV6Mw0fhl42wYDnKOA/WUX0bnMcgXKPtpGoqWff9mb0L6LhyUbZpAodf95hr2MTIY5AoGBAIyPtYP6jRyR980h/Ud1MS0fBxymjQrR+kg3GWjnw0ZJJ8yFEXxDqLV8uLyXQKc89HGbI0cClWgZBTjfIPJ5U4Gl19Xlwx1SFrdgg5mGUqnMARTg7w1TG5QLSqNhZo2jgBM5FCJRbDUCO/MzLcFhTeGNva9yP7E7gW5/Dott9D7d
signtType: 2019082866535131
charset: 2019082866535131
wepay:
gataway-url: https://openapi.alipay.com/gateway.do
merchantId: 1551961491
appId: wx3498304dda39c5a1
partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK
\ No newline at end of file
server:
port: ${liquidnet.info.port}
tomcat:
uri-encoding: UTF-8
maxThreads: 2000 #默认200
minSpareThreads: 2000 #默认10
maxConnections: 20000 #默认10000
acceptCount: 5000 #默认100
processorCache: -1 #默认200
servlet:
context-path: ${liquidnet.info.context}
# -----------------------------------------------------------
knife4j:
enable: true
production: ${liquidnet.knife4j.disable}
basic:
enable: false
username: ${liquidnet.security.username}
password: ${liquidnet.security.password}
# -----------------------------------------------------------
logging:
# config: ${liquidnet.logfile.config}
file:
name: ${liquidnet.logfile.path}/${liquidnet.logfile.name}.log
max-size: ${liquidnet.logfile.file-max-size}
pattern:
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %X{lnsTranceId} [%logger{96}:%line] - %msg%n'
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %X{lnsTranceId} [%logger{96}:%line] - %msg%n'
rolling-file-name: ${liquidnet.logfile.path}/${liquidnet.logfile.name}-%d{yyyy-MM-dd}.%i.log
level:
root: info
#以下是为指定包设置日志级别
com:
liquidnet: ${liquidnet.logfile.level}
# -----------------------------------------------------------
eureka:
# client:
# register-with-eureka: true
# fetch-registry: true
# serviceUrl:
# defaultZone: http://${liquidnet.security.username}:${liquidnet.security.password}@${liquidnet.eureka.host}/eureka-server/eureka
instance:
hostname: ${spring.cloud.client.ip-address}
lease-expiration-duration-in-seconds: 15 #服务过期时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
lease-renewal-interval-in-seconds: 5 #服务刷新时间配置,每隔这个时间会主动心跳一次
prefer-ip-address: true
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
# -----------------------------------------------------------
#actuator/info
info:
app:
name: ${liquidnet.info.name}
company:
name: lightnet.io
build:
groupId: '@project.groupId@'
artifactId: '@project.artifactId@'
version: '@project.version@'
# -----------------------------------------------------------
mybatis-plus:
mapper-locations: classpath:com.liquidnet.service.kylin.mapper/*Mapper.xml
# -----------------------------------------------------------
spring:
application:
name: ${liquidnet.info.name}
servlet:
multipart:
max-file-size: 5MB
max-request-size: 10MB
profiles:
include: common-service #这里加载management相关公共配置
autoconfigure:
exclude: org.springframework.cloud.bus.BusAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
rabbitmq:
addresses: ${liquidnet.rabbitmq.host}
port: ${liquidnet.rabbitmq.port}
username: ${liquidnet.rabbitmq.username}
password: ${liquidnet.rabbitmq.password}
virtual-host: ${liquidnet.rabbitmq.virtual-host}
connection-timeout: ${liquidnet.rabbitmq.connection-timeout}
redis:
database: 0
port: ${liquidnet.redis.dragon.port}
host: ${liquidnet.redis.dragon.host}
password: ${liquidnet.redis.dragon.password}
lettuce:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
redisson:
singleServerConfig:
address: redis://${liquidnet.redis.host}:${liquidnet.redis.port}
password: ${liquidnet.redis.password}
clientName: null
database: 7 #选择使用哪个数据库0~15
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
subscriptionsPerConnection: 5
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 32
connectionPoolSize: 64
dnsMonitoringInterval: 5000
threads: 16
nettyThreads: 32
codec:
class: "org.redisson.codec.JsonJacksonCodec"
transportMode: "NIO"
data:
mongodb:
uri: mongodb://${liquidnet.mongodb.user}:${liquidnet.mongodb.pwd}@${liquidnet.mongodb.host}/?authSource=admin&maxPoolSize=2000&waitQueueMultiple=100
sslEnabled: ${liquidnet.mongodb.sslEnabled}
database: ${liquidnet.mongodb.database}
# -----------------------------------------------------------
# -----------------------------------------------------------
global-auth:
exclude-url-pattern:
- ${liquidnet.info.context}/doc.html
- ${liquidnet.info.context}/webjars/**
- ${liquidnet.info.context}/swagger-resources/**
- ${liquidnet.info.context}/v2/api-docs*
- ${liquidnet.info.context}/station/login
- ${liquidnet.info.context}/station/login/sms
# -
- ${liquidnet.info.context}/partner/buyNotice/**
- ${liquidnet.info.context}/partner/checkUser/**
- ${liquidnet.info.context}/partner/checkUser/performance/**
- ${liquidnet.info.context}/partner/ticket/**
- ${liquidnet.info.context}/partner/times/**
- ${liquidnet.info.context}/partner/performance/**
# banner
- ${liquidnet.info.context}/banners/**
- ${liquidnet.info.context}/order/checkOrderTime
- ${liquidnet.info.context}/order/syncOrder
# 退款回掉
- ${liquidnet.info.context}/refund/callback
# 演出
- ${liquidnet.info.context}/performance/localList
- ${liquidnet.info.context}/performance/noticeList
- ${liquidnet.info.context}/performance/roadList/**
- ${liquidnet.info.context}/performance/recommendList
- ${liquidnet.info.context}/performance/exclusiveList
- ${liquidnet.info.context}/performance/search
- ${liquidnet.info.context}/performance/list
- ${liquidnet.info.context}/performance/calendar
- ${liquidnet.info.context}/performance/calendarPerformances
- ${liquidnet.info.context}/performance/*
# -----------------------------------------------------------
# -----------------------------------------------------------
# -----------------------------------------------------------
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>liquidnet-service-notify</artifactId>
<groupId>com.liquidnet</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liquidnet-service-notify-impl</artifactId>
<dependencies>
<!-- common -->
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-common-cache-redis</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- other -->
<dependency>
<groupId>com.liquidnet</groupId>
<artifactId>liquidnet-service-dragon-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.2</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.15.6.ALL</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.liquidnet.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.util.Arrays;
@Slf4j
@SpringBootApplication(scanBasePackages = {"com.liquidnet"})
public class ServiceNotifyApplication implements CommandLineRunner {
@Autowired
private Environment environment;
public static void main(String[] args) {
SpringApplication.run(ServiceNotifyApplication.class, args);
}
@Override
public void run(String... strings) {
try {
log.info("\n----------------------------------------------------------\n\t" +
"Application '{}' is running! Access URLs:\n\t" +
"Local: \t\thttp://127.0.0.1:{}\n\t" +
"External: \thttp://{}:{}{}/doc.html\n\t" +
"Profile(s): \t{}\n----------------------------------------------------------",
environment.getProperty("spring.application.name"),
environment.getProperty("server.port"),
InetAddress.getLocalHost().getHostAddress(),
environment.getProperty("server.port"),
environment.getProperty("server.servlet.context-path"),
Arrays.toString(environment.getActiveProfiles()));
} catch (Exception e) {
e.printStackTrace();
}
}
// @Bean
// MongoTransactionManager transactionManager(MongoDbFactory factory){
// return new MongoTransactionManager(factory);
// }
}
package com.liquidnet.service.dragon.biz;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.dragon.bo.PayNotifyReqBo;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.PayNotifyDto;
import com.liquidnet.service.dragon.utils.DataUtils;
import com.liquidnet.service.dragon.utils.MqHandleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: DragonServiceCommonBiz
* @Package com.liquidnet.service.dragon.biz
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/19 18:06
*/
@Slf4j
@Component
public class DragonServiceCommonBiz {
@Autowired
private MqHandleUtil mqHandleUtil;
@Autowired
private DataUtils dataUtils;
public DragonOrdersDto buildPayOrders(DragonPayBaseReqDto dragonPayBaseReqDto, DragonPayBaseRespDto respDto){
//构造订单
DragonOrdersDto orders = DragonOrdersDto.getNew();
// orders.setMid();
orders.setOrderId(IDGenerator.nextTimeId());
orders.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode()));
orders.setCode(dragonPayBaseReqDto.getCode());
orders.setType(dragonPayBaseReqDto.getType());
orders.setPrice(dragonPayBaseReqDto.getPrice());
orders.setName(dragonPayBaseReqDto.getName());
orders.setDetail(dragonPayBaseReqDto.getDetail());
orders.setOrderCode(dragonPayBaseReqDto.getOrderCode());
orders.setClientIp(dragonPayBaseReqDto.getClientIp());
orders.setNotifyUrl(dragonPayBaseReqDto.getNotifyUrl());
orders.setNotifyStatus(Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_INIT.getCode()));
orders.setPaymentType((dragonPayBaseReqDto.getDeviceFrom()+dragonPayBaseReqDto.getPayType()).toUpperCase());
// orders.setPaymentId();
orders.setPaymentAt(LocalDateTime.now());
// orders.setFinishedAt();
orders.setCreatedAt(LocalDateTime.now());
// orders.setUpdatedAt();
long startTime = System.currentTimeMillis();
//放到redis缓存中
dataUtils.createPayOrder(orders.getCode(),orders);
log.info("redis-createPayOrder->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
// 持久化到数据库
startTime = System.currentTimeMillis();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.insert"),
new Object[]{orders.getOrderId(),orders.getStatus(), orders.getCode(), orders.getType()
, orders.getPrice(), orders.getName(), orders.getDetail()
, orders.getOrderCode(), orders.getClientIp()
, orders.getNotifyUrl(), orders.getNotifyStatus(),orders.getPaymentType(),
orders.getPaymentId(), orders.getPaymentAt()
, orders.getFinishedAt(), orders.getCreatedAt()
, orders.getUpdatedAt(),orders.getDeletedAt()}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
log.info("redis-queue-sendMySqlRedis->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
return orders;
}
/**
* 更新支付状态
* @param code
* @param paymentId
* @return
*/
public boolean updateOrderStatus(String code,Integer status,String paymentId){
try {
LocalDateTime finishedAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
//t.status = ? ,t.payment_id = ?,t.finished_at = ?,t.updated_at =? where t.code = ?
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.updateOrderStatus"),
new Object[]{status,paymentId,finishedAt, updateAt,code}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
if(insertResult) return true;
} catch (Exception e) {
log.error("dragon:updateDragonOrderStatus:error msg:{}",e);
e.printStackTrace();
}
return false;
}
/**
* 更新支付通知状态
* @param code
* @return
*/
public boolean updateNotifyStatus(String code,Integer status){
try {
LocalDateTime updateAt = LocalDateTime.now();
//update dragon_orders t set t.notify_status = ? ,t.updated_at =? where t.code = ?
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_orders.updateNotifyStatus"),
new Object[]{status,updateAt,code}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_KEY.getCode()
);
if(insertResult) return true;
} catch (Exception e) {
log.error("dragon:updateNotifyStatus:error msg:{}",e);
e.printStackTrace();
}
return false;
}
/**
* 三方异步通知入库
* @param paymentType
* @param content
*/
public void createDragonOrderLogs(String code,String paymentType,String content){
try {
String orderId = IDGenerator.nextTimeId();
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = null;
LocalDateTime deleteAt = null;
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_order_logs.insert"),
new Object[]{code,paymentType,content, createAt, updateAt,deleteAt}
,DragonConstant.MysqlRedisQueueEnum.DRAGON_PAY_NOTIFY_KEY.getCode()
);
} catch (Exception e) {
log.error("dragon:createOrderLog:error msg:{}",e);
e.printStackTrace();
}
}
/**
* 商户异步通知入库
* @param payNotifyReqBo
* @param notifyParam
*/
public void createDragonPayNotify(PayNotifyReqBo payNotifyReqBo,String notifyParam){
PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
try {
String code = payNotifyDto.getCode();
String orderCode = payNotifyDto.getOrderCode();
String notifyUrl = payNotifyReqBo.getNotifyUrl();
String notifyData = notifyParam;
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_pay_notify.insert"),
new Object[]{code,orderCode,notifyUrl,notifyData, createAt, updateAt}
,DragonConstant.MysqlRedisQueueEnum.PAY_MCH_NOTIFY_KEY.getCode()
);
log.info("dragon:createDragonPayNotify:success code:{}",code);
} catch (Exception e) {
log.error("dragon:createDragonPayNotify:error msg:{}",e);
e.printStackTrace();
}
}
/**
* 商户异步通知失败入库
* @param payNotifyReqBo
* @param notifyParam
*/
public void createDragonPayNotifyFail(PayNotifyReqBo payNotifyReqBo, String notifyParam){
PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
try {
String code = payNotifyDto.getCode();
String orderCode = payNotifyDto.getOrderCode();
String notifyUrl = payNotifyReqBo.getNotifyUrl();
String notifyData = notifyParam;
String failDesc = "通知失败";
LocalDateTime createAt = LocalDateTime.now();
LocalDateTime updateAt = LocalDateTime.now();
boolean insertResult = mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_pay_notify_fail.insert"),
new Object[]{code,orderCode,notifyUrl,notifyData,failDesc,createAt, updateAt}
, DragonConstant.MysqlRedisQueueEnum.PAY_MCH_NOTIFY_ERROR_KEY.getCode()
);
log.info("dragon:createDragonPayNotifyFail:success code:{}",code);
} catch (Exception e) {
log.error("dragon:createDragonPayNotifyFail:error msg:{}",e);
e.printStackTrace();
}
}
}
package com.liquidnet.service.dragon.bo;
import com.alibaba.fastjson.JSON;
import com.liquidnet.service.dragon.dto.PayNotifyDto;
import lombok.Data;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayNotifyReqDto
* @Package com.liquidnet.service.consumer.dragon.service.bo
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/14 20:22
*/
@Data
public class PayNotifyReqBo {
private String notifyUrl;
private String content;
private PayNotifyDto payNotifyDto;
@Override
public String toString(){
return JSON.toJSONString(this);
}
}
package com.liquidnet.service.dragon.channel.alipay.biz;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.sign.MD5;
import com.liquidnet.service.dragon.utils.ObjectUtil;
import com.liquidnet.service.dragon.utils.PayAlipayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayBiz
* @Package com.liquidnet.service.dragon.channel.alipay.biz
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 16:21
*/
@Slf4j
@Component
public class AlipayBiz{
/**
* tradeWapPay
* @param alipayTradePayReq
* @return
*/
public static Map<String, Object> tradeWapPay(AlipayTradePayReq alipayTradePayReq) {
log.info("AlipayBiz.tradeWapPay-->> req : {}",alipayTradePayReq.toString());
String timeExpress = "5m";// 支付超时,线下扫码交易定义为5分钟
AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("product_code", alipayTradePayReq.getProductCode());
paramMap.put("total_amount", alipayTradePayReq.getTotalAmount().toString());
paramMap.put("subject", alipayTradePayReq.getSubject());
paramMap.put("body", alipayTradePayReq.getBody());
paramMap.put("out_trade_no", alipayTradePayReq.getOutTradeNo());
paramMap.put("timeout_express", timeExpress);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setNotifyUrl(alipayTradePayReq.getNotifyUrl());
// request.setTimestamp(DateUtil.now());
log.info("bizContent :{}", JsonUtils.toJson(paramMap));
request.setBizContent(JsonUtils.toJson(paramMap));
try {
long startTime = System.currentTimeMillis();
AlipayTradeWapPayResponse response = alipayClient.sdkExecute(request);
// AlipayTradeWapPayResponse response = new AlipayTradeWapPayResponse();
log.info("alipay-alipayClient.sdkExecut->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
// Map<String,Object> responseJSON = JsonUtils.OM().convertValue(response,Map.class);
startTime = System.currentTimeMillis();
Map<String,Object> responseJSON = ObjectUtil.cloneHashMapStringAndObj();
log.info("AlipayUtil-->tradeWapPay-->cloneHashMapStringAndObj 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
responseJSON.put("code",response.getCode());
responseJSON.put("msg",response.getMsg());
responseJSON.put("subCode",response.getSubCode());
responseJSON.put("subMsg",response.getSubMsg());
responseJSON.put("body",response.getBody());
responseJSON.put("merchantOrderNo",response.getMerchantOrderNo());
responseJSON.put("outTradeNo",response.getOutTradeNo());
responseJSON.put("sellerId",response.getSellerId());
responseJSON.put("totalAmount",response.getTotalAmount());
responseJSON.put("tradeNo",response.getTradeNo());
startTime = System.currentTimeMillis();
// log.info("AlipayUtil-->tradeWapPay-->支付宝返回结果:{}", JsonUtils.toJson(response));
log.info("AlipayUtil-->tradeWapPay-->支付宝返回结果 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
return responseJSON;
} catch (Exception e) {
log.error("支付宝支付异常:{}", e);
JSONObject resultJSON = ObjectUtil.cloneJsonObjectObj();
resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
resultJSON.put("errorCode", "9999");
return resultJSON;
}
}
/**
* 支付宝支付
* @param alipayTradePayReq
* @return
*/
public static Map<String, Object> tradeAppPay(AlipayTradePayReq alipayTradePayReq) {
log.info("AlipayUtil.tradeAppPay-->> req : {}",alipayTradePayReq.toString());
String timeExpress = "5m";// 支付超时,线下扫码交易定义为5分钟
AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("product_code", alipayTradePayReq.getProductCode());
paramMap.put("total_amount", alipayTradePayReq.getTotalAmount().toString());
paramMap.put("subject", alipayTradePayReq.getSubject());
paramMap.put("body", alipayTradePayReq.getBody());
paramMap.put("out_trade_no", alipayTradePayReq.getOutTradeNo());
paramMap.put("timeout_express", timeExpress);
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setNotifyUrl(alipayTradePayReq.getNotifyUrl());
// request.setTimestamp(DateUtil.now());
log.info("bizContent :{}",JSONObject.toJSONString(paramMap));
request.setBizContent(JSONObject.toJSONString(paramMap));
try {
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
// JSONObject responseJSON = JSONObject.parseObject(JSONObject.toJSONString(response));
Map<String,Object> responseJSON = JsonUtils.fromJson(JsonUtils.toJson(response), new TypeReference<Map<String,Object>>() {
});
log.info("AlipayUtil-->tradeAppPay-->支付宝返回结果:{}", responseJSON);
return responseJSON;
} catch (AlipayApiException e) {
log.error("支付宝支付异常:{}", e);
JSONObject resultJSON = new JSONObject();
resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
resultJSON.put("errorCode", "9999");
return resultJSON;
}
}
/**
* 订单查询
*
* @return
*/
public static Map<String, Object> tradeQuery(String outTradeNo) {
log.info("AlipayBiz.tradeQuery-->> 支付宝交易查询");
AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();
SortedMap<String, Object> bizContentMap = new TreeMap<>();
bizContentMap.put("out_trade_no", outTradeNo);
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent(JSONObject.toJSONString(bizContentMap));
try {
AlipayTradeQueryResponse response = alipayClient.execute(request);
JSONObject responseJSON = JSONObject.parseObject(JSONObject.toJSONString(response));
log.info("支付宝订单查询返回结果:{}", responseJSON);
return responseJSON;
} catch (AlipayApiException e) {
log.error("支付宝交易查询异常:{}", e);
return null;
}
}
private static String getSign(SortedMap<String, String> paramMap, String key) {
StringBuilder signBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : paramMap.entrySet()) {
if (!"sign".equals(entry.getKey()) && !"sign_type".equals(entry.getKey()) && !StringUtil.isEmpty(entry.getValue())) {
signBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
}
return MD5.sign(signBuilder.substring(0, signBuilder.length() - 1), key, "UTF-8");
}
public static Map<String , String> parseNotifyMsg(Map<String, String[]> requestParams){
Map<String,String> params = new HashMap<String,String>();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
return params;
}
}
package com.liquidnet.service.dragon.channel.alipay.constant;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayConstant
* @Package com.liquidnet.service.dragon.channel.alipay.constant
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 20:52
*/
public class AlipayConstant {
public enum AlipayTradeStateEnum {
TRADE_CLOSED ("TRADE_CLOSED","交易关闭"),
TRADE_FINISHED ("TRADE_FINISHED","支付完成"),
TRADE_SUCCESS ("TRADE_SUCCESS","支付成功"),
WAIT_BUYER_PAY ("WAIT_BUYER_PAY","交易创建"),
FAIL("","支付失败");
private String code;
private String message;
AlipayTradeStateEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
}
package com.liquidnet.service.dragon.channel.alipay.req;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayTradePayReq
* @Package com.liquidnet.service.dragon.channel.alipay.req
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/9 17:50
*/
@Data
public class AlipayTradePayReq implements Serializable, Cloneable{
private static final long serialVersionUID = -5827961038383330701L;
private String productCode;
private BigDecimal totalAmount;
private String subject;
private String body;
private String outTradeNo;
private String timeExpire;
private String notifyUrl;
private String timestamp;
@Override
public String toString(){
return JSON.toJSONString(this);
}
private static final AlipayTradePayReq obj = new AlipayTradePayReq();
public static AlipayTradePayReq getNew() {
try {
return (AlipayTradePayReq) obj.clone();
} catch (CloneNotSupportedException e) {
return new AlipayTradePayReq();
}
}
}
/*
* Copyright 2015-2102 RonCoo(http://www.roncoo.com) Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.liquidnet.service.dragon.channel.alipay.sign;
import org.apache.commons.codec.digest.DigestUtils;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
/**
* 签名加密MD%
*/
public class MD5 {
/**
* 签名字符串
* @param text 需要签名的字符串
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static String sign(String text, String key, String input_charset) {
text = text + key;
return DigestUtils.md5Hex(getContentBytes(text, input_charset));
}
/**
* 签名字符串
* @param text 需要签名的字符串
* @param sign 签名结果
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static boolean verify(String text, String sign, String key, String input_charset) {
text = text + key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
if(mysign.equals(sign)) {
return true;
}
else {
return false;
}
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.alipay.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class AlipayStrategyContext {
private final Map<String, IAlipayStrategy> handlerMap = new HashMap<>();
public IAlipayStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IAlipayStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.alipay.strategy;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class AlipayStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyAlipayHandler.class);
AlipayStrategyContext strategyContext = event.getApplicationContext().getBean(AlipayStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyAlipayHandler typeHandler = bean.getClass().getAnnotation(StrategyAlipayHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IAlipayStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.alipay.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IAlipayStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
}
package com.liquidnet.service.dragon.channel.alipay.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyGetFundDataHandler
* @Package com.liquidnet.service.reconciliation.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/10/27 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyAlipayHandler {
DragonConstant.DeviceFromEnum value();
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.IAlipayStrategy;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AbstractAlipayStrategy
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/12 12:36
*/
@Slf4j
public abstract class AbstractAlipayStrategy implements IAlipayStrategy {
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
protected String productCode = "QUICK_WAP_PAY";
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
//设置productCode
setProductCode();
AlipayTradePayReq alipayTradePayReq = AlipayTradePayReq.getNew();
alipayTradePayReq.setProductCode(this.productCode);
alipayTradePayReq.setTotalAmount(dragonPayBaseReqDto.getPrice());
alipayTradePayReq.setSubject(dragonPayBaseReqDto.getName());
alipayTradePayReq.setBody(dragonPayBaseReqDto.getDetail());
//dragon中支付编号
alipayTradePayReq.setOutTradeNo(dragonPayBaseReqDto.getCode());
//设置订单过期时间
String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmss);
alipayTradePayReq.setTimeExpire(timeExpire);
alipayTradePayReq.setNotifyUrl(this.getNotifyUrl());
alipayTradePayReq.setTimestamp(dragonPayBaseReqDto.getCreateDate());
//调用支付
long startTime = System.currentTimeMillis();
Map<String, Object> result = this.executePay(alipayTradePayReq);
// log.info("dragonPay:alipay:"+dragonPayBaseReqDto.getDeviceFrom()+" response xmlStr: {} ", JSON.toJSONString(result));
log.info("alipay-dragonPay->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
//拼接返回参数
DragonPayBaseRespDto respDto = buildCommonRespDto(dragonPayBaseReqDto);
respDto = this.buildResponseDto(respDto,result);
//支付订单持久化
dragonServiceCommonBiz.buildPayOrders(dragonPayBaseReqDto,null);
return ResponseDto.success(respDto);
}
/**
* 支付请求
* @param alipayTradePayReq
* @return
*/
protected abstract Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq);
/**
* 设置productCode
*/
protected abstract void setProductCode();
/**
* 设置notifyUrl
*/
protected abstract String getNotifyUrl();
/**
* 构造公共返回参数
* @param dragonPayBaseReqDto
* @return
*/
protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto){
DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
respDto.setCode(dragonPayBaseReqDto.getCode());
respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
respDto.setPayData(payData);
return respDto;
}
/**
* 构造返回参数
*/
abstract DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto,Map<String, Object> respResult);
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyAlipayHandler(DragonConstant.DeviceFromEnum.APP)
public class AlipayStrategyAppImpl extends AbstractAlipayStrategy {
@Value("${liquidnet.dragon.alipay.gataway-url}")
private String alipayGatewayUrl;
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private AlipayBiz alipayBiz;
@Override
protected Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq) {
return alipayBiz.tradeAppPay(alipayTradePayReq);
}
protected void setProductCode() {
this.productCode = "QUICK_MSECURITY_PAY";
}
@Override
protected String getNotifyUrl() {
// notifyUrl = "/notify/app/alipay/1";
return notifyUrl + "/notify/alipay/app";
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map<String, Object> respResult) {
payBaseRespDto.getPayData().setOrderStr(respResult.get("body").toString());
return payBaseRespDto;
}
}
package com.liquidnet.service.dragon.channel.alipay.strategy.impl;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.strategy.annotation.StrategyAlipayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Service
@StrategyAlipayHandler(DragonConstant.DeviceFromEnum.WAP)
public class AlipayStrategyWapImpl extends AbstractAlipayStrategy {
@Value("${liquidnet.dragon.alipay.gataway-url}")
private String alipayGatewayUrl;
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private AlipayBiz alipayBiz;
@Override
protected Map<String, Object> executePay(AlipayTradePayReq alipayTradePayReq) {
return alipayBiz.tradeWapPay(alipayTradePayReq);
}
protected void setProductCode() {
this.productCode = "QUICK_WAP_PAY";
}
@Override
protected String getNotifyUrl() {
// notifyUrl = "/notify/wap/alipay/1";
return notifyUrl + "/notify/alipay/wap";
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, Map<String, Object> respResult) {
payBaseRespDto.getPayData().setRedirectUrl(alipayGatewayUrl + "?" + respResult.get("body"));
return payBaseRespDto;
}
}
package com.liquidnet.service.dragon.channel.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import javax.servlet.http.HttpServletRequest;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IPayChannelStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
String dragonNotify(HttpServletRequest request,String payType,String deviceFrom);
DragonPayOrderQueryRespDto checkOrderStatus(String code);
}
package com.liquidnet.service.dragon.channel.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class PayChannelStrategyContext {
private final Map<String, IPayChannelStrategy> handlerMap = new HashMap<>();
public IPayChannelStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IPayChannelStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.strategy;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class PayChannelStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyPayChannelHandler.class);
PayChannelStrategyContext strategyContext = event.getApplicationContext().getBean(PayChannelStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyPayChannelHandler typeHandler = bean.getClass().getAnnotation(StrategyPayChannelHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IPayChannelStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyGetFundDataHandler
* @Package com.liquidnet.service.reconciliation.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/10/27 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyPayChannelHandler {
DragonConstant.PayChannelEnum value();
}
package com.liquidnet.service.dragon.channel.strategy.biz;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.bo.PayNotifyReqBo;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.dto.PayNotifyDto;
import com.liquidnet.service.dragon.utils.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: DragonPayBiz
* @Package com.liquidnet.service.dragon.channel.strategy.biz
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/14 14:12
*/
@Slf4j
@Component
public class DragonPayBiz {
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
public PayNotifyReqBo buildPayNotifyReqBo(DragonOrdersDto dragonOrdersDto){
PayNotifyReqBo payNotifyReqBo = new PayNotifyReqBo();
payNotifyReqBo.setNotifyUrl(dragonOrdersDto.getNotifyUrl());
PayNotifyDto payNotifyDto = new PayNotifyDto();
payNotifyDto.setStatus(dragonOrdersDto.getStatus());
payNotifyDto.setType(dragonOrdersDto.getType());
payNotifyDto.setCode(dragonOrdersDto.getCode());
payNotifyDto.setPaymentId(dragonOrdersDto.getPaymentId());
payNotifyDto.setOrderCode(dragonOrdersDto.getOrderCode());
payNotifyDto.setPrice(dragonOrdersDto.getPrice());
payNotifyDto.setPaymentType(dragonOrdersDto.getPaymentType());
if(StringUtil.isNotNull(dragonOrdersDto.getPaymentAt())){
payNotifyDto.setPaymentAt(DateUtil.Formatter.yyyyMMddHHmmss.format(dragonOrdersDto.getPaymentAt()));
}else{
payNotifyDto.setPaymentAt("");
}
payNotifyReqBo.setPayNotifyDto(payNotifyDto);
return payNotifyReqBo;
}
public DragonPayOrderQueryRespDto buildPayOrderQueryRespDto(DragonOrdersDto ordersDto){
DragonPayOrderQueryRespDto queryRespDto = new DragonPayOrderQueryRespDto();
queryRespDto.setStatus(ordersDto.getStatus());
queryRespDto.setType(ordersDto.getType());
queryRespDto.setCode(ordersDto.getCode());
queryRespDto.setPaymentId(ordersDto.getPaymentId());
queryRespDto.setOrderCode(ordersDto.getOrderCode());
queryRespDto.setPrice(ordersDto.getPrice());
queryRespDto.setPaymentType(ordersDto.getPaymentType());
if(StringUtil.isNotNull(ordersDto.getPaymentAt())){
queryRespDto.setPaymentAt(DateUtil.Formatter.yyyyMMddHHmmss.format(ordersDto.getPaymentAt()));
}else{
queryRespDto.setPaymentAt("");
}
return queryRespDto;
}
// public void sendNotifyBackup(PayNotifyReqBo payNotifyReqBo){
// PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
// LocalDateTime nowTime = LocalDateTime.now();
// MultiValueMap<String, String> params = new LinkedMultiValueMap();
// params.add("status", payNotifyDto.getStatus().toString());
// params.add("type", payNotifyDto.getType());
// params.add("code", payNotifyDto.getCode());
// params.add("paymentId", payNotifyDto.getPaymentId());
// params.add("orderCode", payNotifyDto.getOrderCode());
// params.add("price", payNotifyDto.getPrice().toString());
// params.add("paymentType", payNotifyDto.getPaymentType());
// String jsonData = JSON.toJSONString(params);
// log.info("dragon:notify:post url:{}",payNotifyReqBo.getNotifyUrl());
// log.info("dragon:notify:post data:{}",jsonData);
// try {
// String response = HttpUtil.post(payNotifyReqBo.getNotifyUrl(), params);
// log.debug("PAY RESPONSE=" + response);
// if (response.equals("success")) {
// this.createDragonPayNotify(payNotifyReqBo,jsonData);
// //更新通知状态-通知成功
// this.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_SUCCESS.getCode()));
// } else {
// this.createDragonPayNotifyFail(payNotifyReqBo,jsonData);
// //更新通知状态-通知失败
// this.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_FAIL.getCode()));
// }
//
// if(true){
// throw new ConnectTimeoutException();
// }
// } catch (ConnectTimeoutException e) {
// System.out.println("请求超时");
//
// }catch (Exception e){
// e.printStackTrace();
// }
// }
public boolean sendNotify(PayNotifyReqBo payNotifyReqBo){
PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
LocalDateTime nowTime = LocalDateTime.now();
CloseableHttpClient httpclient = HttpClients.createDefault();
String jsonData = "";
try {
HttpPost httpPost = new HttpPost(payNotifyReqBo.getNotifyUrl());
//配置超时
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000).setConnectionRequestTimeout(5000)
.setSocketTimeout(5000).build();
httpPost.setConfig(requestConfig);
//设置post请求参数
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("status", payNotifyDto.getStatus().toString()));
nvps.add(new BasicNameValuePair("type", payNotifyDto.getType()));
nvps.add(new BasicNameValuePair("code", payNotifyDto.getCode()));
nvps.add(new BasicNameValuePair("paymentId", payNotifyDto.getPaymentId()));
nvps.add(new BasicNameValuePair("orderCode", payNotifyDto.getOrderCode()));
nvps.add(new BasicNameValuePair("price", payNotifyDto.getPrice().toString()));
nvps.add(new BasicNameValuePair("paymentType", payNotifyDto.getPaymentType()));
nvps.add(new BasicNameValuePair("paymentAt", payNotifyDto.getPaymentAt()));
jsonData = JsonUtils.toJson(covertNVPS2Params(nvps));
log.info("dragon:notify:post url:{}",payNotifyReqBo.getNotifyUrl());
log.info("dragon:notify:post data:{}",jsonData);
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
//执行post请求
CloseableHttpResponse responseObj = httpclient.execute(httpPost);
String response = EntityUtils.toString(responseObj.getEntity(), "utf-8");
log.debug("PAY RESPONSE=" + response);
if (response.equalsIgnoreCase("success")) {
dragonServiceCommonBiz.createDragonPayNotify(payNotifyReqBo,jsonData);
//更新通知状态-通知成功
dragonServiceCommonBiz.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_SUCCESS.getCode()));
return true;
} else {
dragonServiceCommonBiz.createDragonPayNotifyFail(payNotifyReqBo,jsonData);
//更新通知状态-通知失败
dragonServiceCommonBiz.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_FAIL.getCode()));
return false;
}
} catch (ConnectTimeoutException e) {
log.error("dragon:sendNotify 请求超时",e);
dragonServiceCommonBiz.createDragonPayNotifyFail(payNotifyReqBo,jsonData);
//更新通知状态-通知失败
dragonServiceCommonBiz.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_EXPIRE.getCode()));
return false;
} catch (Exception e) {
log.error("dragon:sendNotify 请求失败",e);
dragonServiceCommonBiz.createDragonPayNotifyFail(payNotifyReqBo,jsonData);
//更新通知状态-通知失败
dragonServiceCommonBiz.updateNotifyStatus(payNotifyDto.getCode(),Integer.valueOf(DragonConstant.PayNotifyStatusEnum.NOTIFY_FAIL.getCode()));
return false;
}finally {
//释放连接
try {
if (httpclient != null) {
httpclient.close();
}
} catch (IOException e) {
log.error("连接无法关闭",e);
}
}
}
public String getPaymentType(String payType,String deviceFrom){
return (deviceFrom+payType).toUpperCase();
}
private static Map<String, Object> covertNVPS2Params(List<NameValuePair> nvpList) {
Map<String, Object> rsMap = ObjectUtil.cloneHashMapStringAndObj();
for (NameValuePair nameValuePair : nvpList) {
rsMap.put(nameValuePair.getName(),nameValuePair.getValue());
}
return rsMap;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.IPayChannelStrategy;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AbstractPayChannelStrategyImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/16 13:04
*/
@Slf4j
public abstract class AbstractPayChannelStrategyImpl implements IPayChannelStrategy {
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DataUtils dataUtils;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Override
public abstract ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
@Override
public abstract String dragonNotify(HttpServletRequest request, String payType, String deviceFrom);
@Override
public abstract DragonPayOrderQueryRespDto checkOrderStatus(String code);
/**
* 支付成功方法
* @param dragonOrdersDto
* @param bankTrxNo
* @param timeEnd
* @param bankReturnMsg
*/
@Transactional(rollbackFor = Exception.class)
protected boolean completeSuccessOrder(DragonOrdersDto dragonOrdersDto, String bankTrxNo, LocalDateTime timeEnd, String bankReturnMsg) {
log.info("订单支付成功!");
dragonOrdersDto.setPaymentAt(timeEnd);
dragonOrdersDto.setPaymentId(bankTrxNo);// 设置银行流水号
dragonOrdersDto.setStatus(Integer.parseInt(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
//更新缓存
dataUtils.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto);
//修改订单状态
dragonServiceCommonBiz.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto.getStatus(),bankTrxNo);
//通知商户
return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(dragonOrdersDto));
}
/**
* 支付失败方法
* @param dragonOrdersDto
* @param bankReturnMsg
*/
protected boolean completeFailOrder(DragonOrdersDto dragonOrdersDto, String bankReturnMsg) {
log.info("订单支付失败!");
// dragonOrdersDto.setPaymentAt(timeEnd);
// dragonOrdersDto.setPaymentId(bankTrxNo);// 设置银行流水号
dragonOrdersDto.setStatus(Integer.parseInt(DragonConstant.PayStatusEnum.STATUS_PAY_FAIL.getCode()));
//更新缓存
dataUtils.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto);
//修改订单状态
dragonServiceCommonBiz.updateOrderStatus(dragonOrdersDto.getCode(),dragonOrdersDto.getStatus(),null);
//通知商户
return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(dragonOrdersDto));
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.alipay.biz.AlipayBiz;
import com.liquidnet.service.dragon.channel.alipay.constant.AlipayConstant;
import com.liquidnet.service.dragon.channel.alipay.strategy.AlipayStrategyContext;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.impl.DragonOrderRefundsServiceImpl;
import com.liquidnet.service.dragon.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyAlipayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.ALIPAY)
public class PayChannelStrategyAlipayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private AlipayStrategyContext alipayStrategyContext;
@Autowired
private DataUtils dataUtils;
@Autowired
private AlipayBiz alipayBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonOrderRefundsServiceImpl dragonOrderRefundsService;
@Value("${liquidnet.dragon.alipay.appId}")
private String appId;
@Value("${liquidnet.dragon.alipay.merchantPubKey}")
private String merchantPubKey;
@Value("${liquidnet.dragon.alipay.merchantPrivateKey}")
private String merchantPrivateKey;
@Value("${liquidnet.dragon.alipay.signtType}")
private String signtType;
@Value("${liquidnet.dragon.alipay.charset}")
private String charset;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return alipayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
log.info("alipay-->notify-->begin payType:{} deviceFrom:{}",payType,deviceFrom);
Map<String, String[]> requestParams = request.getParameterMap();
Map<String, String> notifyMap = new HashMap<String, String>();
notifyMap = alipayBiz.parseNotifyMsg(requestParams);
log.info("dragonNotify-->alipay json : {}", JSON.toJSONString(notifyMap));
log.info("接收到{}支付结果{}", payType, notifyMap);
String returnStr = "fail";
String code = notifyMap.get("out_trade_no");
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
//退款
if(notifyMap.containsKey("refund_fee") || notifyMap.containsKey("gmt_refund") || notifyMap.containsKey("out_biz_no")) {
returnStr = dragonOrderRefundsService.aliPayRefundCallBack(JSON.toJSONString(notifyMap));
}
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtils.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
try {
if (AlipaySignature.rsaCheckV1(notifyMap, merchantPubKey, "UTF-8", "RSA2")){
String tradeStatus = notifyMap.get("trade_status");
boolean notifyResult = false;
if (AlipayConstant.AlipayTradeStateEnum.TRADE_SUCCESS.name().equals(tradeStatus)
||AlipayConstant.AlipayTradeStateEnum.TRADE_FINISHED.name().equals(tradeStatus)) {
String gmtPaymentStr = notifyMap.get("gmt_payment");// 付款时间
LocalDateTime timeEnd = null;
if (!StringUtil.isEmpty(gmtPaymentStr)) {
timeEnd = DateUtil.Formatter.yyyyMMddHHmmss.parse(gmtPaymentStr);
}
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("trade_no"), timeEnd, notifyMap.toString());
} else {
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
if(notifyResult){
returnStr = "success";
}
} else {// 验证失败
log.error("alipay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getMessage());
return returnStr;
}
} catch (AlipayApiException e) {
log.error("alipay notify fail 验签失败:e:{}" , e);
log.error("alipay notify fail 验签失败:code:{} msg:{}" ,DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_SIGN_ERROR.getMessage());
}
log.info("返回支付通道{}信息{}", payType, returnStr);
log.info("alipay-->notify-->end payType:{} deviceFrom:{}",payType,deviceFrom);
return returnStr;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
Map<String, Object> resultMap = alipayBiz.tradeQuery(code);
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
if ("10000".equals(resultMap.get("code"))) {
// 当返回状态为“TRADE_FINISHED”交易成功结束和“TRADE_SUCCESS”支付成功时更新交易状态
if (AlipayConstant.AlipayTradeStateEnum.TRADE_SUCCESS.getCode().equals(resultMap.get("tradeStatus"))
|| AlipayConstant.AlipayTradeStateEnum.TRADE_FINISHED.getCode().equals(resultMap.get("tradeStatus"))) {
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
}else{
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAY_FAIL.getCode()));
}
// throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getMessage());
}else if("40004".equals(resultMap.get("code"))&&"ACQ.TRADE_NOT_EXIST".equalsIgnoreCase(resultMap.get("subCode").toString())){
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode()));
}else{
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_ALIPAY_QUERY_ERROR.getMessage());
}
return respDto;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyApplepayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.APPLEPAY)
public class PayChannelStrategyApplepayImpl extends AbstractPayChannelStrategyImpl {
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return null;
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
return null;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
return null;
}
}
package com.liquidnet.service.dragon.channel.strategy.impl;
import com.alibaba.fastjson.JSON;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.annotation.StrategyPayChannelHandler;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.wepay.constant.WepayConstant;
import com.liquidnet.service.dragon.channel.wepay.strategy.WepayStrategyContext;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtils;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayChannelStrategyWepayImpl
* @Package com.liquidnet.service.dragon.channel.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/13 13:06
*/
@Slf4j
@Component
@StrategyPayChannelHandler(DragonConstant.PayChannelEnum.WEPAY)
public class PayChannelStrategyWepayImpl extends AbstractPayChannelStrategyImpl {
@Autowired
private WepayStrategyContext wepayStrategyContext;
@Autowired
private DataUtils dataUtils;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
return wepayStrategyContext.getStrategy(dragonPayBaseReqDto.getDeviceFrom()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
String returnStr = "<xml>\n" + " <return_code><![CDATA[FAIL]]></return_code>\n" + " <return_msg><![CDATA[FAIL]]></return_msg>\n" + "</xml>";;
try {
InputStream inputStream = request.getInputStream();// 从request中取得输入流
Map<String, String> notifyMap = new HashMap<String, String>();
try {
notifyMap = PayWepayUtils.parseXml(inputStream);
log.info("dragonNotify-->wepay json : {}", JSON.toJSONString(notifyMap));
log.info("接收到{}支付结果{}", payType, notifyMap);
String code = notifyMap.get("out_trade_no");
//持久化通知记录
dragonServiceCommonBiz.createDragonOrderLogs(code,dragonPayBiz.getPaymentType(payType,deviceFrom),JSON.toJSONString(notifyMap));
// 根据银行订单号获取支付信息
DragonOrdersDto dragonOrdersDto = dataUtils.getPayOrderByCode(code);
if (dragonOrdersDto == null) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
if (DragonConstant.PayStatusEnum.STATUS_PAID.getCode().equals(dragonOrdersDto.getStatus())) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getCode(),DragonErrorCodeEnum.TRADE_ERROR_HAS_PAID.getMessage());
}
String sign = notifyMap.remove("sign");
boolean notifyResult = false;
if (PayWepayUtils.getInstance().notifySign(notifyMap, sign)) {// 根据配置信息验证签名
if (WepayConstant.WeixinTradeStateEnum.SUCCESS.getCode().equals(notifyMap.get("result_code"))) {// 业务结果
// 成功
String timeEndStr = notifyMap.get("time_end");
LocalDateTime timeEnd = null;
if (!StringUtil.isEmpty(timeEndStr)) {
timeEnd = DateUtil.Formatter.yyyyMMddHHmmssTrim.parse(timeEndStr);
}
notifyResult = this.completeSuccessOrder(dragonOrdersDto, notifyMap.get("transaction_id"), timeEnd, notifyMap.toString());
} else {
notifyResult = this.completeFailOrder(dragonOrdersDto, notifyMap.toString());
}
if(notifyResult){
returnStr = "<xml>\n" + " <return_code><![CDATA[SUCCESS]]></return_code>\n" + " <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
}
} else {
log.error("wepay notify fail code:{} msg:{} ",DragonErrorCodeEnum.TRADE_WEPAY_SIGN_ERROR.getCode(),DragonErrorCodeEnum.TRADE_WEPAY_SIGN_ERROR.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return returnStr;
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
DragonPayOrderQueryRespDto respDto = wepayStrategyContext.getStrategy(DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getDeviceFrom()).checkOrderStatus(code);
return respDto;
}
}
package com.liquidnet.service.dragon.channel.wepay.biz;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import com.liquidnet.service.dragon.utils.XmlUtil;
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.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: WepayBiz
* @Package com.liquidnet.service.dragon.channel.wepay.biz
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 16:46
*/
@Slf4j
@Component
public class WepayBiz{
@Value("${liquidnet.dragon.wepay.merchantId}")
private String merchantId;
/**
* 订单查询
*
* @return
*/
public Map<String, Object> tradeQuery(String outTradeNo, String appid) {
log.info("WepayBiz.tradeQuery-->> request outTradeNo:{} appid:{} ",outTradeNo,appid);
Map<String, Object> respMap = new HashMap<>();
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("appid", appid);
paramMap.put("mch_id", merchantId);
String nonce_str = PayWepayUtils.getInstance().getNonceStr();
paramMap.put("nonce_str", nonce_str);
paramMap.put("out_trade_no", outTradeNo);
String sign = PayWepayUtils.getInstance().createSign(paramMap);
paramMap.put("sign", sign);
String data = PayWepayUtils.getInstance().getRequestXml(paramMap);
try{
HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/pay/orderquery");
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = PayWepayUtils.getInstance().getHttpClient().execute(httpost);
HttpEntity entity = response.getEntity();
//接受到返回信息
String xmlStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
log.info("WepayBiz.tradeQuery-->> response xmlStr: {} ",xmlStr);
respMap = XmlUtil.xmlToMap(xmlStr);
}catch (Exception e){
log.error(e.getMessage());
}
return respMap;
}
}
package com.liquidnet.service.dragon.channel.wepay.constant;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: WepayConstant
* @Package com.liquidnet.service.dragon.channel.wepay
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/14 11:05
*/
public class WepayConstant {
public enum WeixinTradeStateEnum {
SUCCESS("SUCCESS","成功"), FAIL("FAIL","失败");
private String code;
private String message;
WeixinTradeStateEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
}
}
/*
* Copyright 2015-2102 RonCoo(http://www.roncoo.com) Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.liquidnet.service.dragon.channel.wepay.req;
import com.liquidnet.commons.lang.util.IDGenerator;
import java.io.Serializable;
/**
* <b>功能说明:微信预支付实体类</b>
* @author Peter
* <a href="http://www.roncoo.com">龙果学院(www.roncoo.com)</a>
*/
public class WepayPrePayReq implements Serializable {
/** 公众账号ID 必填 **/
private String appid;
/** 商户号 必填 **/
private String mchId;
/** 设备号 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB" 默认为'WEB'**/
private String deviceInfo = "WEB";
/** 随机字符串 **/
private String nonceStr = IDGenerator.get32UUID();
/** 签名 **/
private String sign;
/** 商品描述 **/
private String body;
/** 商品详情 **/
private String detail;
/** 附加数据 **/
private String attach;
/** 商户订单号 **/
private String outTradeNo;
/** 货币类型 默认为人民币 **/
private String feeType = "CNY";
/** 总金额 **/
private Integer totalFee;
/** 终端IP **/
private String spbillCreateIp;
/** 交易起始时间 **/
private String timeStart;
/** 交易结束时间 **/
private String timeExpire;
/** 商品标记 **/
private String goodsTag;
/** 通知地址 **/
private String notifyUrl;
/** 商品ID **/
private String productId;
/** 制定支付方式 **/
private String limitPay;
/** 用户标识 **/
private String openid;
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public String getSpbillCreateIp() {
return spbillCreateIp;
}
public void setSpbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
}
public String getTimeStart() {
return timeStart;
}
public void setTimeStart(String timeStart) {
this.timeStart = timeStart;
}
public String getTimeExpire() {
return timeExpire;
}
public void setTimeExpire(String timeExpire) {
this.timeExpire = timeExpire;
}
public String getGoodsTag() {
return goodsTag;
}
public void setGoodsTag(String goodsTag) {
this.goodsTag = goodsTag;
}
public String getNotifyUrl() {
return notifyUrl;
}
public void setNotifyUrl(String notifyUrl) {
this.notifyUrl = notifyUrl;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getLimitPay() {
return limitPay;
}
public void setLimitPay(String limitPay) {
this.limitPay = limitPay;
}
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class AliPayRefundReturnCallBackDto {
@JsonProperty("gmt_create")
private String gmtCreate;
@JsonProperty("charset")
private String charset;
@JsonProperty("seller_email")
private String sellerEmail;
@JsonProperty("gmt_payment")
private String gmtPayment;
@JsonProperty("notify_time")
private String notifyTime;
@JsonProperty("subject")
private String subject;
@JsonProperty("gmt_refund")
private String gmtRefund;
@JsonProperty("sign")
private String sign;
@JsonProperty("out_biz_no")
private String outBizNo;
@JsonProperty("body")
private String body;
@JsonProperty("buyer_id")
private String buyerId;
@JsonProperty("version")
private String version;
@JsonProperty("notify_id")
private String notifyId;
@JsonProperty("notify_type")
private String notifyType;
@JsonProperty("out_trade_no")
private String outTradeNo;
@JsonProperty("total_amount")
private String totalAmount;
@JsonProperty("trade_status")
private String tradeStatus;
@JsonProperty("refund_fee")
private String refundFee;
@JsonProperty("trade_no")
private String tradeNo;
@JsonProperty("auth_app_id")
private String authAppId;
@JsonProperty("buyer_logon_id")
private String buyerLogonId;
@JsonProperty("app_id")
private String appId;
@JsonProperty("sign_type")
private String signType;
@JsonProperty("seller_id")
private String sellerId;
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
@Data
@XStreamAlias("xml")
public class WePayRefundReturnCallBackDto {
@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
@XStreamAlias("appid")
private String appId;
@XStreamAlias("mch_id")
private String mchId;
@XStreamAlias("nonce_str")
private String nonceStr;
@XStreamAlias("req_info")
private String reqInfo;
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
@Data
@XStreamAlias("root")
public class WePayRefundReturnCallBackInfoDto {
@XStreamAlias("out_refund_no")
private String outRefundNo;
@XStreamAlias("out_trade_no")
private String outTradeNo;
@XStreamAlias("refund_account")
private String refundAccount;
@XStreamAlias("refund_fee")
private String refundFee;
@XStreamAlias("refund_id")
private String refundId;
@XStreamAlias("refund_recv_accout")
private String refundRecvAccout;
@XStreamAlias("refund_request_source")
private String refundRequestSource;
@XStreamAlias("refund_status")
private String refundStatus;
@XStreamAlias("settlement_refund_fee")
private String settlementRefundFee;
@XStreamAlias("settlement_total_fee")
private String settlementTotalFee;
@XStreamAlias("success_time")
private String successTime;
@XStreamAlias("total_fee")
private String totalFee;
@XStreamAlias("transaction_id")
private String transactionId;
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
@Data
@XStreamAlias("xml")
public class WePayRefundReturnDto {
@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
@XStreamAlias("appid")
private String appId;
@XStreamAlias("mch_id")
private String mchId;
@XStreamAlias("nonce_str")
private String nonceStr;
@XStreamAlias("sign")
private String sign;
@XStreamAlias("result_code")
private String resultCode;
@XStreamAlias("transaction_id")
private String transactionId;
@XStreamAlias("out_trade_no")
private String outTradeNo;
@XStreamAlias("out_refund_no")
private String outRefundNo;
@XStreamAlias("refund_id")
private String refundId;
@XStreamAlias("refund_channel")
private String refundChannel;
@XStreamAlias("refund_fee")
private String refundFee;
@XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
@XStreamAlias("total_fee")
private String totalFee;
@XStreamAlias("cash_fee")
private String cashFee;
@XStreamAlias("coupon_refund_count")
private String couponRefundCount;
@XStreamAlias("cash_refund_fee")
private String cashRefundFee;
@XStreamAlias("err_code")
private String errCode;
@XStreamAlias("err_code_des")
private String errCodeDes;
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import lombok.Data;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: WepayPayOrderQueryRespDto
* @Package com.liquidnet.service.dragon.channel.wepay.resp
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/14 13:21
*/
@Data
public class WepayOrderQueryRespDto {
}
package com.liquidnet.service.dragon.channel.wepay.resp;
import com.liquidnet.service.dragon.utils.XmlUtil;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: WepayPayRespDto
* @Package com.liquidnet.service.dragon.channel.wepay.resp
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/12 10:40
*/
@Data
@XStreamAlias("xml")
public class WepayPayRespDto {
@XStreamAlias("return_code")
private String returnCode; //SUCCESS
@XStreamAlias("return_msg")
private String returnMsg; //OK
@XStreamAlias("result_code")
private String resultCode; //SUCCESS
@XStreamAlias("mch_id")
private String mchId; //1551961491
@XStreamAlias("appid")
private String appid; //wx3498304dda39c5a1
@XStreamAlias("nonce_str")
private String nonceStr; //Y6Czfx4lhuSv0yUD
@XStreamAlias("sign")
private String sign; //97001E77813055D03E3009F67A836D62
@XStreamAlias("prepay_id")
private String prepayId; //wx111130490949693ab00f679072ea730000
@XStreamAlias("trade_type")
private String tradeType; //MWEB
@XStreamAlias("mweb_url")
private String mwebUrl; //https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx111130490949693ab00f679072ea730000&package=2011082926
public static void xmlToBean(){
String xmlStr = "<xml><return_code><![CDATA[SUCCESS]]></return_code>\n" +
"<return_msg><![CDATA[OK]]></return_msg>\n" +
"<result_code><![CDATA[SUCCESS]]></result_code>\n" +
"<mch_id><![CDATA[1551961491]]></mch_id>\n" +
"<appid><![CDATA[wx3498304dda39c5a1]]></appid>\n" +
"<nonce_str><![CDATA[Y6Czfx4lhuSv0yUD]]></nonce_str>\n" +
"<sign><![CDATA[97001E77813055D03E3009F67A836D62]]></sign>\n" +
"<prepay_id><![CDATA[wx111130490949693ab00f679072ea730000]]></prepay_id>\n" +
"<trade_type><![CDATA[MWEB]]></trade_type>\n" +
"<mweb_url><![CDATA[https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx111130490949693ab00f679072ea730000&package=2011082926]]></mweb_url>\n" +
"</xml> ";
WepayPayRespDto respDto= XmlUtil.toBean(xmlStr, WepayPayRespDto.class);
System.out.println("respDto.getAppid()=="+respDto.getAppid());
System.out.println("respDto.getMwebUrl()==="+respDto.getMwebUrl());
}
public static void main(String[] args) {
xmlToBean();
}
}
package com.liquidnet.service.dragon.channel.wepay.strategy;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
public interface IWepayStrategy {
ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto);
DragonPayOrderQueryRespDto checkOrderStatus(String code);
}
package com.liquidnet.service.dragon.channel.wepay.strategy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class WepayStrategyContext {
private final Map<String, IWepayStrategy> handlerMap = new HashMap<>();
public IWepayStrategy getStrategy(String type) {
return handlerMap.get(type);
}
public void putStrategy(String code, IWepayStrategy strategy) {
handlerMap.put(code, strategy);
}
}
package com.liquidnet.service.dragon.channel.wepay.strategy;
import com.liquidnet.service.dragon.channel.wepay.strategy.annotation.StrategyWepayHandler;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: Test
* @Package com.liquidnet.service.dragon.channel.strategy
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:27
*/
@Component
public class WepayStrategyListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(StrategyWepayHandler.class);
WepayStrategyContext strategyContext = event.getApplicationContext().getBean(WepayStrategyContext.class);
beans.forEach((name, bean) -> {
StrategyWepayHandler typeHandler = bean.getClass().getAnnotation(StrategyWepayHandler.class);
strategyContext.putStrategy(typeHandler.value().getCode(), (IWepayStrategy) bean);
});
}
}
\ No newline at end of file
package com.liquidnet.service.dragon.channel.wepay.strategy.annotation;
import com.liquidnet.service.dragon.constant.DragonConstant;
import java.lang.annotation.*;
/**
* @author AnJiabin <jiabin.an@lightnet.io>
* @version V1.0
* @Description: TODO
* @class: StrategyGetFundDataHandler
* @Package com.liquidnet.service.reconciliation.strategy.annotation
* @Copyright: LightNet @ Copyright (c) 2020
* @date 2020/10/27 15:29
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StrategyWepayHandler {
DragonConstant.DeviceFromEnum value();
}
package com.liquidnet.service.dragon.channel.wepay.strategy.impl;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.biz.DragonServiceCommonBiz;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.wepay.biz.WepayBiz;
import com.liquidnet.service.dragon.channel.wepay.constant.WepayConstant;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.IWepayStrategy;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.utils.DataUtils;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import com.liquidnet.service.dragon.utils.XmlUtil;
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.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AbstractWepayStrategy
* @Package com.liquidnet.service.dragon.channel.wepay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/11 11:56
*/
@Slf4j
public abstract class AbstractWepayStrategy implements IWepayStrategy {
@Autowired
private WepayBiz wepayBiz;
@Autowired
private DataUtils dataUtils;
@Autowired
private DragonServiceCommonBiz dragonServiceCommonBiz;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
try {
//构造请求参数
SortedMap<String, Object> commonParams = this.buildRequestParamMap(dragonPayBaseReqDto);
//追加请求参数
SortedMap<String, Object> parameters = this.appendRequestParam(commonParams,dragonPayBaseReqDto);
//生成签名
String sign = PayWepayUtils.getInstance().createSign(parameters);
parameters.put("sign", sign);
//构造支付请求xml
String data = PayWepayUtils.getInstance().getRequestXml(parameters);
log.info("dragonPay:wepay:"+dragonPayBaseReqDto.getDeviceFrom()+" request jsondata: {} ",data);
HttpPost httpost = new HttpPost(this.getRequestUrl());
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = PayWepayUtils.getInstance().getHttpClient().execute(httpost);
HttpEntity entity = response.getEntity();
//接受到返回信息
String xmlStr = EntityUtils.toString(response.getEntity(), "UTF-8");
EntityUtils.consume(entity);
log.info("dragonPay:wepay:"+dragonPayBaseReqDto.getDeviceFrom()+" response jsonStr: {} ",xmlStr);
WepayPayRespDto respWepayDto= null;
try {
respWepayDto = XmlUtil.toBean(xmlStr, WepayPayRespDto.class);
} catch (Exception e) {
log.error("dragonPay:wepay:"+dragonPayBaseReqDto.getDeviceFrom()+" response format error: {} ",e);
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(),DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
}
if(WepayConstant.WeixinTradeStateEnum.SUCCESS.getCode().equalsIgnoreCase(respWepayDto.getReturnCode())){
if(WepayConstant.WeixinTradeStateEnum.SUCCESS.getCode().equalsIgnoreCase(respWepayDto.getResultCode())){
//构造公共返回参数
DragonPayBaseRespDto respPayDto = this.buildCommonRespDto(dragonPayBaseReqDto,respWepayDto);
//构造自定义返回参数
this.buildResponseDto(respPayDto,respWepayDto);
//支付订单持久化
dragonServiceCommonBiz.buildPayOrders(dragonPayBaseReqDto,respPayDto);
return ResponseDto.success(respPayDto);
}else{
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(),DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
}
}else{
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(),DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 构造公共返回参数
* @param dragonPayBaseReqDto
* @return
*/
protected DragonPayBaseRespDto buildCommonRespDto(DragonPayBaseReqDto dragonPayBaseReqDto,WepayPayRespDto respWepayDto){
String nonceStr = PayWepayUtils.getInstance().getNonceStr();
DragonPayBaseRespDto respDto = new DragonPayBaseRespDto();
respDto.setCode(dragonPayBaseReqDto.getCode());
respDto.setOrderCode(dragonPayBaseReqDto.getOrderCode());
DragonPayBaseRespDto.PayData payData = new DragonPayBaseRespDto.PayData();
payData.setAppId(respWepayDto.getAppid());
payData.setNonceStr(nonceStr);
payData.setPackages("prepay_id="+respWepayDto.getPrepayId());
payData.setSignType("MD5");
Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
payData.setTimeStamp(second+"");
payData.setPartnerId(respWepayDto.getMchId());
payData.setPrepayId(respWepayDto.getPrepayId());
respDto.setPayData(payData);
return respDto;
}
/**
* 构造请求参数
* @return
*/
protected SortedMap<String, Object> buildRequestParamMap(DragonPayBaseReqDto dragonPayBaseReqDto){
String nonceStr = PayWepayUtils.getInstance().getNonceStr();
SortedMap<String, Object> parameters = new TreeMap<>();
parameters.put("mch_id", PayWepayUtils.getInstance().getMerchantId());
parameters.put("nonce_str", nonceStr);
parameters.put("spbill_create_ip", dragonPayBaseReqDto.getClientIp());
parameters.put("total_fee", dragonPayBaseReqDto.getPrice().multiply(BigDecimal.valueOf(100L)).intValue()+"");
parameters.put("body", dragonPayBaseReqDto.getName());
parameters.put("detail", dragonPayBaseReqDto.getDetail());
parameters.put("out_trade_no", dragonPayBaseReqDto.getCode());
String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmssTrim);
parameters.put("time_expire", timeExpire);
parameters.put("notify_url", this.getNotifyUrl());
return parameters;
};
/**
* 追加请求参数
* @param requestMap
* @return
*/
abstract SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap,DragonPayBaseReqDto dragonPayBaseReqDto);
/**
* 构造返回参数
*/
abstract DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto,WepayPayRespDto respDto);
/**
* 获取请求url
* @return
*/
protected abstract String getRequestUrl();
/**
* 设置notifyUrl
*/
protected abstract String getNotifyUrl();
@Override
public DragonPayOrderQueryRespDto checkOrderStatus(String code) {
DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
Map<String, Object> resultMap = wepayBiz.tradeQuery(code,this.getAppid());
DragonPayOrderQueryRespDto respDto = dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
Object returnCode = resultMap.get("return_code");
// 查询失败
if (null == returnCode || "FAIL".equals(returnCode)) {
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_WEPAY_QUERY_ERROR.getCode(),DragonErrorCodeEnum.TRADE_WEPAY_QUERY_ERROR.getMessage());
}
// 当trade_state为SUCCESS时才返回result_code
if ("SUCCESS".equals(resultMap.get("trade_state"))) {
respDto.setStatus(Integer.valueOf(DragonConstant.PayStatusEnum.STATUS_PAID.getCode()));
}
return respDto;
}
protected abstract String getAppid();
}
package com.liquidnet.service.dragon.channel.wepay.strategy.impl;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.annotation.StrategyWepayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyWepayHandler(DragonConstant.DeviceFromEnum.APP)
public class WepayStrategyAppImpl extends AbstractWepayStrategy {
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Override
SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap,DragonPayBaseReqDto dragonPayBaseReqDto) {
requestMap.put("trade_type", "APP");
requestMap.put("appid", PayWepayUtils.getInstance().getAPP_ID());
return requestMap;
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, WepayPayRespDto respDto) {
payBaseRespDto.getPayData().setPackages("Sign=WXPay");
//设置签名
SortedMap<String, Object> paramMap = new TreeMap<String, Object>();
paramMap.put("appid", payBaseRespDto.getPayData().getAppId());
paramMap.put("partnerid", payBaseRespDto.getPayData().getPartnerId());
paramMap.put("prepayid", payBaseRespDto.getPayData().getPrepayId());
paramMap.put("package", payBaseRespDto.getPayData().getPackages());
paramMap.put("noncestr", payBaseRespDto.getPayData().getNonceStr());
paramMap.put("timestamp", payBaseRespDto.getPayData().getTimeStamp());
log.info("wepay sercond sign param :{} ", JsonUtils.toJson(paramMap));
String sign = PayWepayUtils.getInstance().createSign(paramMap);
payBaseRespDto.getPayData().setPaySign(sign);
return payBaseRespDto;
}
@Override
protected String getRequestUrl() {
return "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
@Override
protected String getNotifyUrl() {
return notifyUrl + "/notify/wepay/app";
}
@Override
protected String getAppid() {
return PayWepayUtils.getInstance().getAPP_ID();
}
}
package com.liquidnet.service.dragon.channel.wepay.strategy.impl;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.annotation.StrategyWepayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyWepayHandler(DragonConstant.DeviceFromEnum.APPLET)
public class WepayStrategyAppletImpl extends AbstractWepayStrategy{
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Override
SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap, DragonPayBaseReqDto dragonPayBaseReqDto) {
requestMap.put("trade_type", "JSAPI");
requestMap.put("appid", PayWepayUtils.getInstance().getAPPLET_APP_ID());
requestMap.put("openid", dragonPayBaseReqDto.getOpenId()); //只有trade_type="JSAPI"时必须传
return requestMap;
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, WepayPayRespDto respDto) {
//设置签名
SortedMap<String, Object> paramMap = new TreeMap<String, Object>();
paramMap.put("appId", respDto.getAppid());
paramMap.put("package", payBaseRespDto.getPayData().getPackages());
paramMap.put("nonceStr", payBaseRespDto.getPayData().getNonceStr());
paramMap.put("timeStamp", payBaseRespDto.getPayData().getTimeStamp());
paramMap.put("signType", payBaseRespDto.getPayData().getSignType());
String sign = PayWepayUtils.getInstance().createSign(paramMap);
payBaseRespDto.getPayData().setPaySign(sign);
return payBaseRespDto;
}
@Override
protected String getRequestUrl() {
return "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
@Override
protected String getNotifyUrl() {
return notifyUrl + "/notify/wepay/applet";
}
@Override
protected String getAppid() {
return PayWepayUtils.getInstance().getAPPLET_APP_ID();
}
}
package com.liquidnet.service.dragon.channel.wepay.strategy.impl;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.annotation.StrategyWepayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyWepayHandler(DragonConstant.DeviceFromEnum.JS)
public class WepayStrategyJsImpl extends AbstractWepayStrategy{
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Override
SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap, DragonPayBaseReqDto dragonPayBaseReqDto) {
requestMap.put("trade_type", "JSAPI");
requestMap.put("appid", PayWepayUtils.getInstance().getJS_APP_ID());
requestMap.put("openid", dragonPayBaseReqDto.getOpenId()); //只有trade_type="JSAPI"时必须传
return requestMap;
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, WepayPayRespDto respDto) {
//设置签名
SortedMap<String, Object> paramMap = new TreeMap<String, Object>();
paramMap.put("appId", respDto.getAppid());
paramMap.put("package", payBaseRespDto.getPayData().getPackages());
paramMap.put("nonceStr", payBaseRespDto.getPayData().getNonceStr());
paramMap.put("timeStamp", payBaseRespDto.getPayData().getTimeStamp());
paramMap.put("signType", payBaseRespDto.getPayData().getSignType());
String sign = PayWepayUtils.getInstance().createSign(paramMap);
payBaseRespDto.getPayData().setPaySign(sign);
return payBaseRespDto;
}
@Override
protected String getRequestUrl() {
return "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
@Override
protected String getNotifyUrl() {
return notifyUrl + "/notify/wepay/js";
}
@Override
protected String getAppid() {
return PayWepayUtils.getInstance().getJS_APP_ID();
}
}
package com.liquidnet.service.dragon.channel.wepay.strategy.impl;
import com.liquidnet.service.dragon.channel.wepay.resp.WepayPayRespDto;
import com.liquidnet.service.dragon.channel.wepay.strategy.annotation.StrategyWepayHandler;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.utils.PayWepayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.SortedMap;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: AlipayStrategyWapImpl
* @Package com.liquidnet.service.dragon.channel.alipay.strategy.impl
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 14:34
*/
@Slf4j
@Component
@StrategyWepayHandler(DragonConstant.DeviceFromEnum.WAP)
public class WepayStrategyWapImpl extends AbstractWepayStrategy{
@Value("${liquidnet.dragon.url}")
private String notifyUrl;
@Override
SortedMap<String, Object> appendRequestParam(SortedMap<String, Object> requestMap, DragonPayBaseReqDto dragonPayBaseReqDto) {
requestMap.put("trade_type", "MWEB");
requestMap.put("appid", PayWepayUtils.getInstance().getWAP_APP_ID());
return requestMap;
}
@Override
DragonPayBaseRespDto buildResponseDto(DragonPayBaseRespDto payBaseRespDto, WepayPayRespDto respDto) {
payBaseRespDto.getPayData().setMwebUrl(respDto.getMwebUrl());
return payBaseRespDto;
}
@Override
protected String getRequestUrl() {
return "https://api.mch.weixin.qq.com/pay/unifiedorder";
}
@Override
protected String getNotifyUrl() {
return notifyUrl + "/notify/wepay/wap";
}
@Override
protected String getAppid() {
return PayWepayUtils.getInstance().getWAP_APP_ID();
}
}
package com.liquidnet.service.dragon.config;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.core.JwtValidator;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.DigestUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "access-filter")
public class AccessHandlerIntercept extends HandlerInterceptorAdapter {
private List<String> includeUrlPattern;
private List<String> excludeUrlPattern;
private static final String CONTENT_TYPE = "application/json;charset=utf-8";
private static final String TOKEN_ILLEGAL = "40001";
private static final String TOKEN_KICK = "40002";
private static final String TOKEN_INVALID = "40003";
// private static final String KYLIN_STATION_JWT_VALID = "/*/station/**";
private final static AntPathMatcher antPathMatcher = new AntPathMatcher();
@Autowired
Environment env;
@Autowired
JwtValidator jwtValidator;
@Autowired
RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authorization = request.getHeader(CurrentUtil.uToken), uri = request.getRequestURI(),
responseCode = null, token = null, currentUid = null;
Claims claims = null;
if (StringUtils.isNotBlank(authorization) && StringUtils.length(authorization) > 7) {
token = authorization.substring(7);
try {
// 解析没有异常则表示token验证通过,如有必要可根据自身需求增加验证逻辑
claims = jwtValidator.parse(token);
currentUid = (String) claims.get(CurrentUtil.TOKEN_SUB);
request.setAttribute(CurrentUtil.uToken, token);
request.setAttribute(CurrentUtil.TOKEN_SUB, currentUid);
request.setAttribute(CurrentUtil.uTag, JsonUtils.toJson(claims));
} catch (ExpiredJwtException expiredJwtEx) {
responseCode = TOKEN_INVALID;
log.error("Ex.ExpiredJwtException:{},responseCode:{}", expiredJwtEx.getMessage(), responseCode);
} catch (Exception ex) {
responseCode = TOKEN_ILLEGAL;
log.error("Ex.Exception:{},responseCode:{}", ex.getMessage(), responseCode);
}
} else {
responseCode = TOKEN_ILLEGAL;
}
for (String urlPattern : excludeUrlPattern) {
if (antPathMatcher.match(urlPattern, uri)) {
return true;
}
}
if (StringUtils.isNotEmpty(responseCode)) {
this.responseHandler(response, responseCode);
log.warn("Authority failed:{},uri:[{}],authorization:{}", responseCode, uri, authorization);
return false;
}
if (StringUtils.isEmpty(currentUid)) {
this.responseHandler(response, TOKEN_ILLEGAL);
return false;
}
if (this.authorityHandler(response, uri, token, currentUid, claims)) {
return true;
}
return false;
}
private void responseHandler(HttpServletResponse response, String responseCode) throws IOException {
ResponseDto<Object> responseDto = ResponseDto.failure(ErrorMapping.get(responseCode));
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType(CONTENT_TYPE);
response.getWriter().write(JsonUtils.toJson(responseDto));
}
private boolean authorityHandler(HttpServletResponse response, String uri, String token, String currentUid, Claims claims) throws IOException {
// if (antPathMatcher.match(KYLIN_STATION_JWT_VALID, uri)) {// 专业版APP
// // adam:identity:sso:${uid}:MD5(${token})=${1-在线|0-离线}
// String ssoUidM5TokenKey = jwtValidator.getMsoRedisKey()
// .concat(currentUid).concat(":").concat(DigestUtils.md5DigestAsHex(token.getBytes(StandardCharsets.UTF_8)));
// Integer online = (Integer) redisUtil.get(ssoUidM5TokenKey);
// if (null == online || online != 1) {
// // 已离线
// this.responseHandler(response, TOKEN_INVALID);
//
// return false;
// } else {
// return true;
// }
// } else {
// // adam:identity:sso:${uid}=MD5(${token})
// String ssoKey = jwtValidator.getSsoRedisKey().concat(currentUid), md5Token;
//
// if (StringUtils.isEmpty(md5Token = (String) redisUtil.get(ssoKey))) {
// // 已离线
// this.responseHandler(response, TOKEN_INVALID);
//
// return false;
// } else {
// // 与在线TOKEN比对
// if (md5Token.equals(DigestUtils.md5DigestAsHex(token.getBytes(StandardCharsets.UTF_8)))) {
// // 一致则放行
// return true;
// } else {
// // 不一致则被踢下线
// this.responseHandler(response, TOKEN_KICK);
//
// return false;
// }
// }
// }
String tokenType = (String) claims.get(CurrentUtil.TOKEN_TYPE);
switch (tokenType) {
case CurrentUtil.TOKEN_TYPE_VAL_STATION:// 专业版APP
// adam:identity:sso:${uid}:MD5(${token})=${1-在线|0-离线}
String ssoUidM5TokenKey = jwtValidator.getMsoRedisKey()
.concat(currentUid).concat(":").concat(DigestUtils.md5DigestAsHex(token.getBytes(StandardCharsets.UTF_8)));
Integer online = (Integer) redisUtil.get(ssoUidM5TokenKey);
if (null == online || online != 1) {
// 已离线
this.responseHandler(response, TOKEN_INVALID);
return false;
} else {
return true;
}
case CurrentUtil.TOKEN_TYPE_VAL_USER:
// adam:identity:sso:${uid}=MD5(${token})
String ssoKey = jwtValidator.getSsoRedisKey().concat(currentUid), md5Token;
if (StringUtils.isEmpty(md5Token = (String) redisUtil.get(ssoKey))) {
// 已离线
this.responseHandler(response, TOKEN_INVALID);
return false;
} else {
// 与在线TOKEN比对
if (md5Token.equals(DigestUtils.md5DigestAsHex(token.getBytes(StandardCharsets.UTF_8)))) {
// 一致则放行
return true;
} else {
// 不一致则被踢下线
this.responseHandler(response, TOKEN_KICK);
return false;
}
}
default:
log.warn("Authority failed:{} (Unknown token type).uri:[{}],token:{}", TOKEN_ILLEGAL, uri, token);
this.responseHandler(response, TOKEN_ILLEGAL);
return false;
}
}
}
package com.liquidnet.service.dragon.config;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedisStreamConfig {
// @Autowired
// private RedisPayNotifyReceiver redisPayNotifyReceiver;
// @Bean
// public Subscription subscriptionAlipayNotify0(RedisConnectionFactory factory) {
// var options = StreamMessageListenerContainer
// .StreamMessageListenerContainerOptions
// .builder()
// .pollTimeout(Duration.ofMillis(1))
// .build();
// var listenerContainer = StreamMessageListenerContainer.create(factory, options);
// var subscription = listenerContainer.receiveAutoAck(Consumer.from(DragonConstant.ChannelRedisQueueEnum.ALIPAY_PAY_GROUP.getCode(), "alipay-pay-notify-0"),
// StreamOffset.create(DragonConstant.ChannelRedisQueueEnum.ALIPAY_PAY_KEY.getCode(), ReadOffset.lastConsumed()), redisPayNotifyReceiver);
// listenerContainer.start();
// return subscription;
// }
//
// @Bean
// public Subscription subscriptionAlipayNotify1(RedisConnectionFactory factory) {
// var options = StreamMessageListenerContainer
// .StreamMessageListenerContainerOptions
// .builder()
// .pollTimeout(Duration.ofMillis(1))
// .build();
// var listenerContainer = StreamMessageListenerContainer.create(factory, options);
// var subscription = listenerContainer.receiveAutoAck(Consumer.from(DragonConstant.ChannelRedisQueueEnum.ALIPAY_PAY_GROUP.getCode(), "alipay-pay-notify-1"),
// StreamOffset.create(DragonConstant.ChannelRedisQueueEnum.ALIPAY_PAY_KEY.getCode(), ReadOffset.lastConsumed()), redisPayNotifyReceiver);
// listenerContainer.start();
// return subscription;
// }
//
// @Bean
// public Subscription subscriptionWepayNotify0(RedisConnectionFactory factory) {
// var options = StreamMessageListenerContainer
// .StreamMessageListenerContainerOptions
// .builder()
// .pollTimeout(Duration.ofMillis(1))
// .build();
// var listenerContainer = StreamMessageListenerContainer.create(factory, options);
// var subscription = listenerContainer.receiveAutoAck(Consumer.from(DragonConstant.ChannelRedisQueueEnum.WECHAT_PAY_GROUP.getCode(), "wepay-pay-notify-0"),
// StreamOffset.create(DragonConstant.ChannelRedisQueueEnum.WECHAT_PAY_KEY.getCode(), ReadOffset.lastConsumed()), redisPayNotifyReceiver);
// listenerContainer.start();
// return subscription;
// }
//
// @Bean
// public Subscription subscriptionWepayNotify1(RedisConnectionFactory factory) {
// var options = StreamMessageListenerContainer
// .StreamMessageListenerContainerOptions
// .builder()
// .pollTimeout(Duration.ofMillis(1))
// .build();
// var listenerContainer = StreamMessageListenerContainer.create(factory, options);
// var subscription = listenerContainer.receiveAutoAck(Consumer.from(DragonConstant.ChannelRedisQueueEnum.WECHAT_PAY_GROUP.getCode(), "wepay-pay-notify-1"),
// StreamOffset.create(DragonConstant.ChannelRedisQueueEnum.WECHAT_PAY_KEY.getCode(), ReadOffset.lastConsumed()), redisPayNotifyReceiver);
// listenerContainer.start();
// return subscription;
// }
}
//package com.liquidnet.service.dragon.controller;
//
//import com.liquidnet.commons.lang.util.StringUtil;
//import com.liquidnet.service.base.ResponseDto;
//import com.liquidnet.service.dragon.constant.DragonConstant;
//import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
//import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
//import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
//import com.liquidnet.service.dragon.service.IDragonOrdersService;
//import io.swagger.annotations.ApiImplicitParam;
//import io.swagger.annotations.ApiImplicitParams;
//import io.swagger.annotations.ApiOperation;
//import io.swagger.annotations.ApiResponse;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.*;
//
//import javax.validation.constraints.NotNull;
//import java.math.BigDecimal;
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * @author AnJiabin <anjiabin@zhengzai.tv>
// * @version V1.0
// * @Description: TODO
// * @class: PayController
// * @Package com.liquidnet.service.dragon.controller
// * @Copyright: LightNet @ Copyright (c) 2021
// * @date 2021/7/9 12:29
// */
//@Slf4j
//@RestController
//@RequestMapping("pay")
//public class PayController {
// @Autowired
// private IDragonOrdersService dragonOrdersService;
//
// /**
// * 电脑网页支付宝支付
// * @return
// */
// @PostMapping("/dragonPay")
// @ApiOperation("Dragon支付")
// @ApiResponse(code = 200, message = "接口返回对象参数")
// @ApiImplicitParams({
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "payType", value = "支付类型:alipay,wepay,iappay", example = "alipay"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "deviceFrom", value = "设备来源:web,wap,app,js,apple", example = "wap"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "type", value = "业务类型:TICKET,PRODUCT,COST,MBEANS,LIVE,VIDEO,VIP,CLUB,STRAWBERRY", example = "TICKET"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "price", value = "支付金额", example = "0.1"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "name", value = "订单名称", example = "测试订单001"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "detail", value = "订单描述", example = "测试订单001"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "orderCode", value = "订单编号", example = "ORDER0001"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "clientIp", value = "客户端ip", example = "127.0.0.1"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "notifyUrl", value = "通知url", example = "devdragon.zhengzai.tv"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "createDate", value = "订单创建时间", example = "2021-07-13 13:00:00"),
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "expireTime", value = "订单过期时间", example = "5"),
// })
// @ResponseBody
// public ResponseDto<DragonPayBaseRespDto> dragonPay(
// @RequestParam(value = "payType") @NotNull(message = "支付类型不能为空") String payType,
// @RequestParam(value = "deviceFrom") @NotNull(message = "设备来源不能为空") String deviceFrom,
// @RequestParam(value = "openId",required = false) String openId,
// @RequestParam(value = "type") @NotNull(message = "业务类型不能为空") String type,
// @RequestParam(value = "price") @NotNull(message = "支付金额不能为空") BigDecimal price,
// @RequestParam(value = "name") @NotNull(message = "订单名称不能为空") String name,
// @RequestParam(value = "detail") @NotNull(message = "订单描述不能为空") String detail,
// @RequestParam(value = "orderCode") @NotNull(message = "订单编号不能为空") String orderCode,
// @RequestParam(value = "clientIp") @NotNull(message = "客户端ip不能为空") String clientIp,
// @RequestParam(value = "notifyUrl") @NotNull(message = "通知Url不能为空") String notifyUrl,
// @RequestParam(value = "returnUrl",required = false) String returnUrl,
//// @RequestParam(value = "quitUrl",required = false) String quitUrl,
// @RequestParam(value = "showUrl",required = false) String showUrl,
//// @RequestParam(value = "code",required = false) String code,
// @RequestParam(value = "createDate",required = true) String createDate,
// @RequestParam(value = "expireTime",required = true) String expireTime){
// long startTime = System.currentTimeMillis();
// //为什么在js和applet中才需要判断open_id?
// if(payType.equalsIgnoreCase(DragonConstant.PayChannelEnum.WEPAY.getCode())){
// if(deviceFrom.equalsIgnoreCase(DragonConstant.DeviceFromEnum.JS.getCode())||deviceFrom.equalsIgnoreCase(DragonConstant.DeviceFromEnum.APPLET.getCode())) {
// if (StringUtil.isEmpty(openId)) {
// return ResponseDto.failure("微信支付openId不能为空!");
// }
// }
// }
// DragonPayBaseReqDto dragonPayBaseReqDto = DragonPayBaseReqDto.getNew();
// dragonPayBaseReqDto.setPayType(payType);
// dragonPayBaseReqDto.setDeviceFrom(deviceFrom);
// dragonPayBaseReqDto.setOpenId(openId);
// dragonPayBaseReqDto.setType(type);
// dragonPayBaseReqDto.setPrice(price);
// if(StringUtil.isNotNull(name)&&name.length()>=32){
// name = name.substring(0,32);
// }
// dragonPayBaseReqDto.setName(name);
// if(StringUtil.isNotNull(detail)&&detail.length()>=64){
// detail = detail.substring(0,64);
// }
// dragonPayBaseReqDto.setDetail(detail);
// dragonPayBaseReqDto.setOrderCode(orderCode);
// dragonPayBaseReqDto.setClientIp(clientIp);
// dragonPayBaseReqDto.setNotifyUrl(notifyUrl);
// dragonPayBaseReqDto.setReturnUrl(returnUrl);
//// dragonPayBaseReqDto.setQuitUrl(quitUrl);
// dragonPayBaseReqDto.setShowUrl(showUrl);
//// dragonPayBaseReqDto.setCode(code);
// dragonPayBaseReqDto.setCreateDate(createDate);
// dragonPayBaseReqDto.setExpireTime(expireTime);
// ResponseDto<DragonPayBaseRespDto> responseDto = dragonOrdersService.dragonPay(dragonPayBaseReqDto);
// log.info("PayController->dragonPay->总耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
// return responseDto;
// }
//
// @GetMapping("/checkOrder")
// @ApiOperation("订单查询")
// @ApiResponse(code = 200, message = "接口返回对象参数")
// @ApiImplicitParams({
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "code", value = "", example = "PAY202107131522368438531155")
// })
// @ResponseBody
// public ResponseDto<DragonPayOrderQueryRespDto> checkOrder(@RequestParam(value = "code") @NotNull(message = "支付编号不能为空!") String code){
// DragonPayOrderQueryRespDto respDto = dragonOrdersService.checkOrderStatusByCode(code);
// return ResponseDto.success(respDto);
// }
//
// @GetMapping("/manulNotify")
// @ApiOperation("手动通知商户")
// @ApiResponse(code = 200, message = "接口返回对象参数")
// @ApiImplicitParams({
// @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "code", value = "", example = "PAY202107131522368438531155")
// })
// @ResponseBody
// public ResponseDto<Map<String,String>> manulNotify(@RequestParam(value = "code") @NotNull(message = "支付编号不能为空!") String code){
// boolean respDto = dragonOrdersService.manulNotify(code);
// Map<String,String> rs = new HashMap<>();
// rs.put("code",code);
// rs.put("result",""+respDto);
// return ResponseDto.success(rs);
// }
//}
package com.liquidnet.service.dragon.controller;
import com.liquidnet.service.dragon.service.IDragonOrdersService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: PayNotifyController
* @Package com.liquidnet.service.dragon.controller
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/11 23:35
*/
@RestController
@RequestMapping("notify")
public class PayNotifyController {
@Autowired
private IDragonOrdersService dragonOrdersService;
/**
* 支付宝支付回调
* @return
*/
@PostMapping("/{payType}/{deviceFrom}")
@ApiOperation("支付宝支付回调")
@ApiResponse(code = 200, message = "接口返回对象参数")
@ApiImplicitParams({
@ApiImplicitParam(type = "form", required = true, dataType = "String", name = "payType", value = "支付类型:alipay,wepay,iappay", example = "alipay")
})
public String dragonNotify(@PathVariable("payType") String payType,@PathVariable("deviceFrom") String deviceFrom,HttpServletRequest request, HttpServletResponse respone) throws Exception {
return dragonOrdersService.dragonNotify(request,payType,deviceFrom);
}
}
package com.liquidnet.service.dragon.controller;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.dto.DragonRefundAppDto;
import com.liquidnet.service.dragon.service.IDragonOrderRefundsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Api(tags = "退款")
@RestController
@RequestMapping("refund")
public class RefundController {
@Autowired
IDragonOrderRefundsService orderRefundsService;
// @PostMapping("refundSingle")
// @ApiOperation("单条退款")
// @ApiResponse(code = 200, message = "接口返回对象参数")
// public ResponseDto<DragonRefundAppDto> refundSingle(@RequestParam(value = "orderCode") @NotNull(message = "订单号不能为空") String orderCode,
// @RequestParam(value = "code") @NotNull(message = "支付单能为空") String code,
// @RequestParam(value = "orderRefundCode") @NotNull(message = "退款单号不能为空") String orderRefundCode,
// @RequestParam(value = "reason") @NotNull(message = "退款原因不能为空") String reason,
// @RequestParam(value = "notifyUrl") @NotNull(message = "回调地址不能为空") String returnUrl,
// @RequestParam(value = "price") @NotNull(message = "退款价格不能为空") BigDecimal price,
// @RequestParam(value = "priceTotal") @NotNull(message = "订单价格不能为空") BigDecimal priceTotal,
// @RequestParam(value = "paymentType") @NotNull(message = "支付类型不能为空") String paymentType,
// @RequestParam(value = "paymentId") @NotNull(message = "支付订单号不能为空") String paymentId) {
// return orderRefundsService.dragonRefund(orderCode, code, orderRefundCode, reason, returnUrl, price, paymentType, paymentId, priceTotal);
// }
@PostMapping("callBack/wepay")
@ApiOperation("微信退款回调")
@ApiResponse(code = 200, message = "接口返回对象参数")
public String refundSingle(
HttpServletRequest request,
HttpServletResponse response) {
return orderRefundsService.wePayRefundCallBack(request, response);
}
}
//package com.liquidnet.service.dragon.receiver;
//
//import com.liquidnet.commons.lang.util.HttpUtil;
//import com.liquidnet.commons.lang.util.JsonUtils;
//import com.liquidnet.service.dragon.bo.PayNotifyReqBo;
//import com.liquidnet.service.dragon.dto.PayNotifyDto;
//import com.liquidnet.service.dragon.utils.MqHandleUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.redis.connection.stream.MapRecord;
//import org.springframework.data.redis.stream.StreamListener;
//import org.springframework.stereotype.Component;
//import org.springframework.util.LinkedMultiValueMap;
//import org.springframework.util.MultiValueMap;
//
//import java.time.LocalDateTime;
//
///**
// * 支付回调通知商户
// */
//@Slf4j
//@Component
//public class RedisPayNotifyReceiver implements StreamListener<String, MapRecord<String, String, String>> {
//
// @Autowired
// private MqHandleUtil mqHandleUtil;
// @Override
// public void onMessage(MapRecord<String, String, String> message) {
// log.info("接受到来自redis notify 的消息");
// log.info("message id "+message.getId());
// log.info("stream "+message.getStream());
// log.info("body "+message.getValue());
// this.sendNotify(message.getValue().get("message"));
// }
//
// private void sendNotify(String message){
// PayNotifyReqBo payNotifyReqBo = JsonUtils.fromJson(message, PayNotifyReqBo.class);
// PayNotifyDto payNotifyDto = payNotifyReqBo.getPayNotifyDto();
// LocalDateTime nowTime = LocalDateTime.now();
// MultiValueMap<String, String> params = new LinkedMultiValueMap();
// params.add("status", payNotifyDto.getStatus().toString());
// params.add("type", payNotifyDto.getType());
// params.add("code", payNotifyDto.getCode());
// params.add("paymentId", payNotifyDto.getPaymentId());
// params.add("orderCode", payNotifyDto.getOrderCode());
// params.add("price", payNotifyDto.getPrice().toString());
// params.add("paymentType", payNotifyDto.getPaymentType());
// String response = HttpUtil.post(payNotifyReqBo.getNotifyUrl(), params);
// log.debug("PAY RESPONSE=" + response);
// if (response.equals("success")) {
//// MqHandleUtilsendMySqlRedis(
//// SqlMapping.get("dragon_order_pay.update"),
//// new Object[]{nowTime, DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime), DragonConstant.RefundStatusEnum.STATUS_SUCCESS.getCode(), notifyUrlDto.getRefundCode()}
//// );
// } else {
//// sendMySqlRedis(
//// SqlMapping.get("dragon_order_pay.update"),
//// new Object[]{nowTime, DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime), DragonConstant.RefundStatusEnum.STATUS_FAIL.getCode(), notifyUrlDto.getRefundCode()}
//// );
// }
// }
//}
package com.liquidnet.service.dragon.receiver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisPayReceiver implements StreamListener<String, MapRecord<String, String, String>> {
@Override
public void onMessage(MapRecord<String, String, String> message) {
log.info("接受到来自redis PAY 的消息");
System.out.println("message id "+message.getId());
System.out.println("stream "+message.getStream());
System.out.println("body "+message.getValue());
}
}
package com.liquidnet.service.dragon.receiver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.stream.StreamListener;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class RedisRefundReceiver implements StreamListener<String, MapRecord<String, String, String>> {
@Override
public void onMessage(MapRecord<String, String, String> message) {
log.info("接受到来自redis REFUND 的消息");
System.out.println("message id "+message.getId());
System.out.println("stream "+message.getStream());
System.out.println("body "+message.getValue());
}
}
package com.liquidnet.service.dragon.service.impl;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.dragon.channel.strategy.PayChannelStrategyContext;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseReqDto;
import com.liquidnet.service.dragon.dto.DragonPayBaseRespDto;
import com.liquidnet.service.dragon.dto.DragonPayOrderQueryRespDto;
import com.liquidnet.service.dragon.service.IDragonOrdersService;
import com.liquidnet.service.dragon.utils.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@Service
public class DragonOrdersServiceImpl implements IDragonOrdersService {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
private PayChannelStrategyContext payChannelStrategyContext;
@Autowired
private DataUtils dataUtils;
@Autowired
private DragonPayBiz dragonPayBiz;
@Override
public ResponseDto<DragonPayBaseRespDto> dragonPay(DragonPayBaseReqDto dragonPayBaseReqDto) {
//设置支付编号
dragonPayBaseReqDto.setCode(IDGenerator.payCode());
log.info("dragon:dragonPay:req:dragonPayBaseReqDto : {}",dragonPayBaseReqDto.toString());
return payChannelStrategyContext.getStrategy(dragonPayBaseReqDto.getPayType()).dragonPay(dragonPayBaseReqDto);
}
@Override
public String dragonNotify(HttpServletRequest request,String payType,String deviceFrom) {
return payChannelStrategyContext.getStrategy(payType).dragonNotify(request,payType,deviceFrom);
}
@Override
public DragonPayOrderQueryRespDto checkOrderStatusByCode(String code) {
DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
if(StringUtil.isEmpty(ordersDto)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//如果已支付 直接返回结果
if(!ordersDto.getStatus().toString().equals(DragonConstant.PayStatusEnum.STATUS_UNPAID.getCode())){
return dragonPayBiz.buildPayOrderQueryRespDto(ordersDto);
}
//如果未支付进行三方查询
String payType = DragonConstant.PayTypeEnum.getEnumByCode(ordersDto.getPaymentType()).getPayType();
return payChannelStrategyContext.getStrategy(payType).checkOrderStatus(code);
}
@Override
public boolean manulNotify(String code) {
DragonOrdersDto ordersDto = dataUtils.getPayOrderByCode(code);
if(StringUtil.isEmpty(ordersDto)){
throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getCode(),DragonErrorCodeEnum.TRADE_ERROR_NOT_EXISTS.getMessage());
}
//通知商户
return dragonPayBiz.sendNotify(dragonPayBiz.buildPayNotifyReqBo(ordersDto));
}
}
package com.liquidnet.service.dragon.utils;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.dto.DragonOrdersDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class DataUtils {
@Autowired
private RedisUtil redisUtil;
private long keyExpireTime = 3600*24*7;
public void createPayOrder(String code, DragonOrdersDto ordersDto) {
redisUtil.set(DragonConstant.REDIS_KET_PAY_CODE + code, ordersDto,keyExpireTime);
}
public DragonOrdersDto getPayOrderByCode(String code) {
Object obj = redisUtil.get(DragonConstant.REDIS_KET_PAY_CODE + code);
if(obj!=null){
return (DragonOrdersDto) obj;
}
return null;
}
public void updateOrderStatus(String code, DragonOrdersDto dragonOrdersDto) {
redisUtil.set(DragonConstant.REDIS_KET_PAY_CODE + code, dragonOrdersDto,keyExpireTime);
}
public void setRefundNotifyUrl(String code, String notifyUrl) {
redisUtil.set(DragonConstant.REFUND_REDIS_KET + code, notifyUrl,keyExpireTime);
}
public String getRefundNotifyUrl(String code) {
return (String) redisUtil.get(DragonConstant.REFUND_REDIS_KET + code);
}
}
package com.liquidnet.service.dragon.utils;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.dragon.bo.PayNotifyReqBo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.LinkedList;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: MqHandleUtil
* @Package com.liquidnet.service.dragon.utils
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/10 16:23
*/
@Component
public class MqHandleUtil {
@Autowired
StringRedisTemplate stringRedisTemplate;
/**
* REDIS 队列发送消息 通知商户相关
* @param payNotifyReqBo
* @return
*/
public boolean sendNotifyErrorQueue(PayNotifyReqBo payNotifyReqBo,String queueKey) {
try {
HashMap<String, String> map = ObjectUtil.cloneHashMapStringAndString();
map.put("message", payNotifyReqBo.toString());
MapRecord<String, String, String> record = StreamRecords.mapBacked(map).withStreamKey(queueKey);
stringRedisTemplate.opsForStream().add(record);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 给 REDIS 队列发送消息 数据库相关
*
* @param sql sql语句
* @param data 需要操作的数据
* @return
*/
public boolean sendMySqlRedis(String sql, Object[] data , String redisKey) {
try {
LinkedList<String> sqls = ObjectUtil.cloneLinkedListStr();
sqls.add(sql);
LinkedList<Object[]> sqlsData = ObjectUtil.cloneLinkedListObj();
sqlsData.add(data);
String sqlData = SqlMapping.gets(sqls, sqlsData);
HashMap<String, String> map = ObjectUtil.cloneHashMapStringAndString();
map.put("message", sqlData);
MapRecord<String, String, String> record = StreamRecords.mapBacked(map).withStreamKey(redisKey);
stringRedisTemplate.opsForStream().add(record);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
package com.liquidnet.service.dragon.utils;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: ObjectUtil
* @Package com.liquidnet.service.dragon.utils
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/21 16:00
*/
@Component
public class ObjectUtil {
private static final LinkedList<Object[]> linkedListObj = new LinkedList<Object[]>();
private static final LinkedList<String> linkedListStr = new LinkedList<String>();
private static final HashMap<String, String> hashMapStringAndString = new HashMap<>();
private static final HashMap<String, Object> hashMapStringAndObj = new HashMap<>();
private static final AlipayTradeWapPayRequest alipayTradeWapPayRequest = new AlipayTradeWapPayRequest();
private static final JSONObject jsonObjectObj = new JSONObject();
public static LinkedList<Object[]> cloneLinkedListObj() {
return (LinkedList<Object[]>) linkedListObj.clone();
}
public static LinkedList<String> cloneLinkedListStr() {
return (LinkedList<String>) linkedListStr.clone();
}
public static HashMap<String, String> cloneHashMapStringAndString() {
return (HashMap<String, String>) hashMapStringAndString.clone();
}
public static HashMap<String, Object> cloneHashMapStringAndObj() {
return (HashMap<String, Object>) hashMapStringAndObj.clone();
}
public static AlipayTradeWapPayRequest cloneAlipayTradeWapPayRequest() {
return alipayTradeWapPayRequest;
}
public static JSONObject cloneJsonObjectObj() {
return (JSONObject) jsonObjectObj.clone();
}
}
package com.liquidnet.service.dragon.utils;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.FileInputStream;
import java.net.URL;
import java.security.PrivateKey;
public class PayAlipayUtils {
private static PayAlipayUtils instance = new PayAlipayUtils();
private AlipayClient httpClient = null;
private final String appId = "2019082866535131";
private final String merchant_pub_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmePaETscydypY3rV4mXa8MtcQIL5zjP1KxdusNkHpePeU61hAZxKn0Z8pDB1wNaTK72wgEWaORXeRp4YTbf4usHlW562Pe5wdiSutb3iT6EMJ5eBD4HLI9wWDgYBtwfHwS5JJFhf0eptP4R1XluLiMhmMynLwJvHepgkVrS3mN+jmoPRmKFhZHGIYDoWypBMbUKiFHWiToHK1n0NYHHIi4WgK2wt4Wj7nexQGD69W7ofRCirYmz35c/cNFUA1lqzOEKu2z7PpjA6jQV2GJolnJ4xXPJ8Dpgp4g/dgsGqRydlmFqZD71i/pDDpF0RfRKHL+WhWVhI1hqe6jLtvJE+zQIDAQAB";
private final String merchant_private_key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCArhnBTpcAww8wSYBTwGp6oBvenzCCYFrugERgxJDZ7YnBZ3ZdiAaHjJ9PI0WymkpDr27FSg9czVbiH7G91zPq+8s9onrZi/l6cBZ2VjrwQ9BQPN2a8zHy8D6BfoKEV+PIicGz6hNPA7lgf04NgsXeWjeXnYD/IBTLZmnCxB2sPYo/0EN32mlSG9snO63HlPkoqn8ycw71a1cBrlQ+Y22fFnJAk/vrGoou8E0UHfL5zVE/up+ToOYW/eOKMFL/DSceCy32t9Za0RmpV3i2E9s8gBDewzT10Yf4+4mPUiTR6AhcLjqafAy2IaKPK57WZ6cGF9cGs9yq8bSTRpeNC4alAgMBAAECggEAH0Ms+qvPP94j6IVS6gYLWHNhkfp23JXwQZVkB2Z6EpgFKbmrJhoQDAp8Acv9+OBHPp52ePP/O3qfqxwsIIUSFfrKa9T3p7a8C6UDsAhPFWRETdobtLN05SK87NUBfImly2i8aKtruXycIveKzPmCfPzKGMmpN1Jh+vCMrUbcNqX8OUcxmhGvJwnQuBW4QEiepzl89Nl91iSwFmxaZoqLaB9lYUKke/z7FDHTpTWpZvtvxlZ0gvMVNLVp9NBNazolQ8eEjBG2PsQGD2cLUbM33mLTz+/VQjzZR3KXu5kQR9MloURILDsdxE1AyA4AkIXd4eMszEjA4Dv6CQK/jjrsgQKBgQDIiCt1OGmV2sqDBSn4nZNH7BzY3Hdnf+qsYUi+TXKhnQaT8XPKWZpKE/AcqsIKnANmO4sX0NL7ACBe7Rl1RcU9Mq5XuHhnkveFBVRRIHindzUfEN0WgdLy23qmJ2N+1i4FigelY0E5T2lojVb7wycAgAc6vflwE+eYf8W3968q0QKBgQCkRgsVCWWNMSLZeB0V9LV3Om2/UPWY/ovadTxAQtxg0Z75V6Wdu8u0hrYaPSeUK2ryaoE6HKgp7U8NiJGzgm2wpj7D2ysrPmhX5+CjiWkDMCuvWytVT7hLqhhLp7frZT39u8VhyfC8lE0xA67gAPsGSl1sBoZPwvvsmNAQ/h6rlQKBgQCtCtw9be2m88M3JnieYhOax8Po2u5qsLZoBBcKqLhXf7ISbhPWNFXwwJ29jxicoR5J1O3lIj09fVFxuLX0Pb3DXn2VksjLz8Wp0vx8eUHEeRis8xdleaf4C68du/WemOHjw8VvUWQSOVWjc/vwiumYA+K5LQAXWAXM0c1jP+e3UQKBgEWY/1z8TDATn0Yvo3MH6FIJSTIDJOqa/bmibdJ0AVZruUS+o4Y+aEGlyUU4n6og8wCdqv5p4b1Rs2pyb/hzy/FJndHw60s495A2x2/B6eHV6Mw0fhl42wYDnKOA/WUX0bnMcgXKPtpGoqWff9mb0L6LhyUbZpAodf95hr2MTIY5AoGBAIyPtYP6jRyR980h/Ud1MS0fBxymjQrR+kg3GWjnw0ZJJ8yFEXxDqLV8uLyXQKc89HGbI0cClWgZBTjfIPJ5U4Gl19Xlwx1SFrdgg5mGUqnMARTg7w1TG5QLSqNhZo2jgBM5FCJRbDUCO/MzLcFhTeGNva9yP7E7gW5/Dott9D7d";
private final String sign_type = "RSA2";
private final String charset = "utf-8";
private final String gatewayUrl = "https://openapi.alipay.com/gateway.do";
public PayAlipayUtils() {
}
public static PayAlipayUtils getInstance() {
return instance;
}
public AlipayClient getHttpClient() {
if(httpClient == null){
httpClient = new DefaultAlipayClient(gatewayUrl, appId, merchant_private_key, "json", charset,
merchant_pub_key, sign_type);
}
return httpClient;
}
}
package com.liquidnet.service.dragon.utils;
import com.alipay.api.internal.util.file.IOUtils;
import com.liquidnet.commons.lang.util.MD5Utils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.Security;
import java.util.*;
public class PayWepayUtils {
private CloseableHttpClient httpClient;
private static PayWepayUtils instance = new PayWepayUtils();
private final String merchantId = "1551961491";
private final String partnerKey = "itIuO65O9yKmemOu3S8g1S4orqvCGwXK";
private final String APP_ID="wx86f9777acf2cb585";
private final String WEB_APP_ID="wx3498304dda39c5a1";
private final String JS_APP_ID="wx3498304dda39c5a1";
private final String WAP_APP_ID="wx3498304dda39c5a1";
private final String APPLET_APP_ID="wx4732efeaa2b08086";
public PayWepayUtils() {
}
public static PayWepayUtils getInstance() {
return instance;
}
public String getAPP_ID() {
return APP_ID;
}
public String getAPPLET_APP_ID() {
return APPLET_APP_ID;
}
public String getJS_APP_ID() {
return JS_APP_ID;
}
public String getWEB_APP_ID() {
return WEB_APP_ID;
}
public String getWAP_APP_ID() {
return WAP_APP_ID;
}
public String getMerchantId() {
return merchantId;
}
public CloseableHttpClient getHttpClient() {
try {
if (httpClient == null) {
InputStream certStream = PayWepayUtils.class.getClassLoader().getResourceAsStream("payCert/wepay/wepay_apiclient_cert.p12");
byte[] certData = IOUtils.toByteArray(certStream);
certStream.read(certData);
certStream.close();
KeyStore keyStore = KeyStore.getInstance("PKCS12");
ByteArrayInputStream inputStream = new ByteArrayInputStream(certData);
try {
keyStore.load(inputStream, merchantId.toCharArray());
} finally {
inputStream.close();
}
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, merchantId.toCharArray())
.build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
}
} catch (Exception e) {
e.printStackTrace();
}
return httpClient;
}
//生成随机字符串nonce_str
public String getNonceStr() {
String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 32; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
public String createSign(SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + partnerKey);
return MD5Utils.md5(sb.toString()).toUpperCase();
}
public String getRequestXml(SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
public String unCodeReqInfo(String reqInfo) {
try {
Cipher cipher ;
String key = MD5Utils.md5(partnerKey);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
Security.addProvider(new BouncyCastleProvider());
cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
Base64.Decoder decoder = Base64.getDecoder();
byte[] base64ByteArr = decoder.decode(reqInfo);
String result = new String(cipher.doFinal(base64ByteArr));
return result;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(InputStream inputStream) throws Exception {
if (inputStream == null) {
return null;
}
Map<String, String> map = new HashMap<String, String>();// 将解析结果存储在HashMap中
SAXReader reader = new SAXReader();// 读取输入流
Document document = reader.read(inputStream);
Element root = document.getRootElement();// 得到xml根元素
List<Element> elementList = root.elements();// 得到根元素的所有子节点
for (Element e : elementList) { // 遍历所有子节点
map.put(e.getName(), e.getText());
}
inputStream.close(); // 释放资源
inputStream = null;
return map;
}
public String getPartnerKey() {
return this.partnerKey;
}
public boolean notifySign(Map<String, String> result, String sign) {
String argNotifySign = getStringByStringMap(result) + "&key=" + this.partnerKey;
String notifySign = MD5Utils.md5(argNotifySign).toUpperCase();
if (notifySign.equals(sign)) {
return true;
} else {
return false;
}
}
public static String getStringByStringMap(Map<String, String> map) {
SortedMap<String, Object> smap = new TreeMap<String, Object>(map);
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, Object> m : smap.entrySet()) {
sb.append(m.getKey()).append("=").append(m.getValue()).append("&");
}
sb.delete(sb.length() - 1, sb.length());
return sb.toString();
}
public static void main(String[] args) {
SortedMap<String, Object> paramMap = new TreeMap<String, Object>();
paramMap.put("appid", "wx86f9777acf2cb585");
paramMap.put("partnerid", "1551961491");
paramMap.put("prepayid", "wx26131443671359787bb3996a1fa0fc0000");
paramMap.put("package", "Sign=WXPay");
paramMap.put("noncestr", "rGcsOnNdZ4d9zu6k3yCbVJRG8Ombp8VW");
paramMap.put("timestamp", "1627276483");
String sign = PayWepayUtils.getInstance().createSign(paramMap);
System.out.println("1627274771===="+sign);
}
}
package com.liquidnet.service.dragon.utils;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: XmlUtil
* @Package com.liquidnet.service.dragon.utils
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/12 11:15
*/
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 输出xml和解析xml的工具类
*@ClassName:XmlUtil
*/
@Slf4j
public class XmlUtil{
/**
* java 转换成xml
* @Title: toXml
* @Description: TODO
* @param obj 对象实例
* @return String xml字符串
*/
public static String toXml(Object obj){
XStream xstream=new XStream();
// XStream xstream=new XStream(new DomDriver()); //直接用jaxp dom来解释
// XStream xstream=new XStream(new DomDriver("utf-8")); //指定编码解析器,直接用jaxp dom来解释
XStream.setupDefaultSecurity(xstream);
////如果没有这句,xml中的根元素会是<包.类名>;或者说:注解根本就没生效,所以的元素名就是类的属性
xstream.processAnnotations(obj.getClass()); //通过注解方式的,一定要有这句话
xstream.allowTypesByRegExp(new String[] { ".*" });
// xstream.allowTypes(new Class[]{XmlUtil.class});
// xstream.allowTypesByWildcard(new String[] {
// "com.liquidnet.**"
// });
return xstream.toXML(obj);
}
/**
* 将传入xml文本转换成Java对象
* @Title: toBean
* @Description: TODO
* @param xmlStr
* @param cls xml对应的class类
* @return T xml对应的class类的实例对象
*
* 调用的方法实例:PersonBean person=XmlUtil.toBean(xmlStr, PersonBean.class);
*/
public static <T> T toBean(String xmlStr,Class<T> cls){
//注意:不是new Xstream(); 否则报错:java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserFactory
XStream xstream=new XStream(new DomDriver());
xstream.processAnnotations(cls);
T obj=(T)xstream.fromXML(xmlStr);
return obj;
}
/**
* 写到xml文件中去
* @Title: writeXMLFile
* @Description: TODO
* @param obj 对象
* @param absPath 绝对路径
* @param fileName 文件名
* @return boolean
*/
public static boolean toXMLFile(Object obj, String absPath, String fileName ){
String strXml = toXml(obj);
String filePath = absPath + fileName;
File file = new File(filePath);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
log.error("创建{"+ filePath +"}文件失败!!!" + e);
return false ;
}
}// end if
OutputStream ous = null ;
try {
ous = new FileOutputStream(file);
ous.write(strXml.getBytes());
ous.flush();
} catch (Exception e1) {
log.error("写{"+ filePath +"}文件失败!!!" + e1);
return false;
}finally{
if(ous != null )
try {
ous.close();
} catch (IOException e) {
log.error("写{"+ filePath +"}文件关闭输出流异常!!!" + e);
}
}
return true ;
}
public static Map<String, Object> xmlToMap(String xmlDoc) throws DocumentException {
// 创建一个新的字符串
StringReader read = new StringReader(xmlDoc);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXReader saxReader = new SAXReader();
Map<String, Object> xmlMap = new HashMap<String, Object>();
Document doc = saxReader.read(source); // 通过输入源构造一个Document
Element root = doc.getRootElement(); // 取的根元素
List<Element> elements = root.elements(); // 得到根元素所有子元素的集合(根元素的子节点,不包括孙子节点)
for (Element et : elements) {
xmlMap.put(et.getName(), et.getText());
}
return xmlMap;
}
// /**
// * 从xml文件读取报文
// * @Title: toBeanFromFile
// * @Description: TODO
// * @param absPath 绝对路径
// * @param fileName 文件名
// * @param cls
// * @throws Exception
// * @return T
// */
// public static <T> T toBeanFromFile(String absPath, String fileName,Class<T> cls) throws Exception{
// String filePath = absPath +fileName;
// InputStream ins = null ;
// try {
// ins = new FileInputStream(new File(filePath ));
// } catch (Exception e) {
// throw new Exception("读{"+ filePath +"}文件失败!", e);
// }
//
// String encode = useEncode(cls);
// XStream xstream=new XStream(new DomDriver(encode));
// xstream.processAnnotations(cls);
// T obj =null;
// try {
// obj = (T)xstream.fromXML(ins);
// } catch (Exception e) {
// // TODO Auto-generated catch block
// throw new Exception("解析{"+ filePath +"}文件失败!",e);
// }
// if(ins != null)
// ins.close();
// return obj;
// }
}
\ No newline at end of file
# begin-dev-这里是配置信息基本值
liquidnet:
cloudConfig:
profile: dev
security:
username: user
password: user123
eureka:
host: 127.0.0.1:7001
# end-dev-这里是配置信息基本值
spring:
profiles:
include: service-notify
# begin-dev-这里是配置信息基本值
liquidnet:
cloudConfig:
profile: prod
security:
username: user
password: user123
eureka:
host: 172.17.207.189:7001
# end-dev-这里是配置信息基本值
spring:
profiles:
include: service-notify
#eurekaServer配置
eureka:
client:
register-with-eureka: true
fetch-registry: true
serviceUrl:
defaultZone: http://${liquidnet.security.username}:${liquidnet.security.password}@${liquidnet.eureka.host}/eureka-server/eureka
#configServer配置
spring:
cloud:
config:
# uri: http://39.105.38.151:7002/support-config
# uri: http://39.106.122.201:7002/support-config
# uri: http://127.0.0.1:7002/support-config
profile: ${liquidnet.cloudConfig.profile}
name: ${spring.application.name} #默认为spring.application.name
discovery:
enabled: true
service-id: liquidnet-support-config
# begin-dev-这里是配置信息基本值
liquidnet:
cloudConfig:
profile: test
security:
username: user
password: user123
eureka:
host: 172.17.207.177:7001
# end-dev-这里是配置信息基本值
spring:
profiles:
include: service-notify
spring:
application:
name: liquidnet-service-notify
profiles:
active: dev
server:
tomcat:
max-threads: 2000
min-spare-threads: 200
max-connections: 20000
connection-timeout: 5000
-----BEGIN CERTIFICATE-----
MIID+TCCAuGgAwIBAgIUbSXsyBnq4LzqfbGPFD8HUkMdkpUwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMTkwODIxMDczOTE3WhcNMjQwODE5MDczOTE3WjCBijETMBEGA1UEAwwK
MTU1MTk2MTQ5MTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTYwNAYDVQQL
DC3ljJfkuqzmraPlnKjmmKDnlLvkupLogZTnvZHnp5HmioDmnInpmZDlhazlj7gx
CzAJBgNVBAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAO+ZZzoLW7wEFuwFSHnBYpBi0QHcs4aCgIO7GaAxdztA
KDFsuUuu45GX5rla4O9QfeW9xut9jT6LlEIAPXczZ8Ne3b/xf/kOErGAuaCjHkO1
m4EOf8H/y4uu7Dwgousmf51HDvPFjpkk8QMJ1sf4CTQFIzeXFHXAuBxvt16OdQnJ
LDUz/XuuZTqWUROuPfJh8FV/PhfA3ZRKT5qa4EuGSamesR/tYH0+TYzBYkSTdCHd
PxTrhTAn4UUluWBCB1juK7cgB6Gv2lq8gTVVB/N1QNHBxJ8GKNPDiHHNBEI97KGr
nFHl4uYhtPxXB19PB9B/Io3ITiHIWmFGgnJHqa1myOcCAwEAAaOBgTB/MAkGA1Ud
EwQCMAAwCwYDVR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNh
Lml0cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0
QjA2QUQzOTc1NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEAfWQf
0u9iwj/7Om0GxQZgcZ2xdzn3b2M6ftAFJA66XnOsq3OVCIYu36OEt7AVJanfHFp0
dDKijvhrWgkwxVnzuuDZ4+GHfKa3z6r+XkDoaKv/1MPa9X8HMtrFSNCBiYiRzSBQ
nJrYBt05NbVkG68nnpfHqTnE5ffRNQz0dvOGZBf9ddx52wTbkO9OMlYWlcSZWT6E
grhOVeuwmL6MX+0kpNs8BGAOQbSZXJNfdvl/L2NgwGaL3sTR7HzDegwkq6lhdgfN
WQCQP43tRm7fM69viPZjlwi/Dt3hVlq7p8vuur+n5pPRR4EhC01CzbQQ2MMZC1bi
z4iu9HJAOme5K9M2Nw==
-----END CERTIFICATE-----
# ------------------------创建退款订单----------------------------
dragon_order_refund.insert=INSERT INTO `dragon_order_refunds`(`order_refund_id`,`code` ,`order_refund_code` ,`price` ,`reason` ,`notify_url` ,`refund_type`,`created_at`,`updated_at`)VALUES(?,?,?,?,?,?,?,?,?);
# ------------------------修改退款订单----------------------------
dragon_order_refund_error.update=UPDATE `dragon_order_refunds` SET updated_at = ? , refund_error=? , status=? WHERE order_refund_code = ?
dragon_order_refund_success.update=UPDATE `dragon_order_refunds` SET updated_at = ? , refund_at=? , status=? WHERE order_refund_code = ?
dragon_order_refund_call_back.update=UPDATE `dragon_order_refunds` SET updated_at = ? , finished_at=? , status=? WHERE order_refund_code = ?
# ------------------------创建退款订单日志----------------------------
dragon_order_refund_log.insert=INSERT INTO `dragon_order_refund_logs`(`order_refund_id` ,`refund_type` ,`content`,`created_at`,`updated_at`)VALUES(?,?,?,?,?);
dragon_orders.insert=insert into dragon_orders(order_id, status, code, type, price, name, detail, order_code, client_ip, notify_url,notify_status, payment_type, payment_id, payment_at, finished_at, created_at, updated_at, deleted_at) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
dragon_order_logs.insert=insert into dragon_order_logs(code, payment_type, content, created_at, updated_at, deleted_at) values(?,?,?,?,?,?)
dragon_pay_notify.insert=insert into dragon_pay_notify (code, order_code, notify_url, notify_data, created_at, updated_at) values(?,?,?,?,?,?)
dragon_pay_notify_fail.insert=insert into dragon_pay_notify_fail (code, order_code, notify_url, notify_data, fail_desc, created_at, updated_at) values(?,?,?,?,?,?,?)
dragon_orders.updateOrderStatus=update dragon_orders t set t.status = ? ,t.payment_id = ?,t.finished_at = ?,t.updated_at =? where t.code = ?
dragon_orders.updateNotifyStatus=update dragon_orders t set t.notify_status = ? ,t.updated_at =? where t.code = ?
This diff is collapsed.
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
<module>liquidnet-service-order</module> <module>liquidnet-service-order</module>
<module>liquidnet-service-platform</module> <module>liquidnet-service-platform</module>
<module>liquidnet-service-dragon</module> <module>liquidnet-service-dragon</module>
<module>liquidnet-service-notify</module>
<module>liquidnet-service-executor-all</module> <module>liquidnet-service-executor-all</module>
<module>liquidnet-service-consumer-all</module> <module>liquidnet-service-consumer-all</module>
<module>liquidnet-service-sweet</module> <module>liquidnet-service-sweet</module>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment