mirror of https://gitee.com/y_project/RuoYi.git
短信接口开发
parent
4ebdb29c8e
commit
fcc7074301
|
@ -95,6 +95,13 @@
|
|||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>-->
|
||||
<!-- <layout>ZIP</layout>
|
||||
<includes>
|
||||
<include>
|
||||
<groupId>nothing</groupId>
|
||||
<artifactId>nothing</artifactId>
|
||||
</include>
|
||||
</includes>-->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
@ -147,7 +154,7 @@
|
|||
</plugin> -->
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<!-- <resources>
|
||||
<!-- <resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package com.ruoyi.web.controller.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.config.ServerConfig;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||
import com.ruoyi.common.utils.file.FileUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -14,13 +17,17 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.config.ServerConfig;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.file.FileUploadUtils;
|
||||
import com.ruoyi.common.utils.file.FileUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通用请求处理
|
||||
|
@ -85,10 +92,32 @@ public class CommonController
|
|||
String fileName = FileUploadUtils.upload(filePath, file);
|
||||
String url = serverConfig.getUrl() + fileName;
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
|
||||
ajax.put("url", url);
|
||||
ajax.put("fileName", fileName);
|
||||
ajax.put("newFileName", FileUtils.getName(fileName));
|
||||
ajax.put("originalFilename", file.getOriginalFilename());
|
||||
|
||||
try (InputStream inputStream = file.getInputStream();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
byteArrayOutputStream.write(buffer, 0, bytesRead);
|
||||
md.update(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
byte[] fileBytes = byteArrayOutputStream.toByteArray();
|
||||
byte[] digest = md.digest();
|
||||
String md5 = bytesToHex(digest);
|
||||
String base64 = Base64.getEncoder().encodeToString(fileBytes);
|
||||
ajax.put("fileMd5", md5);
|
||||
ajax.put("context", base64);
|
||||
} catch (IOException | NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("Failed to process file", e);
|
||||
}
|
||||
return ajax;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -97,6 +126,17 @@ public class CommonController
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用上传请求(多个)
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package com.ruoyi.web.controller.sms;
|
||||
|
||||
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SmsTaskTbl;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.service.ISmsTaskTblService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* RCS短信任务配置Controller
|
||||
*
|
||||
* @author dorion
|
||||
* @date 2024-06-01
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/sms/task/rcs")
|
||||
public class RCSSmsTaskTblController extends BaseController
|
||||
{
|
||||
private String prefix = "sms/task/rcs";
|
||||
|
||||
@Autowired
|
||||
private ISmsTaskTblService smsTaskTblService;
|
||||
|
||||
@RequiresPermissions("sms:task:rcs:view")
|
||||
@GetMapping()
|
||||
public String task()
|
||||
{
|
||||
return prefix + "/task";
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询RCS短信任务配置列表
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(SmsTaskTbl smsTaskTbl)
|
||||
{
|
||||
startPage();
|
||||
List<SmsTaskTbl> list = smsTaskTblService.selectSmsTaskTblList(smsTaskTbl);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出RCS短信任务配置列表
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:export")
|
||||
@Log(title = "RCS短信任务配置", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
public AjaxResult export(SmsTaskTbl smsTaskTbl)
|
||||
{
|
||||
List<SmsTaskTbl> list = smsTaskTblService.selectSmsTaskTblList(smsTaskTbl);
|
||||
ExcelUtil<SmsTaskTbl> util = new ExcelUtil<SmsTaskTbl>(SmsTaskTbl.class);
|
||||
return util.exportExcel(list, "RCS短信任务配置数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增RCS短信任务配置
|
||||
*/
|
||||
@GetMapping("/add")
|
||||
public String add()
|
||||
{
|
||||
return prefix + "/add";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增保存RCS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:add")
|
||||
@Log(title = "RCS短信任务配置", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(SmsTaskTbl smsTaskTbl)
|
||||
{
|
||||
return toAjax(smsTaskTblService.insertSmsTaskTbl(smsTaskTbl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改RCS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:edit")
|
||||
@GetMapping("/edit/{idSmsTask}")
|
||||
public String edit(@PathVariable("idSmsTask") Long idSmsTask, ModelMap mmap)
|
||||
{
|
||||
SmsTaskTbl smsTaskTbl = smsTaskTblService.selectSmsTaskTblByIdSmsTask(idSmsTask);
|
||||
mmap.put("smsTaskTbl", smsTaskTbl);
|
||||
return prefix + "/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改保存RCS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:edit")
|
||||
@Log(title = "RCS短信任务配置", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(SmsTaskTbl smsTaskTbl)
|
||||
{
|
||||
return toAjax(smsTaskTblService.updateSmsTaskTbl(smsTaskTbl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除RCS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:rcs:remove")
|
||||
@Log(title = "RCS短信任务配置", businessType = BusinessType.DELETE)
|
||||
@PostMapping( "/remove")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(String ids)
|
||||
{
|
||||
return toAjax(smsTaskTblService.deleteSmsTaskTblByIdSmsTasks(ids));
|
||||
}
|
||||
}
|
|
@ -24,15 +24,15 @@ import java.util.List;
|
|||
* @date 2024-06-01
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/sms/task")
|
||||
public class SmsTaskTblController extends BaseController
|
||||
@RequestMapping("/sms/task/ws")
|
||||
public class WSSmsTaskTblController extends BaseController
|
||||
{
|
||||
private String prefix = "sms/task";
|
||||
private String prefix = "sms/task/ws";
|
||||
|
||||
@Autowired
|
||||
private ISmsTaskTblService smsTaskTblService;
|
||||
|
||||
@RequiresPermissions("sms:task:view")
|
||||
@RequiresPermissions("sms:task:ws:view")
|
||||
@GetMapping()
|
||||
public String task()
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 查询WS短信任务配置列表
|
||||
*/
|
||||
@RequiresPermissions("sms:task:list")
|
||||
@RequiresPermissions("sms:task:ws:list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(SmsTaskTbl smsTaskTbl)
|
||||
|
@ -55,7 +55,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 导出WS短信任务配置列表
|
||||
*/
|
||||
@RequiresPermissions("sms:task:export")
|
||||
@RequiresPermissions("sms:task:ws:export")
|
||||
@Log(title = "WS短信任务配置", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
|
@ -78,7 +78,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 新增保存WS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:add")
|
||||
@RequiresPermissions("sms:task:ws:add")
|
||||
@Log(title = "WS短信任务配置", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
|
@ -90,7 +90,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 修改WS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:edit")
|
||||
@RequiresPermissions("sms:task:ws:edit")
|
||||
@GetMapping("/edit/{idSmsTask}")
|
||||
public String edit(@PathVariable("idSmsTask") Long idSmsTask, ModelMap mmap)
|
||||
{
|
||||
|
@ -102,7 +102,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 修改保存WS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:edit")
|
||||
@RequiresPermissions("sms:task:ws:edit")
|
||||
@Log(title = "WS短信任务配置", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
|
@ -114,7 +114,7 @@ public class SmsTaskTblController extends BaseController
|
|||
/**
|
||||
* 删除WS短信任务配置
|
||||
*/
|
||||
@RequiresPermissions("sms:task:remove")
|
||||
@RequiresPermissions("sms:task:ws:remove")
|
||||
@Log(title = "WS短信任务配置", businessType = BusinessType.DELETE)
|
||||
@PostMapping( "/remove")
|
||||
@ResponseBody
|
|
@ -13,9 +13,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">appid:</label>
|
||||
<label class="col-sm-3 control-label">appId:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="appid" class="form-control" type="text">
|
||||
<input name="appId" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<input type="text" name="channelId"/>
|
||||
</li>
|
||||
<li>
|
||||
<label>appid:</label>
|
||||
<input type="text" name="appid"/>
|
||||
<label>appId:</label>
|
||||
<input type="text" name="appId"/>
|
||||
</li>
|
||||
|
||||
<li class="select-time">
|
||||
|
@ -82,8 +82,8 @@
|
|||
title: '渠道id'
|
||||
},
|
||||
{
|
||||
field: 'appid',
|
||||
title: 'appid'
|
||||
field: 'appId',
|
||||
title: 'appId'
|
||||
},
|
||||
{
|
||||
field: 'secret',
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">appid:</label>
|
||||
<label class="col-sm-3 control-label">appId:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="appid" th:field="*{appid}" class="form-control" type="text">
|
||||
<input name="appId" th:field="*{appId}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('新增WS短信任务配置')" />
|
||||
<th:block th:include="include :: datetimepicker-css" />
|
||||
|
||||
<th:block th:include="include :: bootstrap-fileinput-css" />
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
<form class="form-horizontal m" id="form-task-add">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">任务名称:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="taskName" class="form-control" type="text" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">短信类型:</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="smsBusiType" class="form-control m-b" th:with="type=${@dict.getType('sys_sms_busi_type')}">
|
||||
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">单价:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="price" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="font-noraml col-sm-3 control-label">物料</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="file-loading" >
|
||||
<input id="singleFile" name="file" type="file">
|
||||
</div>
|
||||
<input type="hidden" name="fileName" id="fileName">
|
||||
<input type="hidden" name="filePath" id="filePath">
|
||||
<input type="hidden" name="fileMd5" id="fileMd5">
|
||||
<input type="hidden" name="context" id="context">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">任务开始时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group date">
|
||||
<input name="taskBeginTime" class="form-control" placeholder="yyyy-MM-dd HH:mm:ss" type="text" required>
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">内容类型:</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="smsContentType" class="form-control m-b" th:with="type=${@dict.getType('sys_sms_content_type')}">
|
||||
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">任务状态:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="radio-box" th:each="dict : ${@dict.getType('sys_sms_task_status')}">
|
||||
<input type="radio" th:id="${'taskStatus_' + dict.dictCode}" name="taskStatus" th:value="${dict.dictValue}" th:checked="${dict.default}">
|
||||
<label th:for="${'taskStatus_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: datetimepicker-js" />
|
||||
<th:block th:include="include :: bootstrap-fileinput-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "sms/task/rcs"
|
||||
$("#form-task-add").validate({
|
||||
focusCleanup: true
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
$.operate.save(prefix + "/add", $('#form-task-add').serialize());
|
||||
}
|
||||
}
|
||||
|
||||
$("input[name='taskBeginTime']").datetimepicker({
|
||||
format: "yyyy-mm-dd hh:ii:ss",
|
||||
// minView: "second",
|
||||
autoclose: true
|
||||
});
|
||||
|
||||
$(document).ready(function () {
|
||||
// 单图上传
|
||||
$("#singleFile").fileinput({
|
||||
uploadUrl: ctx + 'common/upload',
|
||||
maxFileCount: 1,
|
||||
autoReplace: true
|
||||
}).on('fileuploaded', function (event, data, previewId, index) {
|
||||
var rsp = data.response;
|
||||
$("#filePath").val(rsp.url);
|
||||
$("#fileName").val(rsp.originalFilename);
|
||||
$("#fileMd5").val(rsp.fileMd5);
|
||||
$("#context").val(rsp.context);
|
||||
// log.info("return url:" + rsp.url)
|
||||
// log.info("reutrn fileName:" + rsp.fileName)
|
||||
// log.info("reutrn newFileName:" + rsp.newFileName)
|
||||
// log.info("return originalFilename:" + rsp.originalFilename)
|
||||
}).on('fileremoved', function (event, id, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
}).on('filecleared', function (event, id, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
}).on('filedeleted', function (event, vKey, jqXHR, extraData) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
})
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,92 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
|
||||
<head>
|
||||
<th:block th:include="include :: header('修改WS短信任务配置')" />
|
||||
<th:block th:include="include :: datetimepicker-css" />
|
||||
</head>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
<form class="form-horizontal m" id="form-task-edit" th:object="${smsTaskTbl}">
|
||||
<input name="idSmsTask" th:field="*{idSmsTask}" type="hidden">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">任务名称:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="taskName" th:field="*{taskName}" class="form-control" type="text" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">短信类型:</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="smsBusiType" class="form-control m-b" th:with="type=${@dict.getType('sys_sms_busi_type')}">
|
||||
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{smsBusiType}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">单价:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="price" th:field="*{price}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label is-required">任务开始时间:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group date">
|
||||
<input name="taskBeginTime" th:value="${#dates.format(smsTaskTbl.taskBeginTime, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text" required>
|
||||
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">内容类型:</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="smsContentType" class="form-control m-b" th:with="type=${@dict.getType('sys_sms_content_type')}">
|
||||
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{smsContentType}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">任务状态:</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="radio-box" th:each="dict : ${@dict.getType('sys_sms_task_status')}">
|
||||
<input type="radio" th:id="${'taskStatus_' + dict.dictCode}" name="taskStatus" th:value="${dict.dictValue}" th:field="*{taskStatus}">
|
||||
<label th:for="${'taskStatus_' + dict.dictCode}" th:text="${dict.dictLabel}"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">成功数:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="successRate" th:field="*{successRate}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">物料总数:</label>
|
||||
<div class="col-sm-8">
|
||||
<input name="issueCount" th:field="*{issueCount}" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: datetimepicker-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "sms/task/rcs";
|
||||
$("#form-task-edit").validate({
|
||||
focusCleanup: true
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
$.operate.save(prefix + "/edit", $('#form-task-edit').serialize());
|
||||
}
|
||||
}
|
||||
|
||||
$("input[name='taskBeginTime']").datetimepicker({
|
||||
format: "yyyy-mm-dd",
|
||||
minView: "month",
|
||||
autoclose: true
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,167 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
|
||||
<head>
|
||||
<th:block th:include="include :: header('WS短信任务配置列表')" />
|
||||
</head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<form id="formId">
|
||||
<div class="select-list">
|
||||
<ul>
|
||||
<li>
|
||||
<label>任务名称:</label>
|
||||
<input type="text" name="taskName"/>
|
||||
</li>
|
||||
<li>
|
||||
<label>任务状态:</label>
|
||||
<select name="taskStatus" th:with="type=${@dict.getType('sys_sms_task_status')}">
|
||||
<option value="">所有</option>
|
||||
<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
|
||||
</select>
|
||||
</li>
|
||||
<li class="select-time">
|
||||
<label>创建时间:</label>
|
||||
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginCreateTime]"/>
|
||||
<span>-</span>
|
||||
<input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[endCreateTime]"/>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i> 搜索</a>
|
||||
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i> 重置</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="btn-group-sm" id="toolbar" role="group">
|
||||
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="sms:task:add">
|
||||
<i class="fa fa-plus"></i> 添加
|
||||
</a>
|
||||
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="sms:task:edit">
|
||||
<i class="fa fa-edit"></i> 修改
|
||||
</a>
|
||||
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="sms:task:remove">
|
||||
<i class="fa fa-remove"></i> 删除
|
||||
</a>
|
||||
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="sms:task:export">
|
||||
<i class="fa fa-download"></i> 导出
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-12 select-table table-striped">
|
||||
<table id="bootstrap-table"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:include="include :: footer" />
|
||||
<script th:inline="javascript">
|
||||
var editFlag = [[${@permission.hasPermi('sms:task:edit')}]];
|
||||
var removeFlag = [[${@permission.hasPermi('sms:task:remove')}]];
|
||||
var smsBusiTypeDatas = [[${@dict.getType('sys_sms_busi_type')}]];
|
||||
var smsContentTypeDatas = [[${@dict.getType('sys_sms_content_type')}]];
|
||||
var taskStatusDatas = [[${@dict.getType('sys_sms_task_status')}]];
|
||||
var prefix = ctx + "sms/task/rcs";
|
||||
|
||||
$(function() {
|
||||
var options = {
|
||||
url: prefix + "/list",
|
||||
createUrl: prefix + "/add",
|
||||
updateUrl: prefix + "/edit/{id}",
|
||||
removeUrl: prefix + "/remove",
|
||||
exportUrl: prefix + "/export",
|
||||
modalName: "WS短信任务配置",
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
field: 'idSmsTask',
|
||||
title: '主键',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'taskName',
|
||||
title: '任务名称'
|
||||
},
|
||||
{
|
||||
field: 'smsBusiType',
|
||||
title: '短信类型',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(smsBusiTypeDatas, value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'price',
|
||||
title: '单价'
|
||||
},
|
||||
{
|
||||
field: 'taskBeginTime',
|
||||
title: '任务开始时间'
|
||||
},
|
||||
{
|
||||
field: 'fileName',
|
||||
title: '物料名称',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'filePath',
|
||||
title: '物料文件下载地址',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'smsContentType',
|
||||
title: '内容类型',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(smsContentTypeDatas, value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'taskStatus',
|
||||
title: '任务状态',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(taskStatusDatas, value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'successRate',
|
||||
title: '成功数'
|
||||
},
|
||||
{
|
||||
field: 'issueCount',
|
||||
title: '物料总数'
|
||||
},
|
||||
{
|
||||
field: 'createBy',
|
||||
title: '创建者'
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
title: '创建时间'
|
||||
},
|
||||
{
|
||||
field: 'updateBy',
|
||||
title: '更新者',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
field: 'updateTime',
|
||||
title: '更新时间',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
var actions = [];
|
||||
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.idSmsTask + '\')"><i class="fa fa-edit"></i>编辑</a> ');
|
||||
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.idSmsTask + '\')"><i class="fa fa-remove"></i>删除</a>');
|
||||
return actions.join('');
|
||||
}
|
||||
}]
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -37,6 +37,8 @@
|
|||
</div>
|
||||
<input type="hidden" name="fileName" id="fileName">
|
||||
<input type="hidden" name="filePath" id="filePath">
|
||||
<input type="hidden" name="fileMd5" id="fileMd5">
|
||||
<input type="hidden" name="context" id="context">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -72,7 +74,7 @@
|
|||
<th:block th:include="include :: datetimepicker-js" />
|
||||
<th:block th:include="include :: bootstrap-fileinput-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "sms/task"
|
||||
var prefix = ctx + "sms/task/ws"
|
||||
$("#form-task-add").validate({
|
||||
focusCleanup: true
|
||||
});
|
||||
|
@ -99,6 +101,8 @@
|
|||
var rsp = data.response;
|
||||
$("#filePath").val(rsp.url);
|
||||
$("#fileName").val(rsp.originalFilename);
|
||||
$("#fileMd5").val(rsp.fileMd5);
|
||||
$("#context").val(rsp.context);
|
||||
// log.info("return url:" + rsp.url)
|
||||
// log.info("reutrn fileName:" + rsp.fileName)
|
||||
// log.info("reutrn newFileName:" + rsp.newFileName)
|
||||
|
@ -107,14 +111,20 @@
|
|||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
}).on('filecleared', function (event, id, index) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
}).on('filedeleted', function (event, vKey, jqXHR, extraData) {
|
||||
$("input[name='" + event.currentTarget.id + "']").val('')
|
||||
$("#filePath").val('');
|
||||
$("#fileName").val('');
|
||||
$("#fileMd5").val('');
|
||||
$("#context").val('');
|
||||
})
|
||||
});
|
||||
</script>
|
|
@ -71,7 +71,7 @@
|
|||
<th:block th:include="include :: footer" />
|
||||
<th:block th:include="include :: datetimepicker-js" />
|
||||
<script th:inline="javascript">
|
||||
var prefix = ctx + "sms/task";
|
||||
var prefix = ctx + "sms/task/ws";
|
||||
$("#form-task-edit").validate({
|
||||
focusCleanup: true
|
||||
});
|
|
@ -62,7 +62,7 @@
|
|||
var smsBusiTypeDatas = [[${@dict.getType('sys_sms_busi_type')}]];
|
||||
var smsContentTypeDatas = [[${@dict.getType('sys_sms_content_type')}]];
|
||||
var taskStatusDatas = [[${@dict.getType('sys_sms_task_status')}]];
|
||||
var prefix = ctx + "sms/task";
|
||||
var prefix = ctx + "sms/task/ws";
|
||||
|
||||
$(function() {
|
||||
var options = {
|
|
@ -202,6 +202,9 @@ public class RestTemplateUtils {
|
|||
/**
|
||||
* 带请求头的POST请求调用方式
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param url 请求URL
|
||||
* @param headers 请求头参数
|
||||
* @param requestBody 请求参数体
|
||||
|
|
|
@ -303,6 +303,7 @@ public class ShiroConfig
|
|||
// 注册相关
|
||||
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
|
||||
filterChainDefinitionMap.put("/api/**", "anon");
|
||||
filterChainDefinitionMap.put("/common/download", "anon");
|
||||
// 系统权限列表
|
||||
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.ruoyi.system.api;
|
||||
|
||||
import com.ruoyi.system.api.entity.U02cx.GetTokenRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface IU02cxApi {
|
||||
|
||||
String getToken(GetTokenRequest getTokenRequest);
|
||||
|
||||
|
||||
String addTask(String requestBody, String token, String appId) throws IOException;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AddTaskRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
private String taskName;
|
||||
|
||||
/**
|
||||
* 单价
|
||||
*/
|
||||
private BigDecimal price;
|
||||
|
||||
/**
|
||||
* 任务开始时间 格式 yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
private String taskBeginTime;
|
||||
|
||||
/**
|
||||
* 物料名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 物料文件下载地址,文件为utf-8编码的txt文件
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 物料文件MD5码
|
||||
*/
|
||||
private String fileMd5;
|
||||
|
||||
/**
|
||||
* 任务文本内容 base64加密字串
|
||||
*/
|
||||
private String context;
|
||||
|
||||
/**
|
||||
* 1-文本任务 2-图文任务 (当前默认文本任务)
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AddTaskResponse extends U02cxCommonResponse{
|
||||
|
||||
private Long taskId;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ApiConstants {
|
||||
|
||||
public static Map<Integer,String> returnCodeMap = new HashMap();
|
||||
|
||||
static {
|
||||
returnCodeMap.put(10001,"无appId");
|
||||
returnCodeMap.put(10002,"请求过于频繁");
|
||||
returnCodeMap.put(10003,"达到日创建任务上限");
|
||||
returnCodeMap.put(10004,"达到日修改任务上限");
|
||||
|
||||
returnCodeMap.put(20001,"appId 与 secret 不匹配");
|
||||
returnCodeMap.put(20002,"token失效");
|
||||
returnCodeMap.put(20003,"未携带token");
|
||||
returnCodeMap.put(20004,"非法任务id");
|
||||
returnCodeMap.put(20005,"缺少物料文件信息");
|
||||
returnCodeMap.put(20006,"无效的物料文件地址");
|
||||
returnCodeMap.put(20007,"物料文件md5不匹配");
|
||||
returnCodeMap.put(20008,"创建任务时 携带无效参数taskId");
|
||||
returnCodeMap.put(20009,"没有文件名称");
|
||||
returnCodeMap.put(20010,"参数未携带下载文件令牌");
|
||||
returnCodeMap.put(20011,"文件令牌失效");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class GetTokenRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 每个用户的各自独立Id
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 配套appId的口令
|
||||
*/
|
||||
private String secret;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetTokenResponse extends U02cxCommonResponse{
|
||||
|
||||
/**
|
||||
* token值 时效 1小时
|
||||
*/
|
||||
private String token;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.ruoyi.system.api.entity.U02cx;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@Data
|
||||
public class U02cxCommonResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 成功 : 0,失败:其他
|
||||
*/
|
||||
private int status;
|
||||
|
||||
/**
|
||||
* 成功 : success,失败:具体原因
|
||||
*/
|
||||
private String msg;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.ruoyi.system.api.impl;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.ruoyi.common.utils.http.RestTemplateUtils;
|
||||
import com.ruoyi.system.api.IU02cxApi;
|
||||
import com.ruoyi.system.api.entity.U02cx.AddTaskResponse;
|
||||
import com.ruoyi.system.api.entity.U02cx.ApiConstants;
|
||||
import com.ruoyi.system.api.entity.U02cx.GetTokenRequest;
|
||||
import com.ruoyi.system.api.entity.U02cx.GetTokenResponse;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Component
|
||||
public class U02cxApiImpl implements IU02cxApi {
|
||||
|
||||
|
||||
@Override
|
||||
public String getToken(GetTokenRequest getTokenRequest) {
|
||||
|
||||
ResponseEntity<GetTokenResponse> responseEntity = RestTemplateUtils.post("http://cot5b.u02cx.com:20086/whatsApi/getToken", getTokenRequest, GetTokenResponse.class);
|
||||
|
||||
Preconditions.checkState(responseEntity.getStatusCode().is2xxSuccessful(), "getToken failed");
|
||||
|
||||
GetTokenResponse getTokenResponse = responseEntity.getBody();
|
||||
Preconditions.checkNotNull(getTokenResponse, "getTokenResponse is null");
|
||||
|
||||
int status = getTokenResponse.getStatus();
|
||||
Preconditions.checkState(0 == status, "getToken failed:" + ApiConstants.returnCodeMap.get(status));
|
||||
return getTokenResponse.getToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addTask(String requestBody, String token, String appId) throws IOException {
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
|
||||
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
|
||||
httpHeaders.add("appId",appId);
|
||||
httpHeaders.add("token",token);
|
||||
|
||||
// ResponseEntity<AddTaskResponse> responseEntity = RestTemplateUtils.post("http://cot5b.u02cx.com:20086/whatsApi/api/task/addTask", httpHeaders, requestBody, AddTaskResponse.class);
|
||||
ResponseEntity<String> responseEntity = RestTemplateUtils.post("http://cot5b.u02cx.com:20086/whatsApi/api/task/addTask", httpHeaders, requestBody, String.class);
|
||||
Preconditions.checkState(responseEntity.getStatusCode().is2xxSuccessful(), "addTask failed");
|
||||
|
||||
// AddTaskResponse addTaskResponse = responseEntity.getBody();
|
||||
String response = responseEntity.getBody();
|
||||
Preconditions.checkNotNull(addTaskResponse, "addTaskResponse is null");
|
||||
|
||||
int status = addTaskResponse.getStatus();
|
||||
Preconditions.checkState(0 == status, "addTask failed:" + ApiConstants.returnCodeMap.get(status)+",msg:"+addTaskResponse.getMsg());
|
||||
|
||||
// CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
// HttpPost httpPost = new HttpPost("http://cot5b.u02cx.com:20086/whatsApi/api/task/addTask");
|
||||
// httpPost.setHeader("Content-Type", "application/json");
|
||||
// httpPost.setHeader("appId", appId);
|
||||
// httpPost.setHeader("token", token);
|
||||
// httpPost.setEntity(new StringEntity(requestBody, "utf8"));
|
||||
// CloseableHttpResponse reportResponse = httpclient.execute(httpPost);
|
||||
// String body = EntityUtils.toString(reportResponse.getEntity(), "utf8");
|
||||
//
|
||||
// AddTaskResponse addTaskResponse = JSONUtil.toBean(body, AddTaskResponse.class);
|
||||
|
||||
return addTaskResponse.getTaskId().toString();
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
|
|||
* 短信渠道管理对象 sms_channel_tbl
|
||||
*
|
||||
* @author dorion
|
||||
* @date 2024-05-28
|
||||
* @date 2024-06-09
|
||||
*/
|
||||
public class SmsChannelTbl extends BaseEntity
|
||||
{
|
||||
|
@ -24,7 +24,7 @@ public class SmsChannelTbl extends BaseEntity
|
|||
|
||||
/** appid */
|
||||
@Excel(name = "appid")
|
||||
private String appid;
|
||||
private String appId;
|
||||
|
||||
/** 口令 */
|
||||
@Excel(name = "口令")
|
||||
|
@ -38,6 +38,10 @@ public class SmsChannelTbl extends BaseEntity
|
|||
@Excel(name = "短信支持类型")
|
||||
private String smsBusiType;
|
||||
|
||||
/** 是否有效 */
|
||||
@Excel(name = "是否有效")
|
||||
private String isValid;
|
||||
|
||||
public void setIdSmsChannel(Long idSmsChannel)
|
||||
{
|
||||
this.idSmsChannel = idSmsChannel;
|
||||
|
@ -56,14 +60,14 @@ public class SmsChannelTbl extends BaseEntity
|
|||
{
|
||||
return channelId;
|
||||
}
|
||||
public void setAppid(String appid)
|
||||
public void setAppId(String appId)
|
||||
{
|
||||
this.appid = appid;
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getAppid()
|
||||
public String getAppId()
|
||||
{
|
||||
return appid;
|
||||
return appId;
|
||||
}
|
||||
public void setSecret(String secret)
|
||||
{
|
||||
|
@ -92,16 +96,26 @@ public class SmsChannelTbl extends BaseEntity
|
|||
{
|
||||
return smsBusiType;
|
||||
}
|
||||
public void setIsValid(String isValid)
|
||||
{
|
||||
this.isValid = isValid;
|
||||
}
|
||||
|
||||
public String getIsValid()
|
||||
{
|
||||
return isValid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("idSmsChannel", getIdSmsChannel())
|
||||
.append("channelId", getChannelId())
|
||||
.append("appid", getAppid())
|
||||
.append("appId", getAppId())
|
||||
.append("secret", getSecret())
|
||||
.append("publicKey", getPublicKey())
|
||||
.append("smsBusiType", getSmsBusiType())
|
||||
.append("isValid", getIsValid())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
package com.ruoyi.system.service.impl;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ruoyi.common.core.domain.entity.SmsTaskTbl;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.system.api.IU02cxApi;
|
||||
import com.ruoyi.system.api.entity.U02cx.AddTaskRequest;
|
||||
import com.ruoyi.system.api.entity.U02cx.GetTokenRequest;
|
||||
import com.ruoyi.system.domain.SmsChannelTbl;
|
||||
import com.ruoyi.system.mapper.SmsChannelTblMapper;
|
||||
import com.ruoyi.system.mapper.SmsTaskTblMapper;
|
||||
import com.ruoyi.system.service.ISmsTaskTblService;
|
||||
import com.ruoyi.system.util.RsaUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
@ -19,9 +29,16 @@ import java.util.List;
|
|||
@Service
|
||||
public class SmsTaskTblServiceImpl implements ISmsTaskTblService
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SmsTaskTblServiceImpl.class);
|
||||
@Autowired
|
||||
private SmsTaskTblMapper smsTaskTblMapper;
|
||||
|
||||
@Autowired
|
||||
private SmsChannelTblMapper smsChannelTblMapper;
|
||||
|
||||
@Autowired
|
||||
private IU02cxApi u02cxApi;
|
||||
|
||||
/**
|
||||
* 查询WS短信任务配置
|
||||
*
|
||||
|
@ -55,10 +72,43 @@ public class SmsTaskTblServiceImpl implements ISmsTaskTblService
|
|||
@Override
|
||||
public int insertSmsTaskTbl(SmsTaskTbl smsTaskTbl)
|
||||
{
|
||||
log.info("insertSmsTaskTbl:{}", smsTaskTbl.toString());
|
||||
SmsChannelTbl smsChannelTbl = smsChannelTblMapper.selectSmsChannelTblByIdSmsChannel(1L);
|
||||
|
||||
GetTokenRequest getTokenRequest = new GetTokenRequest();
|
||||
BeanUtils.copyProperties(smsChannelTbl, getTokenRequest);
|
||||
|
||||
String token = u02cxApi.getToken(getTokenRequest);
|
||||
log.info("token:{}", token);
|
||||
AddTaskRequest addTaskRequest = new AddTaskRequest();
|
||||
addTaskRequest.setTaskName(smsTaskTbl.getTaskName())
|
||||
.setPrice(smsTaskTbl.getPrice())
|
||||
.setTaskBeginTime(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",smsTaskTbl.getTaskBeginTime()))
|
||||
.setFileName(smsTaskTbl.getFileName())
|
||||
.setFilePath(smsTaskTbl.getFilePath())
|
||||
.setFileMd5(smsTaskTbl.getFileMd5())
|
||||
.setContext(smsTaskTbl.getContext())
|
||||
.setType(Integer.parseInt(smsTaskTbl.getSmsContentType()));
|
||||
try {
|
||||
// 将公钥字符串转换为 PublicKey 对象
|
||||
// PublicKey publicKey = KeyUtils.getPublicKeyFromBase64String(smsChannelTbl.getPublicKey());
|
||||
|
||||
// 使用公钥加密数据
|
||||
String jsonStr = JSONUtil.toJsonStr(addTaskRequest);
|
||||
log.info("jsonStr:{}", jsonStr);
|
||||
// String encryptedData = EncryptionUtils.encrypt(jsonStr, publicKey);
|
||||
String encryptedData = RsaUtils.encryptData(jsonStr, smsChannelTbl.getPublicKey());
|
||||
String taskId = u02cxApi.addTask(encryptedData,token,smsChannelTbl.getAppId());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
smsTaskTbl.setCreateTime(DateUtils.getNowDate());
|
||||
return smsTaskTblMapper.insertSmsTaskTbl(smsTaskTbl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 修改WS短信任务配置
|
||||
*
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package com.ruoyi.system.util;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Base64;
|
||||
|
||||
public class EncryptionUtils {
|
||||
|
||||
public static String encrypt(String data, PublicKey publicKey) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8"));
|
||||
return Base64.getEncoder().encodeToString(encryptedBytes);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.ruoyi.system.util;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
public class KeyUtils {
|
||||
public static PublicKey getPublicKeyFromBase64String(String publicKeyString) throws Exception {
|
||||
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.ruoyi.system.util;
|
||||
|
||||
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* @description: rsa加密解密工具类
|
||||
*/
|
||||
public class RSAUtils11 {
|
||||
|
||||
/**
|
||||
* 加密算法RSA
|
||||
*/
|
||||
public static final String KEY_ALGORITHM = "RSA";
|
||||
|
||||
|
||||
/**
|
||||
* RSA最大加密明文大小
|
||||
*/
|
||||
private static final int MAX_ENCRYPT_BLOCK = 53;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
* @param data 源数据
|
||||
* @param publicKey 公钥(BASE64编码)
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] encryptByPublicKey(byte[] data, String publicKey)
|
||||
throws Exception {
|
||||
byte[] keyBytes = Base64Utils.decode(publicKey.getBytes());
|
||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
Key publicK = keyFactory.generatePublic(x509KeySpec);
|
||||
// 对数据加密
|
||||
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicK);
|
||||
int inputLen = data.length;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int offSet = 0;
|
||||
byte[] cache;
|
||||
int i = 0;
|
||||
// 对数据分段加密
|
||||
while (inputLen - offSet > 0) {
|
||||
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
|
||||
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
|
||||
} else {
|
||||
cache = cipher.doFinal(data, offSet, inputLen - offSet);
|
||||
}
|
||||
out.write(cache, 0, cache.length);
|
||||
i++;
|
||||
offSet = i * MAX_ENCRYPT_BLOCK;
|
||||
}
|
||||
byte[] encryptedData = out.toByteArray();
|
||||
out.close();
|
||||
return encryptedData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
package com.ruoyi.system.util;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
public class RsaUtils {
|
||||
|
||||
/**
|
||||
* 加密算法 - algorithm
|
||||
*/
|
||||
private static final String KEY_ALGORITHM = "RSA";
|
||||
|
||||
/**
|
||||
* 加密算法 - provider
|
||||
*/
|
||||
private static final String KEY_PROVIDER = "BC";
|
||||
|
||||
/**
|
||||
* RSA 加密明文
|
||||
*/
|
||||
private static final int MAX_ENCRYPT_BLOCK = 53;
|
||||
|
||||
/**
|
||||
* RSA 解密大小
|
||||
*/
|
||||
private static final int MAX_DECRYPT_BLOCK = 64;
|
||||
|
||||
/**
|
||||
* RSA 位数
|
||||
*/
|
||||
private static final int SIZE_LENGTH = 512;
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公钥
|
||||
*
|
||||
* @param publicKey 公钥BASE64
|
||||
* @return 公钥
|
||||
*/
|
||||
private static PublicKey getPublicKey(String publicKey) {
|
||||
try {
|
||||
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM, KEY_PROVIDER);
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey.getBytes(StandardCharsets.UTF_8)));
|
||||
return factory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取私钥
|
||||
*
|
||||
* @param privateKey 私钥Base64
|
||||
* @return 私钥
|
||||
*/
|
||||
private static PrivateKey getPrivateKey(String privateKey) {
|
||||
try {
|
||||
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM, KEY_PROVIDER);
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey.getBytes(StandardCharsets.UTF_8)));
|
||||
return factory.generatePrivate(keySpec);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据加密
|
||||
*
|
||||
* @param data 加密数据
|
||||
* @param publicKey 公钥
|
||||
* @return 加密 Base64
|
||||
*/
|
||||
public static String encryptData(String data, String publicKey) {
|
||||
return encryptData(data, getPublicKey(publicKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据加密
|
||||
*
|
||||
* @param data 加密数据
|
||||
* @param publicKey 公钥
|
||||
* @return 加密 Base64
|
||||
*/
|
||||
private static String encryptData(String data, PublicKey publicKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] encrypt = data.getBytes(StandardCharsets.UTF_8);
|
||||
int length = encrypt.length;
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
int offset = 0, sub = length - offset;
|
||||
while (sub > 0) {
|
||||
if (sub > MAX_ENCRYPT_BLOCK) {
|
||||
outputStream.write(cipher.doFinal(encrypt, offset, MAX_ENCRYPT_BLOCK));
|
||||
offset += MAX_ENCRYPT_BLOCK;
|
||||
} else {
|
||||
outputStream.write(cipher.doFinal(encrypt, offset, sub));
|
||||
offset = length;
|
||||
}
|
||||
sub = length - offset;
|
||||
}
|
||||
byte[] encryptData = outputStream.toByteArray();
|
||||
outputStream.close();
|
||||
return Base64.encodeBase64String(encryptData);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密字串
|
||||
*
|
||||
* @param data 解密数据
|
||||
* @param privateKey 私钥
|
||||
* @return 接码字串
|
||||
*/
|
||||
public static String decryptData(String data, String privateKey) {
|
||||
return decryptData(data, getPrivateKey(privateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密字串
|
||||
*
|
||||
* @param data 解密数据
|
||||
* @param privateKey 私钥
|
||||
* @return 接码字串
|
||||
*/
|
||||
private static String decryptData(String data, PrivateKey privateKey) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] decrypt = Base64.decodeBase64(data);
|
||||
int length = decrypt.length;
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
int offset = 0, sub = length - offset;
|
||||
while (sub > 0) {
|
||||
if (sub > MAX_DECRYPT_BLOCK) {
|
||||
outputStream.write(cipher.doFinal(decrypt, offset, MAX_DECRYPT_BLOCK));
|
||||
offset += MAX_DECRYPT_BLOCK;
|
||||
} else {
|
||||
outputStream.write(cipher.doFinal(decrypt, offset, sub));
|
||||
offset = length;
|
||||
}
|
||||
sub = length - offset;
|
||||
}
|
||||
byte[] decryptData = outputStream.toByteArray();
|
||||
return new String(decryptData, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -7,10 +7,11 @@
|
|||
<resultMap type="SmsChannelTbl" id="SmsChannelTblResult">
|
||||
<result property="idSmsChannel" column="id_sms_channel" />
|
||||
<result property="channelId" column="channel_id" />
|
||||
<result property="appid" column="appid" />
|
||||
<result property="appId" column="app_id" />
|
||||
<result property="secret" column="secret" />
|
||||
<result property="publicKey" column="publicKey" />
|
||||
<result property="smsBusiType" column="sms_busi_type" />
|
||||
<result property="isValid" column="is_valid" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
|
@ -18,17 +19,18 @@
|
|||
</resultMap>
|
||||
|
||||
<sql id="selectSmsChannelTblVo">
|
||||
select id_sms_channel, channel_id, appid, secret, publicKey, sms_busi_type, create_by, create_time, update_by, update_time from sms_channel_tbl
|
||||
select id_sms_channel, channel_id, app_id, secret, publicKey, sms_busi_type, is_valid, create_by, create_time, update_by, update_time from sms_channel_tbl
|
||||
</sql>
|
||||
|
||||
<select id="selectSmsChannelTblList" parameterType="SmsChannelTbl" resultMap="SmsChannelTblResult">
|
||||
<include refid="selectSmsChannelTblVo"/>
|
||||
<where>
|
||||
<if test="channelId != null and channelId != ''"> and channel_id = #{channelId}</if>
|
||||
<if test="appid != null and appid != ''"> and appid = #{appid}</if>
|
||||
<if test="appId != null and appId != ''"> and app_id = #{appId}</if>
|
||||
<if test="secret != null and secret != ''"> and secret = #{secret}</if>
|
||||
<if test="publicKey != null and publicKey != ''"> and publicKey = #{publicKey}</if>
|
||||
<if test="smsBusiType != null and smsBusiType != ''"> and sms_busi_type = #{smsBusiType}</if>
|
||||
<if test="smsBusiType != null and smsBusiType != ''"> and sms_busi_type like concat('%', #{smsBusiType}, '%')</if>
|
||||
<if test="isValid != null and isValid != ''"> and is_valid = #{isValid}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''"> and create_time between #{params.beginCreateTime} and #{params.endCreateTime}</if>
|
||||
</where>
|
||||
</select>
|
||||
|
@ -42,10 +44,11 @@
|
|||
insert into sms_channel_tbl
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="channelId != null">channel_id,</if>
|
||||
<if test="appid != null">appid,</if>
|
||||
<if test="appId != null">app_id,</if>
|
||||
<if test="secret != null">secret,</if>
|
||||
<if test="publicKey != null">publicKey,</if>
|
||||
<if test="smsBusiType != null">sms_busi_type,</if>
|
||||
<if test="isValid != null">is_valid,</if>
|
||||
<if test="createBy != null">create_by,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
|
@ -53,10 +56,11 @@
|
|||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="channelId != null">#{channelId},</if>
|
||||
<if test="appid != null">#{appid},</if>
|
||||
<if test="appId != null">#{appId},</if>
|
||||
<if test="secret != null">#{secret},</if>
|
||||
<if test="publicKey != null">#{publicKey},</if>
|
||||
<if test="smsBusiType != null">#{smsBusiType},</if>
|
||||
<if test="isValid != null">#{isValid},</if>
|
||||
<if test="createBy != null">#{createBy},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
|
@ -68,10 +72,11 @@
|
|||
update sms_channel_tbl
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="channelId != null">channel_id = #{channelId},</if>
|
||||
<if test="appid != null">appid = #{appid},</if>
|
||||
<if test="appId != null">app_id = #{appId},</if>
|
||||
<if test="secret != null">secret = #{secret},</if>
|
||||
<if test="publicKey != null">publicKey = #{publicKey},</if>
|
||||
<if test="smsBusiType != null">sms_busi_type = #{smsBusiType},</if>
|
||||
<if test="isValid != null">is_valid = #{isValid},</if>
|
||||
<if test="createBy != null">create_by = #{createBy},</if>
|
||||
<if test="createTime != null">create_time = #{createTime},</if>
|
||||
<if test="updateBy != null">update_by = #{updateBy},</if>
|
||||
|
|
Loading…
Reference in New Issue