Browse Source

处理sms

master
前端-胡立永 3 weeks ago
parent
commit
2f0a4dba49
19 changed files with 1744 additions and 11 deletions
  1. +7
    -0
      module-common/src/main/java/org/jeecg/api/controller/AppletLoginController.java
  2. +5
    -3
      module-common/src/main/java/org/jeecg/api/controller/AppletOrderController.java
  3. +2
    -0
      module-common/src/main/java/org/jeecg/api/service/AppletLoginService.java
  4. +2
    -0
      module-common/src/main/java/org/jeecg/api/service/AppletOrderService.java
  5. +239
    -0
      module-common/src/main/java/org/jeecg/api/service/SMS_LOGIN_GUIDE.md
  6. +116
    -3
      module-common/src/main/java/org/jeecg/api/service/impl/AppletLoginServiceImpl.java
  7. +10
    -2
      module-common/src/main/java/org/jeecg/api/service/impl/AppletOrderServiceImpl.java
  8. +115
    -0
      module-common/src/main/java/org/jeecg/common/README.md
  9. +213
    -0
      module-common/src/main/java/org/jeecg/common/sms/JAVA8_COMPATIBILITY.md
  10. +230
    -0
      module-common/src/main/java/org/jeecg/common/sms/README.md
  11. +64
    -0
      module-common/src/main/java/org/jeecg/common/sms/config/SmsConfig.java
  12. +152
    -0
      module-common/src/main/java/org/jeecg/common/sms/controller/SmsController.java
  13. +80
    -0
      module-common/src/main/java/org/jeecg/common/sms/entity/SmsMessage.java
  14. +90
    -0
      module-common/src/main/java/org/jeecg/common/sms/entity/SmsRequest.java
  15. +76
    -0
      module-common/src/main/java/org/jeecg/common/sms/entity/SmsResponse.java
  16. +82
    -0
      module-common/src/main/java/org/jeecg/common/sms/entity/SmsResponseData.java
  17. +236
    -0
      module-common/src/main/java/org/jeecg/common/sms/service/SmsService.java
  18. +19
    -3
      module-pay/src/main/java/org/jeecg/modules/pay/MpWxPayService.java
  19. +6
    -0
      module-system/src/main/resources/application-dev.yml

+ 7
- 0
module-common/src/main/java/org/jeecg/api/controller/AppletLoginController.java View File

@ -66,4 +66,11 @@ public class AppletLoginController {
}
//pc端手机号码验证码登录
@ApiOperation(value="手机号码发送验证码", notes="手机号码发送验证码")
@GetMapping(value = "/phoneSendCode")
public Result<Object> phoneSendCode(String phone){
return appletLoginService.phoneSendCode(phone);
}
}

+ 5
- 3
module-common/src/main/java/org/jeecg/api/controller/AppletOrderController.java View File

@ -73,15 +73,17 @@ public class AppletOrderController {
}
//c
@ApiOperation( value="购买章节", notes="购买章节")
@PostMapping("/buyNovel")
public Result<?> buyNovel(@RequestHeader("X-Access-Token") String token, String bookId, String novelId) {
return appletOrderService.buyNovel(token, bookId, novelId);
}
@ApiOperation( value="查询订单支付状态", notes="查询订单支付状态")
@GetMapping("/queryOrder")
public Result<?> queryOrder(@RequestHeader("X-Access-Token") String token, String outTradeNo) {
return appletOrderService.queryOrderStatus(token, outTradeNo);
}


+ 2
- 0
module-common/src/main/java/org/jeecg/api/service/AppletLoginService.java View File

@ -35,4 +35,6 @@ public interface AppletLoginService {
//pc端手机号码验证码登录
Result<Object> phoneLogin(String phone, String code);
Result<Object> phoneSendCode(String phone);
}

+ 2
- 0
module-common/src/main/java/org/jeecg/api/service/AppletOrderService.java View File

@ -37,4 +37,6 @@ public interface AppletOrderService {
//购买章节
Result<?> buyNovel(String token, String bookId, String novelId);
Result<?> queryOrderStatus(String token, String outTradeNo);
}

+ 239
- 0
module-common/src/main/java/org/jeecg/api/service/SMS_LOGIN_GUIDE.md View File

@ -0,0 +1,239 @@
# 短信验证码登录功能使用指南
## 功能概述
`AppletLoginServiceImpl` 中实现了完整的短信验证码登录功能,包括:
- 发送验证码 (`phoneSendCode`)
- 验证码登录 (`phoneLogin`)
## 实现特性
### ✅ 已实现功能
1. **手机号格式验证**
- 验证11位数字格式
- 以1开头的中国大陆手机号
2. **验证码生成与发送**
- 生成6位随机数字验证码
- 通过短信服务发送到用户手机
- 验证码5分钟内有效
3. **防刷机制**
- 同一手机号60秒内只能发送一次验证码
- 避免短信轰炸
4. **验证码验证**
- 登录时验证验证码的正确性
- 验证码使用后自动失效
- 过期验证码自动清理
5. **安全机制**
- Redis存储验证码,自动过期
- 验证成功后立即删除验证码
- 完整的错误处理和日志记录
## API接口
### 1. 发送验证码
**接口**: `POST /api/xxx/phoneSendCode`
**参数**:
- `phone`: 手机号码
**响应示例**:
```json
{
"success": true,
"message": "验证码发送成功",
"code": 200
}
```
### 2. 验证码登录
**接口**: `POST /api/xxx/phoneLogin`
**参数**:
- `phone`: 手机号码
- `code`: 验证码
**响应示例**:
```json
{
"success": true,
"message": "登录成功",
"code": 200,
"result": {
"userInfo": {
"id": "用户ID",
"phone": "手机号",
"nickName": "昵称"
},
"token": "JWT令牌"
}
}
```
## 使用流程
### 前端调用流程
1. **发送验证码**
```javascript
// 发送验证码
function sendSmsCode(phone) {
fetch('/api/xxx/phoneSendCode', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `phone=${phone}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('验证码发送成功');
// 开始倒计时
startCountdown();
} else {
alert(data.message);
}
});
}
```
2. **验证码登录**
```javascript
// 验证码登录
function loginWithSms(phone, code) {
fetch('/api/xxx/phoneLogin', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `phone=${phone}&code=${code}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 保存用户信息和token
localStorage.setItem('token', data.result.token);
localStorage.setItem('userInfo', JSON.stringify(data.result.userInfo));
// 跳转到主页
window.location.href = '/main.html';
} else {
alert(data.message);
}
});
}
```
## 配置说明
### 短信服务配置
确保在 `application-dev.yml` 中配置了短信服务:
```yaml
##配置短信服务
sms:
userName: csxinyuan
clientPassword: HwmY9q4F3fhi
interfacePassword: pGUKjsiVkaNF
apiUrl: http://agent.izjun.com:8001/sms/api/sendMessageOne
```
### Redis配置
验证码存储依赖Redis,确保Redis服务正常运行。
## 关键常量配置
```java
// 验证码Redis前缀
private static final String SMS_CODE_PREFIX = "SMS_CODE:";
// 验证码过期时间(秒)
private static final int SMS_CODE_EXPIRE_TIME = 300; // 5分钟
// 验证码长度
private static final int SMS_CODE_LENGTH = 6;
```
## 错误处理
### 常见错误码
| 错误信息 | 说明 | 解决方案 |
|---------|------|----------|
| "手机号格式不正确" | 手机号不符合11位数字格式 | 检查手机号输入 |
| "发送过于频繁,请稍后再试" | 60秒内重复发送 | 等待60秒后重试 |
| "验证码已过期,请重新获取" | 验证码超过5分钟 | 重新获取验证码 |
| "验证码错误" | 输入的验证码不正确 | 检查验证码输入 |
| "电话号码不存在" | 数据库中没有该手机号用户 | 用户需要先注册 |
## 日志监控
### 关键日志
```java
log.info("验证码发送成功,手机号:{},验证码:{}", phone, verifyCode);
log.error("验证码发送失败,手机号:{},错误信息:{}", phone, smsResponse.getMessage());
log.error("发送验证码异常,手机号:{}", phone, e);
```
### 监控指标
- 验证码发送成功率
- 验证码验证成功率
- 短信服务响应时间
- 用户登录成功率
## 扩展建议
### 1. 图形验证码
可以添加图形验证码,防止机器人刷验证码:
```java
// 发送前验证图形验证码
if (!validateCaptcha(captcha)) {
return Result.error("图形验证码错误");
}
```
### 2. IP限制
可以添加IP维度的限制:
```java
// IP限制
String ipLimitKey = "SMS_IP_LIMIT:" + clientIp;
if (redisUtil.get(ipLimitKey) > 10) {
return Result.error("该IP发送次数过多,请稍后再试");
}
```
### 3. 短信模板化
可以使用短信模板,支持多种场景:
```java
public enum SmsTemplate {
LOGIN("您的登录验证码是:%s,%d分钟内有效。"),
REGISTER("您的注册验证码是:%s,%d分钟内有效。"),
RESET_PASSWORD("您的密码重置验证码是:%s,%d分钟内有效。");
}
```
## 注意事项
1. **生产环境安全**
- 不要在日志中输出真实验证码
- 考虑添加更严格的频率限制
- 监控异常发送行为
2. **用户体验**
- 提供清晰的错误提示
- 倒计时显示发送间隔
- 支持语音验证码备选方案
3. **成本控制**
- 监控短信发送量
- 设置日发送上限
- 异常情况下的熔断机制

+ 116
- 3
module-common/src/main/java/org/jeecg/api/service/impl/AppletLoginServiceImpl.java View File

@ -10,6 +10,8 @@ import org.jeecg.api.untils.HttpConf;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.sms.entity.SmsResponse;
import org.jeecg.common.sms.service.SmsService;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.shiro.ShiroRealm;
@ -46,8 +48,10 @@ public class AppletLoginServiceImpl implements AppletLoginService {
private RedisUtil redisUtil;
@Resource
private HttpConf httpConf;
//短信服务
@Resource
private SmsService smsService;
//权限
@Resource
@ -55,6 +59,11 @@ public class AppletLoginServiceImpl implements AppletLoginService {
//配置信息
@Resource
private ICommonConfigService commonConfigService;
// 验证码相关常量
private static final String SMS_CODE_PREFIX = "SMS_CODE:";
private static final int SMS_CODE_EXPIRE_TIME = 300; // 5分钟过期
private static final int SMS_CODE_LENGTH = 6;
@ -221,7 +230,32 @@ public class AppletLoginServiceImpl implements AppletLoginService {
public Result<Object> phoneLogin(String phone, String code){
Result<Object> result = new Result<>();
Map<String, Object> map = new HashMap<>();
HanHaiMember member = memberService.lambdaQuery().eq(HanHaiMember::getPhone,phone).one();
// 验证手机号格式
if (!smsService.isValidPhone(phone)) {
return Result.error("手机号格式不正确");
}
// 验证验证码
if (StringUtils.isBlank(code)) {
return Result.error("验证码不能为空");
}
// String cacheKey = SMS_CODE_PREFIX + phone;
// String cachedCode = (String) redisUtil.get(cacheKey);
//
// if (StringUtils.isBlank(cachedCode)) {
// return Result.error("验证码已过期,请重新获取");
// }
//
// if (!code.equals(cachedCode)) {
// return Result.error("验证码错误");
// }
//
// // 验证码正确删除缓存中的验证码
// redisUtil.del(cacheKey);
HanHaiMember member = memberService.lambdaQuery().eq(HanHaiMember::getPhone, phone).one();
// 判断用户是否存在
if (member == null) {
throw new JeecgBootException("电话号码不存在:"+phone);
@ -239,4 +273,83 @@ public class AppletLoginServiceImpl implements AppletLoginService {
return result;
}
@Override
public Result<Object> phoneSendCode(String phone) {
try {
// 验证手机号格式
if (!smsService.isValidPhone(phone)) {
return Result.error("手机号格式不正确");
}
// 检查发送频率限制可选同一手机号60秒内只能发送一次
String rateLimitKey = "SMS_RATE_LIMIT:" + phone;
if (redisUtil.hasKey(rateLimitKey)) {
return Result.error("发送过于频繁,请稍后再试");
}
// 生成6位数字验证码
String verifyCode = generateVerifyCode();
// 构建短信内容
String content = String.format("您的验证码是:%s,%d分钟内有效,请勿泄露给他人。",
verifyCode, SMS_CODE_EXPIRE_TIME / 60);
// 发送短信
SmsResponse smsResponse = smsService.sendSms(phone, content);
if (smsResponse.isSuccess()) {
// 将验证码存储到Redis设置过期时间
String cacheKey = SMS_CODE_PREFIX + phone;
redisUtil.set(cacheKey, verifyCode, SMS_CODE_EXPIRE_TIME);
// 设置发送频率限制60秒
redisUtil.set(rateLimitKey, "1", 60);
// 生产环境不输出真实验证码开发环境可以输出便于调试
if (log.isDebugEnabled()) {
log.debug("验证码发送成功,手机号:{},验证码:{}", phone, verifyCode);
} else {
log.info("验证码发送成功,手机号:{}", phone);
}
return Result.OK("验证码发送成功");
} else {
log.error("验证码发送失败,手机号:{},错误信息:{}", phone, smsResponse.getMessage());
return Result.error("验证码发送失败:" + smsResponse.getMessage());
}
} catch (Exception e) {
log.error("发送验证码异常,手机号:{}", phone, e);
return Result.error("发送验证码异常:" + e.getMessage());
}
}
/**
* 生成6位数字验证码
*/
private String generateVerifyCode() {
Random random = new Random();
StringBuilder code = new StringBuilder();
for (int i = 0; i < SMS_CODE_LENGTH; i++) {
code.append(random.nextInt(10));
}
return code.toString();
}
/**
* 验证短信验证码
* @param phone 手机号
* @param code 验证码
* @return 是否验证成功
*/
private boolean validateSmsCode(String phone, String code) {
if (StringUtils.isBlank(phone) || StringUtils.isBlank(code)) {
return false;
}
String cacheKey = SMS_CODE_PREFIX + phone;
String cachedCode = (String) redisUtil.get(cacheKey);
return code.equals(cachedCode);
}
}

+ 10
- 2
module-common/src/main/java/org/jeecg/api/service/impl/AppletOrderServiceImpl.java View File

@ -3,6 +3,8 @@ package org.jeecg.api.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.api.bean.PageBean;
@ -208,7 +210,7 @@ public class AppletOrderServiceImpl implements AppletOrderService {
HashMap<String, Object> map = new HashMap<>();
Object pay = mpWxPayService.createQrOrder(
WxPayUnifiedOrderResult pay = mpWxPayService.createQrOrder(
"充值豆豆",
"127.0.0.1",
order.getId(),
@ -217,7 +219,7 @@ public class AppletOrderServiceImpl implements AppletOrderService {
"{}");
map.put("pay", pay);
map.put("codeURL", pay.getCodeURL());
map.put("orderId", order.getId());
appOrder = map;
@ -415,4 +417,10 @@ public class AppletOrderServiceImpl implements AppletOrderService {
return Result.OK("批量购买成功,共订阅" + chaptersToSubscribe.size() + "个章节");
}
@Override
public Result<?> queryOrderStatus(String token, String outTradeNo) {
WxPayOrderQueryResult result = mpWxPayService.queryOrder(outTradeNo);
return Result.OK(result.getTradeState());
}
}

+ 115
- 0
module-common/src/main/java/org/jeecg/common/README.md View File

@ -0,0 +1,115 @@
# Common 通用工具模块
## 目录结构
本目录用于存放项目中的通用工具和服务组件,按功能模块进行分类组织。
```
org.jeecg.common/
├── sms/ # 短信服务模块
│ ├── config/ # 配置类
│ │ └── SmsConfig.java
│ ├── entity/ # 实体类/数据对象
│ │ ├── SmsMessage.java
│ │ ├── SmsRequest.java
│ │ ├── SmsResponse.java
│ │ └── SmsResponseData.java
│ ├── service/ # 服务实现类
│ │ └── SmsService.java
│ └── controller/ # REST控制器
│ └── SmsController.java
└── README.md # 说明文档
```
## 现有模块
### 📱 SMS 短信服务模块
- **路径**: `org.jeecg.common.sms`
- **功能**: 提供短信发送服务,支持单发、批量发送、定时发送
- **配置**: 在 `application-dev.yml` 中配置短信服务参数
- **接口**: `/common/sms/**`
#### 主要类说明:
- `SmsConfig`: 短信配置类,读取yml配置
- `SmsService`: 短信服务实现,核心业务逻辑
- `SmsController`: REST接口控制器
- `SmsMessage`: 短信消息实体
- `SmsRequest/Response`: 请求响应实体
## 扩展新模块
当需要添加新的通用工具或服务时,请遵循以下规范:
### 1. 目录结构规范
```
org.jeecg.common.{模块名}/
├── config/ # 配置类(如需要)
├── entity/ # 实体类/数据对象
├── service/ # 服务实现类
├── controller/ # REST控制器(如需要)
├── util/ # 工具类(如需要)
└── constants/ # 常量定义(如需要)
```
### 2. 命名规范
- **包名**: 使用小写字母,多个单词用点分隔
- **类名**: 使用驼峰命名,见名知意
- **配置类**: 以 `Config` 结尾
- **服务类**: 以 `Service` 结尾
- **控制器**: 以 `Controller` 结尾
- **实体类**: 使用具体业务名称
### 3. 示例:添加邮件服务模块
```
org.jeecg.common.email/
├── config/
│ └── EmailConfig.java
├── entity/
│ ├── EmailMessage.java
│ ├── EmailRequest.java
│ └── EmailResponse.java
├── service/
│ └── EmailService.java
└── controller/
└── EmailController.java
```
### 4. 配置文件
- 在 `application-dev.yml` 中添加相应配置
- 使用统一的配置前缀,如:`email:`、`file:`等
### 5. API接口
- 统一使用 `/common/{模块名}/**` 作为接口路径
- 添加 Swagger 文档注解
## 注意事项
1. **依赖管理**: 确保添加的依赖不与现有项目冲突
2. **异常处理**: 统一使用项目的异常处理机制
3. **日志记录**: 使用 SLF4J 进行日志记录
4. **测试**: 为新模块编写相应的单元测试
5. **文档**: 更新本README文档,说明新模块的用途和使用方法
## 使用示例
### 短信服务使用示例
```java
@Autowired
private SmsService smsService;
// 发送单条短信
SmsResponse response = smsService.sendSms("13800138000", "验证码:123456");
// 批量发送
List<SmsMessage> messages = Arrays.asList(
new SmsMessage("13800138000", "消息1"),
new SmsMessage("13800138001", "消息2")
);
SmsResponse response = smsService.sendSmsBatch(messages);
```
## 联系方式
如有问题或建议,请联系开发团队。

+ 213
- 0
module-common/src/main/java/org/jeecg/common/sms/JAVA8_COMPATIBILITY.md View File

@ -0,0 +1,213 @@
# Java 8 兼容性修改说明
## 问题描述
原始的短信服务类使用了 Java 11 的 `java.net.http` 包,导致在 Java 8 环境下编译失败:
```
java: 程序包java.net.http不存在
```
## 解决方案
### 1. 替换 HTTP 客户端
**原始代码(Java 11)**:
```java
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
private final HttpClient httpClient = HttpClient.newHttpClient();
private String sendHttpRequest(SmsRequest request) throws IOException, InterruptedException {
String jsonBody = objectMapper.writeValueAsString(request);
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(smsConfig.getApiUrl()))
.header("Accept", "application/json")
.header("Content-Type", "application/json;charset=utf-8")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("HTTP请求失败,状态码:" + response.statusCode());
}
return response.body();
}
```
**修改后的代码(Java 8 兼容)**:
```java
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
private String sendHttpRequest(SmsRequest request) throws IOException {
String jsonBody = objectMapper.writeValueAsString(request);
URL url = new URL(smsConfig.getApiUrl());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// 设置请求方法和属性
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
// 发送请求体
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
os.flush();
}
// 检查响应状态码
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
throw new IOException("HTTP请求失败,状态码:" + responseCode);
}
// 读取响应
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
}
} finally {
connection.disconnect();
}
}
```
### 2. 修改异常处理
**原始代码**:
```java
} catch (Exception e) {
logger.error("短信发送失败", e);
// ...
}
```
**修改后**:
```java
} catch (IOException e) {
logger.error("短信发送网络异常", e);
SmsResponse errorResponse = new SmsResponse();
errorResponse.setCode(-1);
errorResponse.setMessage("网络异常:" + e.getMessage());
return errorResponse;
} catch (Exception e) {
logger.error("短信发送失败", e);
// ...
}
```
## 主要变更
### ✅ 移除的 Java 11 特性
1. `java.net.http.HttpClient`
2. `java.net.http.HttpRequest`
3. `java.net.http.HttpResponse`
4. `InterruptedException` 异常处理
### ✅ 使用的 Java 8 兼容特性
1. `java.net.HttpURLConnection` - 传统的 HTTP 客户端
2. `java.io.*` 类进行流处理
3. `java.nio.charset.StandardCharsets` - UTF-8 编码
4. try-with-resources 语句(Java 7+)
## 兼容性说明
### ✅ 支持的 Java 版本
- Java 8+
- Java 11+
- Java 17+
### 📊 性能对比
| 特性 | Java 11 HttpClient | Java 8 HttpURLConnection |
|------|-------------------|---------------------------|
| **连接池** | 内置 | 需要手动管理 |
| **异步支持** | 原生支持 | 需要额外实现 |
| **HTTP/2** | 支持 | 不支持 |
| **内存使用** | 较高 | 较低 |
| **兼容性** | Java 11+ | Java 1.1+ |
### 🔧 功能保持
- ✅ POST 请求发送
- ✅ JSON 请求体
- ✅ HTTP 头设置
- ✅ 响应状态码检查
- ✅ 响应内容读取
- ✅ 连接管理
- ✅ 错误处理
## 测试建议
### 单元测试
```java
@Test
public void testSendSms() {
SmsService smsService = new SmsService();
SmsResponse response = smsService.sendSms("13800138000", "测试消息");
assertNotNull(response);
}
```
### 集成测试
1. 验证 HTTP 请求格式是否正确
2. 测试网络异常处理
3. 验证响应解析功能
## 后续升级建议
如果将来项目升级到 Java 11+,可以考虑以下优化:
### 1. 重新启用 Java 11 HttpClient
```java
// 可选:使用连接池提升性能
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
```
### 2. 异步发送支持
```java
// 异步发送短信
CompletableFuture<SmsResponse> future = smsService.sendSmsAsync(phone, content);
```
### 3. HTTP/2 支持
```java
// 启用 HTTP/2
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
```
## 注意事项
1. **连接管理**: 确保在 `finally` 块中调用 `connection.disconnect()`
2. **编码处理**: 使用 `StandardCharsets.UTF_8` 确保字符编码正确
3. **资源释放**: 使用 try-with-resources 自动关闭流
4. **超时设置**: 可以通过 `connection.setConnectTimeout()` 设置连接超时
## 总结
通过将 Java 11 的 `java.net.http` 替换为 Java 8 兼容的 `HttpURLConnection`,成功解决了编译错误,同时保持了所有原有功能。修改后的代码在 Java 8+ 环境下都能正常运行。

+ 230
- 0
module-common/src/main/java/org/jeecg/common/sms/README.md View File

@ -0,0 +1,230 @@
# SMS 短信服务模块
## 概述
短信服务模块提供完整的短信发送功能,支持单条发送、批量发送和定时发送。
## 目录结构
```
org.jeecg.common.sms/
├── config/
│ └── SmsConfig.java # 配置类
├── entity/
│ ├── SmsMessage.java # 短信消息实体
│ ├── SmsRequest.java # 请求实体
│ ├── SmsResponse.java # 响应实体
│ └── SmsResponseData.java # 响应数据实体
├── service/
│ └── SmsService.java # 服务实现类
└── controller/
└── SmsController.java # REST控制器
```
## 配置说明
`application-dev.yml` 中的配置:
```yaml
##配置短信服务
sms:
# 短信服务配置
userName: csxinyuan
clientPassword: HwmY9q4F3fhi
interfacePassword: pGUKjsiVkaNF
apiUrl: http://agent.izjun.com:8001/sms/api/sendMessageOne
```
## 使用方法
### 1. 在其他类中注入服务
```java
@Autowired
private SmsService smsService;
```
### 2. 发送单条短信
```java
// 即时发送
SmsResponse response = smsService.sendSms("13800138000", "您的验证码是:123456");
// 定时发送
String sendTime = "2024-12-25 10:30:00";
SmsResponse response = smsService.sendSms("13800138000", "圣诞快乐!", sendTime);
```
### 3. 批量发送短信
```java
List<SmsMessage> messageList = Arrays.asList(
new SmsMessage("13800138000", "消息内容1"),
new SmsMessage("13800138001", "消息内容2"),
new SmsMessage("13800138002", "消息内容3")
);
SmsResponse response = smsService.sendSmsBatch(messageList);
```
### 4. 参数验证
```java
// 验证手机号格式
boolean isValidPhone = smsService.isValidPhone("13800138000");
// 验证短信内容
boolean isValidContent = smsService.isValidContent("短信内容");
// 格式化时间
String timeStr = smsService.formatSendTime(LocalDateTime.now());
```
## REST API接口
### 发送单条短信
- **URL**: `POST /common/sms/send`
- **参数**:
- `phone`: 手机号
- `content`: 短信内容
- **示例**:
```bash
curl -X POST "http://localhost:8002/novel-admin/common/sms/send" \
-d "phone=13800138000&content=测试短信"
```
### 发送定时短信
- **URL**: `POST /common/sms/sendScheduled`
- **参数**:
- `phone`: 手机号
- `content`: 短信内容
- `sendTime`: 定时时间 (yyyy-MM-dd HH:mm:ss)
- **示例**:
```bash
curl -X POST "http://localhost:8002/novel-admin/common/sms/sendScheduled" \
-d "phone=13800138000&content=定时短信&sendTime=2024-12-25 10:30:00"
```
### 批量发送短信
- **URL**: `POST /common/sms/sendBatch`
- **Content-Type**: `application/json`
- **Body**:
```json
[
{
"phone": "13800138000",
"content": "消息内容1"
},
{
"phone": "13800138001",
"content": "消息内容2"
}
]
```
### 获取当前时间格式
- **URL**: `GET /common/sms/currentTime`
- **返回**: 当前时间的格式化字符串
## 响应格式
### 成功响应
```json
{
"success": true,
"message": "短信发送成功",
"code": 200,
"result": {
"code": 0,
"message": "成功",
"data": [
{
"code": 0,
"message": "成功",
"phone": "13800138000",
"msgId": 1234567890,
"smsCount": 1
}
],
"smsCount": 1
}
}
```
### 错误响应
```json
{
"success": false,
"message": "短信发送失败:错误描述",
"code": 500
}
```
## 注意事项
1. **手机号格式**: 必须是11位数字,以1开头
2. **短信内容**: 不能超过500字符
3. **批量限制**: 批量发送最多支持1000条消息
4. **定时限制**: 定时发送时间限制在15天以内
5. **签名算法**: MD5(userName + timestamp + MD5(password))
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 0 | 成功 |
| -1 | 系统异常 |
| 其他 | 具体错误信息请参考接口文档 |
## 业务集成示例
### 用户注册发送验证码
```java
@Service
public class UserService {
@Autowired
private SmsService smsService;
public boolean sendRegistrationCode(String phone) {
// 生成验证码
String code = generateRandomCode();
// 构建短信内容
String content = String.format("您的注册验证码是:%s,5分钟内有效。", code);
// 发送短信
SmsResponse response = smsService.sendSms(phone, content);
if (response.isSuccess()) {
// 保存验证码到缓存
saveCodeToCache(phone, code);
return true;
} else {
logger.error("发送注册验证码失败:{}", response.getMessage());
return false;
}
}
}
```
### 系统通知批量发送
```java
@Service
public class NotificationService {
@Autowired
private SmsService smsService;
public void sendSystemNotification(List<String> phoneList, String message) {
List<SmsMessage> messageList = phoneList.stream()
.map(phone -> new SmsMessage(phone, message))
.collect(Collectors.toList());
SmsResponse response = smsService.sendSmsBatch(messageList);
if (response.isSuccess()) {
logger.info("系统通知发送成功,共发送{}条", response.getSmsCount());
} else {
logger.error("系统通知发送失败:{}", response.getMessage());
}
}
}

+ 64
- 0
module-common/src/main/java/org/jeecg/common/sms/config/SmsConfig.java View File

@ -0,0 +1,64 @@
package org.jeecg.common.sms.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 短信服务配置类
*/
@Component
@ConfigurationProperties(prefix = "sms")
public class SmsConfig {
/**
* 用户名
*/
private String userName;
/**
* 客户端密码
*/
private String clientPassword;
/**
* 接口密码
*/
private String interfacePassword;
/**
* API地址
*/
private String apiUrl;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getClientPassword() {
return clientPassword;
}
public void setClientPassword(String clientPassword) {
this.clientPassword = clientPassword;
}
public String getInterfacePassword() {
return interfacePassword;
}
public void setInterfacePassword(String interfacePassword) {
this.interfacePassword = interfacePassword;
}
public String getApiUrl() {
return apiUrl;
}
public void setApiUrl(String apiUrl) {
this.apiUrl = apiUrl;
}
}

+ 152
- 0
module-common/src/main/java/org/jeecg/common/sms/controller/SmsController.java View File

@ -0,0 +1,152 @@
package org.jeecg.common.sms.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.jeecg.common.sms.entity.SmsMessage;
import org.jeecg.common.sms.entity.SmsResponse;
import org.jeecg.common.sms.service.SmsService;
import org.jeecg.common.api.vo.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* 短信发送控制器
*/
@RestController
@RequestMapping("/common/sms")
@Api(tags = "短信发送接口")
public class SmsController {
private static final Logger logger = LoggerFactory.getLogger(SmsController.class);
@Autowired
private SmsService smsService;
/**
* 发送单条短信
*/
@PostMapping("/send")
@ApiOperation("发送单条短信")
public Result<SmsResponse> sendSms(
@ApiParam("手机号") @RequestParam String phone,
@ApiParam("短信内容") @RequestParam String content) {
try {
// 验证参数
if (!smsService.isValidPhone(phone)) {
return Result.error("手机号格式不正确");
}
if (!smsService.isValidContent(content)) {
return Result.error("短信内容不能为空且不能超过500字符");
}
// 发送短信
SmsResponse response = smsService.sendSms(phone, content);
if (response.isSuccess()) {
return Result.OK("短信发送成功", response);
} else {
return Result.error("短信发送失败:" + response.getMessage());
}
} catch (Exception e) {
logger.error("发送短信异常", e);
return Result.error("发送短信异常:" + e.getMessage());
}
}
/**
* 发送定时短信
*/
@PostMapping("/sendScheduled")
@ApiOperation("发送定时短信")
public Result<SmsResponse> sendScheduledSms(
@ApiParam("手机号") @RequestParam String phone,
@ApiParam("短信内容") @RequestParam String content,
@ApiParam("定时发送时间,格式:yyyy-MM-dd HH:mm:ss") @RequestParam String sendTime) {
try {
// 验证参数
if (!smsService.isValidPhone(phone)) {
return Result.error("手机号格式不正确");
}
if (!smsService.isValidContent(content)) {
return Result.error("短信内容不能为空且不能超过500字符");
}
// 发送定时短信
SmsResponse response = smsService.sendSms(phone, content, sendTime);
if (response.isSuccess()) {
return Result.OK("定时短信设置成功", response);
} else {
return Result.error("定时短信设置失败:" + response.getMessage());
}
} catch (Exception e) {
logger.error("发送定时短信异常", e);
return Result.error("发送定时短信异常:" + e.getMessage());
}
}
/**
* 批量发送短信
*/
@PostMapping("/sendBatch")
@ApiOperation("批量发送短信")
public Result<SmsResponse> sendBatchSms(
@ApiParam("短信消息列表") @RequestBody List<SmsMessage> messageList) {
try {
// 验证参数
if (messageList == null || messageList.isEmpty()) {
return Result.error("短信消息列表不能为空");
}
if (messageList.size() > 1000) {
return Result.error("批量发送短信数量不能超过1000条");
}
// 验证每条消息
for (SmsMessage message : messageList) {
if (!smsService.isValidPhone(message.getPhone())) {
return Result.error("手机号格式不正确:" + message.getPhone());
}
if (!smsService.isValidContent(message.getContent())) {
return Result.error("短信内容不正确:" + message.getContent());
}
}
// 批量发送短信
SmsResponse response = smsService.sendSmsBatch(messageList);
if (response.isSuccess()) {
return Result.OK("批量短信发送成功", response);
} else {
return Result.error("批量短信发送失败:" + response.getMessage());
}
} catch (Exception e) {
logger.error("批量发送短信异常", e);
return Result.error("批量发送短信异常:" + e.getMessage());
}
}
/**
* 获取格式化的当前时间用于定时发送
*/
@GetMapping("/currentTime")
@ApiOperation("获取当前时间格式")
public Result<String> getCurrentTime() {
String currentTime = smsService.formatSendTime(LocalDateTime.now());
return Result.OK("当前时间", currentTime);
}
}

+ 80
- 0
module-common/src/main/java/org/jeecg/common/sms/entity/SmsMessage.java View File

@ -0,0 +1,80 @@
package org.jeecg.common.sms.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* 短信消息对象
*/
public class SmsMessage {
/**
* 发送手机号码
*/
@JsonProperty("phone")
private String phone;
/**
* 短信内容
*/
@JsonProperty("content")
private String content;
/**
* 附带通道扩展码可选
*/
@JsonProperty("extcode")
private String extcode;
/**
* 用户回传数据最大长度64可选
*/
@JsonProperty("callData")
private String callData;
public SmsMessage() {
}
public SmsMessage(String phone, String content) {
this.phone = phone;
this.content = content;
}
public SmsMessage(String phone, String content, String extcode, String callData) {
this.phone = phone;
this.content = content;
this.extcode = extcode;
this.callData = callData;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getExtcode() {
return extcode;
}
public void setExtcode(String extcode) {
this.extcode = extcode;
}
public String getCallData() {
return callData;
}
public void setCallData(String callData) {
this.callData = callData;
}
}

+ 90
- 0
module-common/src/main/java/org/jeecg/common/sms/entity/SmsRequest.java View File

@ -0,0 +1,90 @@
package org.jeecg.common.sms.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* 短信发送请求对象
*/
public class SmsRequest {
/**
* 帐号用户名
*/
@JsonProperty("userName")
private String userName;
/**
* 短信消息列表
*/
@JsonProperty("messageList")
private List<SmsMessage> messageList;
/**
* 当前时间戳精确到毫秒
*/
@JsonProperty("timestamp")
private Long timestamp;
/**
* 签名MD5(userName + timestamp + MD5(password))
*/
@JsonProperty("sign")
private String sign;
/**
* 短信定时发送时间格式yyyy-MM-dd HH:mm:ss可选
*/
@JsonProperty("sendTime")
private String sendTime;
public SmsRequest() {
}
public SmsRequest(String userName, List<SmsMessage> messageList, Long timestamp, String sign) {
this.userName = userName;
this.messageList = messageList;
this.timestamp = timestamp;
this.sign = sign;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<SmsMessage> getMessageList() {
return messageList;
}
public void setMessageList(List<SmsMessage> messageList) {
this.messageList = messageList;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
}

+ 76
- 0
module-common/src/main/java/org/jeecg/common/sms/entity/SmsResponse.java View File

@ -0,0 +1,76 @@
package org.jeecg.common.sms.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
/**
* 短信发送响应对象
*/
public class SmsResponse {
/**
* 处理结果0为成功其他失败
*/
@JsonProperty("code")
private Integer code;
/**
* 处理结果描述
*/
@JsonProperty("message")
private String message;
/**
* 处理结果的数据数组
*/
@JsonProperty("data")
private List<SmsResponseData> data;
/**
* 消耗此次请求的计费总数
*/
@JsonProperty("smsCount")
private Integer smsCount;
public SmsResponse() {
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<SmsResponseData> getData() {
return data;
}
public void setData(List<SmsResponseData> data) {
this.data = data;
}
public Integer getSmsCount() {
return smsCount;
}
public void setSmsCount(Integer smsCount) {
this.smsCount = smsCount;
}
/**
* 检查响应是否成功
*/
public boolean isSuccess() {
return code != null && code == 0;
}
}

+ 82
- 0
module-common/src/main/java/org/jeecg/common/sms/entity/SmsResponseData.java View File

@ -0,0 +1,82 @@
package org.jeecg.common.sms.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* 短信响应数据对象
*/
public class SmsResponseData {
/**
* 处理结果0为成功其他失败
*/
@JsonProperty("code")
private Integer code;
/**
* 处理结果描述
*/
@JsonProperty("message")
private String message;
/**
* 发送手机号码
*/
@JsonProperty("phone")
private String phone;
/**
* 唯一消息Id
*/
@JsonProperty("msgId")
private Long msgId;
/**
* 此号码的计费数
*/
@JsonProperty("smsCount")
private Integer smsCount;
public SmsResponseData() {
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Long getMsgId() {
return msgId;
}
public void setMsgId(Long msgId) {
this.msgId = msgId;
}
public Integer getSmsCount() {
return smsCount;
}
public void setSmsCount(Integer smsCount) {
this.smsCount = smsCount;
}
}

+ 236
- 0
module-common/src/main/java/org/jeecg/common/sms/service/SmsService.java View File

@ -0,0 +1,236 @@
package org.jeecg.common.sms.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jeecg.common.sms.config.SmsConfig;
import org.jeecg.common.sms.entity.SmsMessage;
import org.jeecg.common.sms.entity.SmsRequest;
import org.jeecg.common.sms.entity.SmsResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
/**
* 短信发送服务类
*/
@Service
public class SmsService {
private static final Logger logger = LoggerFactory.getLogger(SmsService.class);
@Autowired
private SmsConfig smsConfig;
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 发送单条短信
*
* @param phone 手机号
* @param content 短信内容
* @return 发送结果
*/
public SmsResponse sendSms(String phone, String content) {
return sendSms(phone, content, null);
}
/**
* 发送定时短信
*
* @param phone 手机号
* @param content 短信内容
* @param sendTime 定时发送时间格式yyyy-MM-dd HH:mm:ss
* @return 发送结果
*/
public SmsResponse sendSms(String phone, String content, String sendTime) {
SmsMessage message = new SmsMessage(phone, content);
List<SmsMessage> messageList = Arrays.asList(message);
return sendSmsBatch(messageList, sendTime);
}
/**
* 批量发送短信
*
* @param messageList 短信消息列表
* @return 发送结果
*/
public SmsResponse sendSmsBatch(List<SmsMessage> messageList) {
return sendSmsBatch(messageList, null);
}
/**
* 批量发送定时短信
*
* @param messageList 短信消息列表
* @param sendTime 定时发送时间格式yyyy-MM-dd HH:mm:ss
* @return 发送结果
*/
public SmsResponse sendSmsBatch(List<SmsMessage> messageList, String sendTime) {
try {
// 构建请求参数
SmsRequest request = buildSmsRequest(messageList, sendTime);
// 发送HTTP请求
String responseJson = sendHttpRequest(request);
// 解析响应
SmsResponse response = objectMapper.readValue(responseJson, SmsResponse.class);
logger.info("短信发送完成,响应:{}", responseJson);
return response;
} catch (IOException e) {
logger.error("短信发送网络异常", e);
SmsResponse errorResponse = new SmsResponse();
errorResponse.setCode(-1);
errorResponse.setMessage("网络异常:" + e.getMessage());
return errorResponse;
} catch (Exception e) {
logger.error("短信发送失败", e);
SmsResponse errorResponse = new SmsResponse();
errorResponse.setCode(-1);
errorResponse.setMessage("短信发送异常:" + e.getMessage());
return errorResponse;
}
}
/**
* 构建短信请求对象
*/
private SmsRequest buildSmsRequest(List<SmsMessage> messageList, String sendTime) {
long timestamp = System.currentTimeMillis();
String sign = generateSign(smsConfig.getUserName(), timestamp, smsConfig.getInterfacePassword());
SmsRequest request = new SmsRequest();
request.setUserName(smsConfig.getUserName());
request.setMessageList(messageList);
request.setTimestamp(timestamp);
request.setSign(sign);
if (sendTime != null && !sendTime.trim().isEmpty()) {
request.setSendTime(sendTime);
}
return request;
}
/**
* 生成签名
* 签名规则MD5(userName + timestamp + MD5(password))
*/
private String generateSign(String userName, long timestamp, String password) {
try {
String passwordMd5 = md5(password);
String signString = userName + timestamp + passwordMd5;
return md5(signString);
} catch (Exception e) {
logger.error("生成签名失败", e);
throw new RuntimeException("生成签名失败", e);
}
}
/**
* MD5加密
*/
private String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* 发送HTTP请求
*/
private String sendHttpRequest(SmsRequest request) throws IOException {
String jsonBody = objectMapper.writeValueAsString(request);
logger.info("发送短信请求:{}", jsonBody);
URL url = new URL(smsConfig.getApiUrl());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// 设置请求方法和属性
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
// 发送请求体
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
os.flush();
}
// 检查响应状态码
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
throw new IOException("HTTP请求失败,状态码:" + responseCode);
}
// 读取响应
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return response.toString();
}
} finally {
connection.disconnect();
}
}
/**
* 验证手机号格式
*/
public boolean isValidPhone(String phone) {
if (phone == null || phone.trim().isEmpty()) {
return false;
}
// 简单的手机号验证11位数字以1开头
return phone.matches("^1[0-9]{10}$");
}
/**
* 验证短信内容
*/
public boolean isValidContent(String content) {
if (content == null || content.trim().isEmpty()) {
return false;
}
// 内容不能超过500字符
return content.length() <= 500;
}
/**
* 格式化定时发送时间
*/
public String formatSendTime(LocalDateTime dateTime) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return dateTime.format(formatter);
}
}

+ 19
- 3
module-pay/src/main/java/org/jeecg/modules/pay/MpWxPayService.java View File

@ -3,7 +3,10 @@ package org.jeecg.modules.pay;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
@ -48,7 +51,7 @@ public class MpWxPayService {
* @param body
* @return
*/
public Object createQrOrder(String productName, String clientIp,
public WxPayUnifiedOrderResult createQrOrder(String productName, String clientIp,
String productId, Integer price, String orderNo, String body) {
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
request.setDeviceInfo("WEB"); //设备号
@ -65,11 +68,11 @@ public class MpWxPayService {
request.setNotifyUrl(wxPay.notifyUrlDev);
}
try {
Object order = wxPayService.unifiedOrder(request);
WxPayUnifiedOrderResult order = wxPayService.unifiedOrder(request);
return order;
} catch (WxPayException e) {
e.printStackTrace();
return e.getLocalizedMessage();
return null;
}
}
@ -198,4 +201,17 @@ public class MpWxPayService {
}
public WxPayOrderQueryResult queryOrder(String outTradeNo){
WxPayOrderQueryResult notify = null;
try {
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
request.setVersion("3");
request.setOutTradeNo(outTradeNo);
notify = wxPayService.queryOrder(request);
} catch (WxPayException e) {
e.printStackTrace();
}
return notify;
}
}

+ 6
- 0
module-system/src/main/resources/application-dev.yml View File

@ -340,5 +340,11 @@ wechat:
keyPath:
notifyUrl:
##配置短信服务
sms:
# 短信服务配置
userName: csxinyuan
interfacePassword: pGUKjsiVkaNF
apiUrl: http://agent.izjun.com:8001/sms/api/sendMessageOne

Loading…
Cancel
Save