This commit is contained in:
N1KO 2024-12-27 10:00:52 +08:00
parent 672e8cd033
commit da59e62ef4
23 changed files with 782 additions and 10 deletions

View File

@ -2,18 +2,25 @@
FROM maven:3.8.4-openjdk-11-slim AS builder
WORKDIR /app
# 1. 将本地项目所有内容拷贝到容器中 (包含pom.xml、src等)
COPY . .
# 使用 Maven 在容器中进行编译和打包(根据需要决定是否跳过测试)
# 2. 使用 Maven 在容器中进行编译和打包(如果需要测试可去掉 -DskipTests
RUN mvn clean package -DskipTests
# ------------------------------------
# 第二阶段:使用精简的 OpenJDK 11 镜像作为运行时环境
FROM openjdk:11-jre-slim
WORKDIR /app
# 从构建阶段复制打包好的 jar 文件到运行阶段
# 3. 从构建阶段复制打包好的 jar 文件到运行阶段
COPY --from=builder /app/target/baogutang-music-1.0-SNAPSHOT.jar /app/app.jar
# 若应用在 8080 端口监听,这里进行暴露
# 4. (可选) 复制证书文件到容器中。如果你的证书在项目根目录 certs/ 下,就这样写:
COPY src/main/resources/alipay/prod /usr/local/certs/baogutang/alipay/prod
# 若应用在 8105 端口监听,这里进行暴露
EXPOSE 8105
# 运行应用

View File

@ -107,6 +107,13 @@
<artifactId>httpclient</artifactId>
</dependency>
<!--IJPay-AliPay-->
<dependency>
<groupId>com.github.javen205</groupId>
<artifactId>IJPay-AliPay</artifactId>
<version>2.9.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@ -0,0 +1,60 @@
package top.baogutang.music.aspect;
import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.baogutang.music.enums.PayChannel;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 16:21
*/
@Slf4j
@Aspect
@Component
public class PayAspect {
@Resource
private AliPayApiConfig aliPayApiConfig;
@Pointcut("execution(* top.baogutang.music.controller.OrderController.*(..))")
public void payPointCut() {
// PointCut
}
@Around("payPointCut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
Object result;
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
assert sra != null;
HttpServletRequest request = sra.getRequest();
PayChannel payChannel = PayChannel.getPayChannel(request.getParameter("payChannel"));
if (Objects.equals(PayChannel.ALI_PAY, payChannel)) {
AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig);
}
try {
result = pjp.proceed();
} finally {
AliPayApiConfigKit.removeThreadLocalAppId();
}
return result;
}
}

View File

@ -0,0 +1,67 @@
package top.baogutang.music.client;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.ijpay.alipay.AliPayApi;
import lombok.extern.slf4j.Slf4j;
import top.baogutang.music.dao.entity.OrderEntity;
import top.baogutang.music.domain.res.pay.OrderRes;
import top.baogutang.music.enums.PayChannel;
import top.baogutang.music.service.IOrderService;
import top.baogutang.music.service.IPayService;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 13:50
*/
@Slf4j
public abstract class AbstractOrderClient {
@Resource
private IPayService payService;
@Resource
private IOrderService orderService;
public abstract PayChannel getPayChannel();
public abstract BigDecimal getAmount();
public abstract String getNotifyUrl();
public OrderRes order(Long userId) {
// 1.创建订单
OrderEntity order = orderService.createOrder(userId, getPayChannel(), getAmount());
// 2.支付
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setSubject("BAOGUTANGMUSIC");
model.setTotalAmount(order.getAmount().toString());
model.setStoreId("BAOGUTANGMUSIC");
model.setTimeoutExpress("10m");
model.setOutTradeNo(order.getOrderNo());
model.setProductCode("QR_CODE_OFFLINE");
String qrCode;
try {
String resultStr = AliPayApi.tradePrecreatePayToResponse(model, getNotifyUrl())
.getBody();
JSONObject jsonObject = JSON.parseObject(resultStr);
qrCode = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
} catch (Exception e) {
log.error("预下单失败:{}", e.getMessage(), e);
return null;
}
OrderRes orderRes = new OrderRes();
orderRes.setQrCode(qrCode);
orderRes.setUserId(userId);
orderRes.setOrderId(order.getId());
orderRes.setOrderNo(order.getOrderNo());
return orderRes;
}
}

View File

@ -0,0 +1,39 @@
package top.baogutang.music.client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import top.baogutang.music.enums.PayChannel;
import top.baogutang.music.properties.AliPayConfigProperties;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 13:50
*/
@Slf4j
@Service
public class AliPayClient extends AbstractOrderClient {
@Resource
private AliPayConfigProperties aliPayConfigProperties;
@Override
public PayChannel getPayChannel() {
return PayChannel.ALI_PAY;
}
@Override
public BigDecimal getAmount() {
return aliPayConfigProperties.getPayAmount();
}
@Override
public String getNotifyUrl() {
return aliPayConfigProperties.getCallbackUrl();
}
}

View File

@ -0,0 +1,51 @@
package top.baogutang.music.config;
import com.alipay.api.AlipayApiException;
import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.baogutang.music.properties.AliPayConfigProperties;
import javax.annotation.Resource;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 11:00
*/
@Slf4j
@Configuration
public class AliPayConfig {
@Resource
private AliPayConfigProperties aliPayConfigProperties;
@Bean
public AliPayApiConfig aliPayApiConfig() throws AlipayApiException {
log.info(">>>>>>>>>>alipay api config init start<<<<<<<<<<");
AliPayApiConfig aliPayApiConfig;
try {
aliPayApiConfig = AliPayApiConfigKit.getApiConfig(aliPayConfigProperties.getAppId());
} catch (Exception e) {
aliPayApiConfig = AliPayApiConfig.builder()
.setAppId(aliPayConfigProperties.getAppId())
.setServiceUrl(aliPayConfigProperties.getServerUrl())
.setPrivateKey(aliPayConfigProperties.getPrivateKey())
.setAliPayPublicKey(aliPayConfigProperties.getPublicKey())
.setAppCertPath(aliPayConfigProperties.getAppCertPath())
.setAliPayCertPath(aliPayConfigProperties.getAliPayCertPath())
.setAliPayRootCertPath(aliPayConfigProperties.getAliPayRootCertPath())
.setCharset("UTF-8")
.setSignType("RSA2")
// 证书模式
.buildByCert();
}
log.info(">>>>>>>>>>alipay api config init success<<<<<<<<<<");
return aliPayApiConfig;
}
}

View File

@ -0,0 +1,50 @@
package top.baogutang.music.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ijpay.alipay.AliPayApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import top.baogutang.music.properties.AliPayConfigProperties;
import top.baogutang.music.utils.JacksonUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/26 : 14:36
*/
@Slf4j
@Controller
@RequestMapping("/api/v1/callback")
public class CallbackController {
@Resource
private AliPayConfigProperties aliPayConfigProperties;
@RequestMapping("/alipay")
@ResponseBody
public String certNotifyUrl(HttpServletRequest request) {
try {
// 获取支付宝POST过来反馈信息
Map<String, String> params = AliPayApi.toMap(request);
log.info(">>>>>>>>>>>received callback from alipay:{}<<<<<<<<<<", JacksonUtil.toJson(params));
boolean verifyResult = AlipaySignature.rsaCertCheckV1(params, aliPayConfigProperties.getAliPayCertPath(), "UTF-8", "RSA2");
if (!verifyResult) {
log.error(">>>>>>>>>>certNotifyUrl sign check failed<<<<<<<<<<");
return "failure";
}
return "success";
} catch (AlipayApiException e) {
log.error(">>>>>>>>>>process alipay callback failed:{}<<<<<<<<<<", e.getErrMsg(), e);
return "failure";
}
}
}

View File

@ -1,20 +1,43 @@
package top.baogutang.music.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import top.baogutang.music.annos.Login;
import top.baogutang.music.domain.Results;
import top.baogutang.music.domain.res.pay.OrderRes;
import top.baogutang.music.enums.PayChannel;
import top.baogutang.music.factory.PayClientFactory;
import top.baogutang.music.utils.UserThreadLocal;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/15 : 11:52
* @date: 2024/12/25 : 13:37
*/
@Slf4j
@RestController
@RequestMapping("/api/v1/music/order")
public class OrderController {
@Resource
private PayClientFactory payClientFactory;
@Login
@GetMapping
public Results<OrderRes> order(@RequestParam(name = "payChannel") PayChannel payChannel) {
return Results.ok(payClientFactory.getClient(payChannel).order(UserThreadLocal.get()));
}
// @Login
// @PostMapping("/pcPay")
// public void webPay(@RequestParam(name = "payChannel") PayChannel payChannel,
// @RequestParam(name = "orderId") Long orderId,
// HttpServletResponse response) {
// payClientFactory.getClient(payChannel).pcPay(UserThreadLocal.get(), orderId, response);
// }
}

View File

@ -0,0 +1,36 @@
package top.baogutang.music.dao.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import top.baogutang.music.enums.OrderStatus;
import java.math.BigDecimal;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:28
*/
@Getter
@Setter
@TableName("t_order")
public class OrderEntity extends BaseEntity{
private static final long serialVersionUID = -2388686162093163854L;
private Long userId;
private String orderNo;
/**
* 三方订单号
*/
private String thirdOrderNo;
private BigDecimal amount;
private OrderStatus status;
}

View File

@ -0,0 +1,16 @@
package top.baogutang.music.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import top.baogutang.music.dao.entity.OrderEntity;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:31
*/
@Mapper
public interface OrderMapper extends BaseMapper<OrderEntity> {
}

View File

@ -0,0 +1,27 @@
package top.baogutang.music.domain.res.pay;
import lombok.Data;
import java.io.Serializable;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:14
*/
@Data
public class OrderRes implements Serializable {
private static final long serialVersionUID = 4241847954570649614L;
private Long userId;
private Long orderId;
private String orderNo;
private String qrCode;
}

View File

@ -0,0 +1,24 @@
package top.baogutang.music.enums;
import java.util.List;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:31
*/
public enum OrderStatus {
CREATED,
PAYED,
CANCELED,
;
public static List<OrderStatus> unCompletedStatus() {
return List.of(CREATED);
}
}

View File

@ -0,0 +1,28 @@
package top.baogutang.music.enums;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 13:53
*/
public enum PayChannel {
ALI_PAY,
WECHAT_PAY,
UNION_PAY,
;
public static PayChannel getPayChannel(String payChannel) {
for (PayChannel channel : PayChannel.values()) {
if (channel.name().equalsIgnoreCase(payChannel)) {
return channel;
}
}
return null;
}
}

View File

@ -0,0 +1,38 @@
package top.baogutang.music.factory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import top.baogutang.music.client.AbstractOrderClient;
import top.baogutang.music.enums.PayChannel;
import java.util.HashMap;
import java.util.Map;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 13:55
*/
@Slf4j
@Component
public class PayClientFactory implements BeanPostProcessor {
private final Map<PayChannel, AbstractOrderClient> paylClientMap = new HashMap<>();
public AbstractOrderClient getClient(PayChannel payChannel) {
return paylClientMap.get(payChannel);
}
@Override
@SuppressWarnings("unchecked")
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AbstractOrderClient) {
paylClientMap.put(((AbstractOrderClient) bean).getPayChannel(), (AbstractOrderClient) bean);
}
return bean;
}
}

View File

@ -0,0 +1,38 @@
package top.baogutang.music.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 11:05
*/
@Data
@Component
@ConfigurationProperties(prefix = "baogutang.alipay.config")
public class AliPayConfigProperties {
private String appId;
private String publicKey;
private String privateKey;
private String serverUrl;
private String appCertPath;
private String aliPayCertPath;
private String aliPayRootCertPath;
private BigDecimal payAmount;
private String callbackUrl;
}

View File

@ -0,0 +1,19 @@
package top.baogutang.music.service;
import com.baomidou.mybatisplus.extension.service.IService;
import top.baogutang.music.dao.entity.OrderEntity;
import top.baogutang.music.enums.PayChannel;
import java.math.BigDecimal;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:27
*/
public interface IOrderService extends IService<OrderEntity> {
OrderEntity createOrder(Long userId, PayChannel payChannel, BigDecimal amount);
}

View File

@ -0,0 +1,11 @@
package top.baogutang.music.service;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:19
*/
public interface IPayService {
}

View File

@ -0,0 +1,53 @@
package top.baogutang.music.service.impl;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import top.baogutang.music.dao.entity.OrderEntity;
import top.baogutang.music.dao.mapper.OrderMapper;
import top.baogutang.music.enums.OrderStatus;
import top.baogutang.music.enums.PayChannel;
import top.baogutang.music.service.IOrderService;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.UUID;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:32
*/
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements IOrderService {
@Override
public OrderEntity createOrder(Long userId, PayChannel payChannel, BigDecimal amount) {
// 1.查看当前用户是否有未完成的订单如果有则返回
OrderEntity unCompletedOrder = new LambdaQueryChainWrapper<>(baseMapper)
.eq(OrderEntity::getUserId, userId)
.in(OrderEntity::getStatus, OrderStatus.unCompletedStatus())
.eq(OrderEntity::getDeleted, false)
.last("limit 1")
.one();
if (Objects.nonNull(unCompletedOrder)) {
log.info(">>>>>>>>>>用户{}有未完成的订单{}<<<<<<<<<<", userId, unCompletedOrder.getId());
return unCompletedOrder;
}
// 2.创建订单
OrderEntity order = new OrderEntity();
order.setUserId(userId);
order.setOrderNo(UUID.randomUUID().toString().replace("-", ""));
order.setAmount(amount);
order.setStatus(OrderStatus.CREATED);
order.setCreateTime(LocalDateTime.now());
baseMapper.insert(order);
// 3.返回订单
return order;
}
}

View File

@ -0,0 +1,17 @@
package top.baogutang.music.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import top.baogutang.music.service.IPayService;
/**
*
* @description:
*
* @author: N1KO
* @date: 2024/12/25 : 15:19
*/
@Slf4j
@Service
public class PayServiceImpl implements IPayService {
}

View File

@ -0,0 +1,43 @@
-----BEGIN CERTIFICATE-----
MIIDljCCAn6gAwIBAgIQICQSJQVUjK/fpNBFS51NsDANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
YXNzIDIgUjEwHhcNMjQxMjI1MDI1NTI0WhcNMjkxMjI0MDI1NTI0WjB3MQswCQYDVQQGEwJDTjES
MBAGA1UECgwJ5ZSQ57un5p2oMQ8wDQYDVQQLDAZBbGlwYXkxQzBBBgNVBAMMOuaUr+S7mOWunSjk
uK3lm70p572R57uc5oqA5pyv5pyJ6ZmQ5YWs5Y+4LTIwODg4MDI1MTAxNTM0MzIwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQxhuQiz39iArPYwIaVk5z3vIIZ3/lCg/YyEYlcT91i2j/
Ktn8ntHV1oxvtSSQ1JZNeopIq/tuWLKZ5xmrN4s+E3u8nMOw2UeZny1517y19M5kvihEF83EvmTR
+8j6im4OrN32mnL3t4DXRDwW5wBj/CE4laMk4kpgTP8q1cpumcfuvLHFQhPlm03Xe1TnxC9uTfJd
GzPu9PZuEWJdEhyvS5w8js3I3B3aAtUUSVDpDBSV7IvuS6MeQjRd50SkQ1UinqsP7oCrGZ2uArK7
omf36kRqaKTmxKSX+MTrkKqI2nkqNE58hzjl7opOEDe+rdD8TGdzJS8uz1I/9bq0DY3ZAgMBAAGj
EjAQMA4GA1UdDwEB/wQEAwID+DANBgkqhkiG9w0BAQsFAAOCAQEAUQp0v1+7YEfmmu95KxI2EfK7
8H7/MXdl8gsE2/ULywI8LTvMq0WnZdnWrk3IT3yip/F1TRDm1/fmXP3WktK4BWkJMO2Rhv7G7rF6
vnlcWf8pp6VS50tO+mV5K0B7QiaaW89lOVcD8+bmDnxHXUTu6+klsO+i4Hvcfa059/QyUVZvJ9ou
6Nxt3lYJVK8Lk/QknfFKq/mCoxphjq1WitDZc3BxHC6QXNKKZAEv+fPMXQfol8SRO7XOQKGKPzm9
XU9KoiWa4yO2UcQjRvkejcz/OL/BqKOSo89buXWX39BEG6CNYKpVc3xRbXbedQfSXaUp0Kw9bPJO
GKRzZZsvS4r9YA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE4jCCAsqgAwIBAgIIYsSr5bKAMl8wDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU
BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw
LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy
MjE0MzQxNVoXDTM3MTEyNjE0MzQxNVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu
YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp
bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAyIFIxMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAsLMfYaoRoPRbmDcAfXPCmKf43pWRN5yTXa/KJWO0l+mrgQvs89bA
NEvbDUxlkGwycwtwi5DgBuBgVhLliXu+R9CYgr2dXs8D8Hx/gsggDcyGPLmVrDOnL+dyeauheARZ
fA3du60fwEwwbGcVIpIxPa/4n3IS/ElxQa6DNgqxh8J9Xwh7qMGl0JK9+bALuxf7B541Gr4p0WEN
G8fhgjBV4w4ut9eQLOoa1eddOUSZcy46Z7allwowwgt7b5VFfx/P1iKJ3LzBMgkCK7GZ2kiLrL7R
iqV+h482J7hkJD+ardoc6LnrHO/hIZymDxok+VH9fVeUdQa29IZKrIDVj65THQIDAQABo2MwYTAf
BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUSqHkYINtUSAtDPnS8Xoy
oP9p7qEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB
AIQ8TzFy4bVIVb8+WhHKCkKNPcJe2EZuIcqvRoi727lZTJOfYy/JzLtckyZYfEI8J0lasZ29wkTt
a1IjSo+a6XdhudU4ONVBrL70U8Kzntplw/6TBNbLFpp7taRALjUgbCOk4EoBMbeCL0GiYYsTS0mw
7xdySzmGQku4GTyqutIGPQwKxSj9iSFw1FCZqr4VP4tyXzMUgc52SzagA6i7AyLedd3tbS6lnR5B
L+W9Kx9hwT8L7WANAxQzv/jGldeuSLN8bsTxlOYlsdjmIGu/C9OWblPYGpjQQIRyvs4Cc/mNhrh+
14EQgwuemIIFDLOgcD+iISoN8CqegelNcJndFw1PDN6LkVoiHz9p7jzsge8RKay/QW6C03KNDpWZ
EUCgCUdfHfo8xKeR+LL1cfn24HKJmZt8L/aeRZwZ1jwePXFRVtiXELvgJuM/tJDIFj2KD337iV64
fWcKQ/ydDVGqfDZAdcU4hQdsrPWENwPTQPfVPq2NNLMyIH9+WKx9Ed6/WzeZmIy5ZWpX1TtTolo6
OJXQFeItMAjHxW/ZSZTok5IS3FuRhExturaInnzjYpx50a6kS34c5+c8hYq7sAtZ/CNLZmBnBCFD
aMQqT8xFZJ5uolUaSeXxg7JFY1QsYp5RKvj4SjFwCGKJ2+hPPe9UyyltxOidNtxjaknOCeBHytOr
-----END CERTIFICATE-----

View File

@ -0,0 +1,88 @@
-----BEGIN CERTIFICATE-----
MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG
EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw
MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO
UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT
V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti
W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ
MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b
53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI
pDoiVhsLwg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0
MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV
BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j
aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk
rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2
xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp
dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6
vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl
YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1
Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H
DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98
SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG
PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe
9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC
AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90
tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy
nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf
tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq
JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3
IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW
05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41
T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI
kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop
PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N
1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y
jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02
77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi
kT9qhqn+lw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG
EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0
WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp
YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU
WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt
rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ
4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2
zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg
wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH
Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF
BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM
E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg
MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq
MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp
bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv
b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV
nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5
4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg
wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw
WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN
z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g
KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA
uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF
MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp
emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3
U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I
UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn
DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU
1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX
Yf4Zr0fJsGuv
-----END CERTIFICATE-----

View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIEhTCCA22gAwIBAgIQICQSJZuKOSV/tUkbKIJbljANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0
aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENs
YXNzIDEgUjEwHhcNMjQxMjI1MDI1NTI0WhcNMjkxMjI0MDI1NTI0WjBNMQswCQYDVQQGEwJDTjES
MBAGA1UECgwJ5ZSQ57un5p2oMQ8wDQYDVQQLDAZBbGlwYXkxGTAXBgNVBAMMEDIwODg4MDI1MTAx
NTM0MzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUirYg+bGLRHq/cr/K9M8owW9P
26K3Et5TnIgyNjsZ4GVvg4rvo84V6EPob8qSSGej9pN5dJdk1HPn7fvBOt0lgfeCIoB18HxCbKpS
eDDUSj+vL9IrQ0s8zYqWEbyQt43l+R6tib2kHXKfOJiwgVQXmM0GdvxQ5VLXYp4egM0aSvmvPaef
TJiON5a11GoKSXKZVlWiTRVlzzyMJgPUspwRH8I4YVqDqPhkQ1EUfy2QLW1DKFzqV/4L57Ewx2Tv
QdEhu5Dur8kKHc7K/xdxw2fvW1mpN+xa7atXN6pmzjZLDXeBjBdUp8pTjcYelHWIkac3MvN1tprP
rUJbdIPyDKblAgMBAAGjggEpMIIBJTAfBgNVHSMEGDAWgBRxB+IEYRbk5fJl6zEPyeD0PJrVkTAd
BgNVHQ4EFgQUsE5Yz2+7DyFYxE72JGYY2yYkPVQwQAYDVR0gBDkwNzA1BgdggRwBbgEBMCowKAYI
KwYBBQUHAgEWHGh0dHA6Ly9jYS5hbGlwYXkuY29tL2Nwcy5wZGYwDgYDVR0PAQH/BAQDAgbAMC8G
A1UdHwQoMCYwJKAioCCGHmh0dHA6Ly9jYS5hbGlwYXkuY29tL2NybDk2LmNybDBgBggrBgEFBQcB
AQRUMFIwKAYIKwYBBQUHMAKGHGh0dHA6Ly9jYS5hbGlwYXkuY29tL2NhNi5jZXIwJgYIKwYBBQUH
MAGGGmh0dHA6Ly9jYS5hbGlwYXkuY29tOjgzNDAvMA0GCSqGSIb3DQEBCwUAA4IBAQBeAebvy7Du
9dGbDMM2JUD5Pt7gdlqdab1uDaKf8SnPmmvcZFFKYvOsa+26eDthwGE7aXTNcB7MCTPrdkj6IFoi
zwekAmevXn1sN1rUBOSGsJmi5KS652ZNflBWs2XXgiPxWaMKeoFEjGEJ9NldtLDmER0JOjTNGb4X
syqfstwt2xhMZkc8VNYpe0nHTMJVHcSV+w8PBx0STQ+Dt+1VDVcKABMF110nsiqjbAi/RcAv2l9+
vyC8GXecRN6l8dSnmMG/gjncGGYSXx4RwmJXskkIkkexa9oTYmcdb6m7uTFRCles09HKLHaXxCx7
jeyLo8gH7doOlBQZ++Vr2ivIEKiO
-----END CERTIFICATE-----

View File

@ -976,8 +976,13 @@
});
const batchData = await batchResponse.json();
if (batchData.code === -200) {
showMessage(data.msg);
} else if (batchData.code === -300) {
// TODO VIP 等级
if (batchData.code === 200) {
} else if (batchData.code === 200) {
const batchNo = batchData.data;
progressBar.value = 50;
@ -1026,7 +1031,9 @@
if (username) {
userInfoDiv.textContent = `欢迎, ${username}`;
} else {
userInfoDiv.textContent = `欢迎, 未登录`;
setTimeout(() => {
window.location.href = '/login.html';
}, 200);
}
}
@ -1037,10 +1044,10 @@
}
function showMessage(msg) {
alert(msg);
// alert(msg);
setTimeout(() => {
window.location.href = '/login.html';
}, 500);
}, 200);
}
function logout() {