vip
This commit is contained in:
@@ -73,18 +73,18 @@ public class ClientOrderInfoController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* 确认出货
|
// * 确认出货
|
||||||
*/
|
// */
|
||||||
@Log(title = "确认出货", businessType = BusinessType.UPDATE)
|
// @Log(title = "确认出货", businessType = BusinessType.UPDATE)
|
||||||
@PostMapping("/confirmShipment")
|
// @PostMapping("/confirmShipment")
|
||||||
public AjaxResult confirmShipment(@RequestParam("orderId") String orderId) {
|
// public AjaxResult confirmShipment(@RequestParam("orderId") String orderId) {
|
||||||
try {
|
// try {
|
||||||
return orderInfoService.confirmShipment(orderId);
|
// return orderInfoService.confirmShipment(orderId);
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
return AjaxResult.error("确认出货失败: " + e.getMessage());
|
// return AjaxResult.error("确认出货失败: " + e.getMessage());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请退款
|
* 申请退款
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
package com.ruoyi.common.utils;
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.text.StrFormatter;
|
import com.ruoyi.common.core.text.StrFormatter;
|
||||||
@@ -719,4 +725,42 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
|||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String convertToBeijingTime(String gmtTime) {
|
||||||
|
try {
|
||||||
|
// 移除时区标识
|
||||||
|
String timeStr = gmtTime.replace(" Etc/GMT", "");
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// 解析为本地时间
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, formatter);
|
||||||
|
|
||||||
|
// GMT时间加8小时就是北京时间
|
||||||
|
LocalDateTime beijingTime = localDateTime.plusHours(8);
|
||||||
|
|
||||||
|
return beijingTime.format(formatter);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("时间转换失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将GMT时间字符串转换为时间戳(毫秒)
|
||||||
|
*/
|
||||||
|
public static long convertToTimestampMillis(String gmtTime) {
|
||||||
|
try {
|
||||||
|
String timeStr = gmtTime.replace(" Etc/GMT", "");
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(timeStr, formatter);
|
||||||
|
ZonedDateTime gmtDateTime = localDateTime.atZone(ZoneId.of("GMT"));
|
||||||
|
|
||||||
|
return gmtDateTime.toInstant().toEpochMilli();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("时间戳转换失败: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -30,6 +30,12 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||||
|
<artifactId>wechatpay-java</artifactId>
|
||||||
|
<version>0.2.17</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ public class AppleyPay {
|
|||||||
* @param receipt 苹果传递前端给的值
|
* @param receipt 苹果传递前端给的值
|
||||||
* @param chooseEnv 是否时测试环境
|
* @param chooseEnv 是否时测试环境
|
||||||
*/
|
*/
|
||||||
public ShopUser setIapCertificate(Long userId, String receipt, OrderInfo orderInfo,boolean chooseEnv) {
|
public ShopUser setIapCertificate(Long userId, String receipt, OrderInfo orderInfo, boolean chooseEnv) {
|
||||||
log.info("IOS端发送的购买凭证。数据有 userId = {},receipt = {},chooseEnv = {}",userId,receipt,chooseEnv);
|
log.info("IOS端发送的购买凭证。数据有 userId = {},receipt = {},chooseEnv = {}", userId, receipt, chooseEnv);
|
||||||
if (userId == null || StringUtils.isEmpty(receipt)) {
|
if (userId == null || StringUtils.isEmpty(receipt)) {
|
||||||
log.error("用户ID 或者 receipt为空");
|
log.error("用户ID 或者 receipt为空");
|
||||||
return null;
|
return null;
|
||||||
@@ -92,7 +92,7 @@ public class AppleyPay {
|
|||||||
url = chooseEnv == true ? certificateUrl : certificateUrlTest;
|
url = chooseEnv == true ? certificateUrl : certificateUrlTest;
|
||||||
final String certificateCode = receipt;
|
final String certificateCode = receipt;
|
||||||
if (StringUtils.isNotEmpty(certificateCode)) {
|
if (StringUtils.isNotEmpty(certificateCode)) {
|
||||||
return sendHttpsCoon(url, certificateCode, userId,orderInfo);
|
return sendHttpsCoon(url, certificateCode, userId, orderInfo);
|
||||||
} else {
|
} else {
|
||||||
log.error("用户ID 或者 receipt为空");
|
log.error("用户ID 或者 receipt为空");
|
||||||
return null;
|
return null;
|
||||||
@@ -101,7 +101,7 @@ public class AppleyPay {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送请求 向苹果发起验证支付请求是否有效:本方法有认证方法进行调用
|
* 发送请求 向苹果发起验证支付请求是否有效:本方法有认证方法进行调用
|
||||||
*
|
* <p>
|
||||||
* 支持的订阅产品ID:
|
* 支持的订阅产品ID:
|
||||||
* - com.mingyue.product.month (月付)
|
* - com.mingyue.product.month (月付)
|
||||||
* - com.mingyue.product.quarterly (季付)
|
* - com.mingyue.product.quarterly (季付)
|
||||||
@@ -177,14 +177,14 @@ public class AppleyPay {
|
|||||||
// 处理 latest_receipt_info(可能是数组或单个对象)
|
// 处理 latest_receipt_info(可能是数组或单个对象)
|
||||||
InAppTransaction latestTransaction = null;
|
InAppTransaction latestTransaction = null;
|
||||||
if (latestReceiptInfoObj instanceof JSONArray) {
|
if (latestReceiptInfoObj instanceof JSONArray) {
|
||||||
// 如果是数组,取最后一个(最新的交易)
|
// 如果是数组,取第一个(最新的交易)
|
||||||
JSONArray receiptArray = (JSONArray) latestReceiptInfoObj;
|
JSONArray receiptArray = (JSONArray) latestReceiptInfoObj;
|
||||||
if (receiptArray.isEmpty()) {
|
if (receiptArray.isEmpty()) {
|
||||||
log.error("latest_receipt_info 数组为空");
|
log.error("latest_receipt_info 数组为空");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 获取最新的交易记录(数组最后一个元素)
|
// 获取最新的交易记录(数组最后一个元素)
|
||||||
Object lastReceipt = receiptArray.get(receiptArray.size() - 1);
|
Object lastReceipt = receiptArray.get(0);
|
||||||
latestTransaction = JSONUtil.toBean(lastReceipt.toString(), InAppTransaction.class);
|
latestTransaction = JSONUtil.toBean(lastReceipt.toString(), InAppTransaction.class);
|
||||||
} else {
|
} else {
|
||||||
// 如果是单个对象
|
// 如果是单个对象
|
||||||
@@ -200,11 +200,12 @@ public class AppleyPay {
|
|||||||
String transactionId = latestTransaction.getTransactionId();
|
String transactionId = latestTransaction.getTransactionId();
|
||||||
String productId = latestTransaction.getProductId();
|
String productId = latestTransaction.getProductId();
|
||||||
// 获取过期时间(北京时间)
|
// 获取过期时间(北京时间)
|
||||||
Long expiresDateMsInBeijing = latestTransaction.getExpiresDateMsInBeijing();
|
String expiresData = latestTransaction.getExpiresDate();
|
||||||
|
//long expiresDateMsInBeijing = StringUtils.convertToTimestampMillis(expiresData);
|
||||||
|
|
||||||
// 查询交易信息是否已经存在
|
// 查询交易信息是否已经存在
|
||||||
OrderInfo selectOrderInfo = orderInfoMapper.selectByTradeNo(transactionId);
|
OrderInfo selectOrderInfo = orderInfoMapper.selectByTradeNo(transactionId);
|
||||||
if (selectOrderInfo != null){
|
if (selectOrderInfo != null) {
|
||||||
log.warn("交易ID {} 已存在,可能重复处理。用户ID: {}", transactionId, userId);
|
log.warn("交易ID {} 已存在,可能重复处理。用户ID: {}", transactionId, userId);
|
||||||
// 交易信息已存在
|
// 交易信息已存在
|
||||||
return null;
|
return null;
|
||||||
@@ -230,15 +231,14 @@ public class AppleyPay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证订阅是否过期(对于订阅类型,使用北京时间)
|
// 验证订阅是否过期(对于订阅类型,使用北京时间)TODO:// 待修改
|
||||||
if (expiresDateMsInBeijing != null) {
|
|
||||||
long currentTimestamp = System.currentTimeMillis();
|
long currentTimestamp = System.currentTimeMillis();
|
||||||
if (expiresDateMsInBeijing < currentTimestamp) {
|
// if (expiresDateMsInBeijing < currentTimestamp) {
|
||||||
log.warn("订阅已过期。交易ID: {}, 过期时间(北京时间): {}, 当前时间: {}",
|
// log.warn("订阅已过期。交易ID: {}, 过期时间(北京时间): {}, 当前时间: {}",
|
||||||
transactionId, new Date(expiresDateMsInBeijing), new Date(currentTimestamp));
|
// transactionId, new Date(expiresDateMsInBeijing), new Date(currentTimestamp));
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// 根据产品ID处理不同的订阅类型
|
// 根据产品ID处理不同的订阅类型
|
||||||
String packageType = null;
|
String packageType = null;
|
||||||
@@ -286,7 +286,7 @@ public class AppleyPay {
|
|||||||
orderInfo.setPayTime(DateUtils.getNowDate());
|
orderInfo.setPayTime(DateUtils.getNowDate());
|
||||||
orderInfo.setStartTime(startTime);
|
orderInfo.setStartTime(startTime);
|
||||||
orderInfo.setTradeNo(transactionId);
|
orderInfo.setTradeNo(transactionId);
|
||||||
orderInfo.setCallbackContent(transactionId); // 保存交易ID
|
orderInfo.setCallbackContent(latestTransaction.getOriginalTransactionId()); // 保存交易ID
|
||||||
orderInfo.setCallTime(DateUtils.getNowDate());
|
orderInfo.setCallTime(DateUtils.getNowDate());
|
||||||
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ public class AppleyPay {
|
|||||||
Date endTime = calculateEndTime(startTime, packageType);
|
Date endTime = calculateEndTime(startTime, packageType);
|
||||||
orderInfo.setEndTime(endTime);
|
orderInfo.setEndTime(endTime);
|
||||||
orderInfo.setPackageType(packageType);
|
orderInfo.setPackageType(packageType);
|
||||||
} else if ("com.mingyue.product.quarterly".equals(productId)) {
|
} else if ("com.mingyue.item.quarterly".equals(productId)) {
|
||||||
// 季付
|
// 季付
|
||||||
packageType = "2";
|
packageType = "2";
|
||||||
orderName = "VIP会员包季度";
|
orderName = "VIP会员包季度";
|
||||||
@@ -312,7 +312,7 @@ public class AppleyPay {
|
|||||||
orderInfo.setOrderName(orderName);
|
orderInfo.setOrderName(orderName);
|
||||||
orderInfo.setEndTime(endTime);
|
orderInfo.setEndTime(endTime);
|
||||||
orderInfo.setPackageType(packageType);
|
orderInfo.setPackageType(packageType);
|
||||||
} else if ("com.mingyue.product.semiAnnual".equals(productId)) {
|
} else if ("com.mingyue.item.semiAnnual".equals(productId)) {
|
||||||
// 半年付
|
// 半年付
|
||||||
packageType = "3";
|
packageType = "3";
|
||||||
orderName = "VIP会员包半年";
|
orderName = "VIP会员包半年";
|
||||||
@@ -323,7 +323,7 @@ public class AppleyPay {
|
|||||||
orderInfo.setOrderName(orderName);
|
orderInfo.setOrderName(orderName);
|
||||||
orderInfo.setEndTime(endTime);
|
orderInfo.setEndTime(endTime);
|
||||||
orderInfo.setPackageType(packageType);
|
orderInfo.setPackageType(packageType);
|
||||||
} else if ("com.mingyue.product.annual".equals(productId)) {
|
} else if ("com.mingyue.item.annual".equals(productId)) {
|
||||||
// 年付
|
// 年付
|
||||||
packageType = "4";
|
packageType = "4";
|
||||||
orderName = "VIP会员包年";
|
orderName = "VIP会员包年";
|
||||||
@@ -423,7 +423,6 @@ public class AppleyPay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意:下面代码跟苹果支付业务无关。
|
* 注意:下面代码跟苹果支付业务无关。
|
||||||
* 这里的code 是前端请求苹果,苹果给前端的一个密钥(如果我们通过base64解密后,可获得signature、purchase-info、environment、pod、signing-status)这个密钥用于告诉Java服务器 想苹果服务器校验订单是否成功的参数
|
* 这里的code 是前端请求苹果,苹果给前端的一个密钥(如果我们通过base64解密后,可获得signature、purchase-info、environment、pod、signing-status)这个密钥用于告诉Java服务器 想苹果服务器校验订单是否成功的参数
|
||||||
@@ -474,8 +473,12 @@ public class AppleyPay {
|
|||||||
|
|
||||||
// 添加padding
|
// 添加padding
|
||||||
switch (base64.length() % 4) {
|
switch (base64.length() % 4) {
|
||||||
case 2: base64 += "=="; break;
|
case 2:
|
||||||
case 3: base64 += "="; break;
|
base64 += "==";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
base64 += "=";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] decodedBytes = Base64.decode(base64);
|
byte[] decodedBytes = Base64.decode(base64);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.system.util;
|
package com.ruoyi.system.util;
|
||||||
|
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -129,6 +130,11 @@ public class InAppTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String expiresDateMs = "2025-11-06 13:54:04 Etc/GMT";
|
||||||
|
System.out.println(StringUtils.convertToTimestampMillis(expiresDateMs));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取购买日期时间戳(北京时间,毫秒)
|
* 获取购买日期时间戳(北京时间,毫秒)
|
||||||
* 将太平洋时间转换为北京时间
|
* 将太平洋时间转换为北京时间
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package com.ruoyi.system.util;
|
||||||
|
|
||||||
|
import com.wechat.pay.java.core.Config;
|
||||||
|
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||||
|
import com.wechat.pay.java.core.exception.HttpException;
|
||||||
|
import com.wechat.pay.java.core.exception.MalformedMessageException;
|
||||||
|
import com.wechat.pay.java.core.exception.ServiceException;
|
||||||
|
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
|
||||||
|
import com.wechat.pay.java.service.payments.app.model.CloseOrderRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
|
||||||
|
import com.wechat.pay.java.service.payments.app.model.QueryOrderByIdRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||||
|
|
||||||
|
public class WeChatAppServiceExtensionExample {
|
||||||
|
/**
|
||||||
|
* 商户号
|
||||||
|
*/
|
||||||
|
public static String merchantId = "190000****";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户API私钥路径
|
||||||
|
*/
|
||||||
|
public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户证书序列号
|
||||||
|
*/
|
||||||
|
public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户APIV3密钥
|
||||||
|
*/
|
||||||
|
public static String apiV3Key = "...";
|
||||||
|
|
||||||
|
public static AppServiceExtension service;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 初始化商户配置
|
||||||
|
Config config =
|
||||||
|
new RSAAutoCertificateConfig.Builder()
|
||||||
|
.merchantId(merchantId)
|
||||||
|
// 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
|
||||||
|
.privateKeyFromPath(privateKeyPath)
|
||||||
|
.merchantSerialNumber(merchantSerialNumber)
|
||||||
|
.apiV3Key(apiV3Key)
|
||||||
|
.build();
|
||||||
|
// 初始化服务
|
||||||
|
service = new AppServiceExtension.Builder().config(config).build();
|
||||||
|
try {
|
||||||
|
// ... 调用接口
|
||||||
|
PrepayWithRequestPaymentResponse response = prepayWithRequestPayment();
|
||||||
|
System.out.println(response);
|
||||||
|
} catch (HttpException e) { // 发送HTTP请求失败
|
||||||
|
// 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
|
||||||
|
} catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
|
||||||
|
// 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
|
||||||
|
} catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
|
||||||
|
// 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭订单
|
||||||
|
*/
|
||||||
|
public static void closeOrder() {
|
||||||
|
|
||||||
|
CloseOrderRequest request = new CloseOrderRequest();
|
||||||
|
// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||||
|
// 调用接口
|
||||||
|
service.closeOrder(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APP支付下单,并返回APP调起支付数据
|
||||||
|
*/
|
||||||
|
public static PrepayWithRequestPaymentResponse prepayWithRequestPayment() {
|
||||||
|
PrepayRequest request = new PrepayRequest();
|
||||||
|
// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||||
|
// 调用接口
|
||||||
|
return service.prepayWithRequestPayment(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付订单号查询订单
|
||||||
|
*/
|
||||||
|
public static Transaction queryOrderById() {
|
||||||
|
|
||||||
|
QueryOrderByIdRequest request = new QueryOrderByIdRequest();
|
||||||
|
// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||||
|
// 调用接口
|
||||||
|
return service.queryOrderById(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户订单号查询订单
|
||||||
|
*/
|
||||||
|
public static Transaction queryOrderByOutTradeNo() {
|
||||||
|
|
||||||
|
QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
|
||||||
|
// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||||
|
// 调用接口
|
||||||
|
return service.queryOrderByOutTradeNo(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,6 +69,8 @@
|
|||||||
<result property="updateTime" column="update_time" />
|
<result property="updateTime" column="update_time" />
|
||||||
<result property="isDel" column="is_del" />
|
<result property="isDel" column="is_del" />
|
||||||
<result property="descinfo" column="descinfo" />
|
<result property="descinfo" column="descinfo" />
|
||||||
|
<result property="vipStartTime" column="vip_start_time" />
|
||||||
|
<result property="vipEndTime" column="vip_end_time" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectShopUserVo">
|
<sql id="selectShopUserVo">
|
||||||
|
|||||||
Reference in New Issue
Block a user