diff --git a/txw-common/.gitignore b/txw-common/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/txw-common/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/txw-common/README.md b/txw-common/README.md new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/txw-common/README.md @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/txw-common/pom.xml b/txw-common/pom.xml new file mode 100644 index 0000000..e37ddf8 --- /dev/null +++ b/txw-common/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + com.css.ggzc + ggzc-framework-dependencies + 1.0.0-SNAPSHOT + + txw-common + com.css.txw + 1.0.0-SNAPSHOT + ${project.artifactId} + txw-common + + ${project.artifactId} + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + + + + + + codingcorp-qyd_repo-mvn_public + mvn_public + http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/ + + + + + + com.css.ggzc + ggzc-framework-starter + 1.0.0-SNAPSHOT + pom + import + + + + + + + + com.css.ggzc + ggzc-framework-starter-web + + + + com.css.ggzc + ggzc-framework-starter-common + + + + com.css.ggzc + ggzc-framework-starter-cache + + + + com.css.ggzc + ggzc-framework-starter-mybatis + + + + com.css.ggzc + ggzc-framework-starter-cache + + + + com.alibaba + easyexcel + + + diff --git a/txw-common/settings.xml b/txw-common/settings.xml new file mode 100644 index 0000000..e089e4a --- /dev/null +++ b/txw-common/settings.xml @@ -0,0 +1,61 @@ + + + + + + + codingcorp-qyd_repo-mvn_public + coding-user + coding-pwd + + + + + + + Repository Proxy + + true + + + + + codingcorp-qyd_repo-mvn_public + mvn_public + http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/ + + true + + + true + always + + + + + + codingcorp-qyd_repo-mvn_public + + true + + + true + + http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/ + + + + + + + + codingcorp-qyd_repo-mvn_public + + central + mvn_public + http://codingcorp-maven.pkg.codingstd.xc01.cloud.sat.tax/repository/qyd_repo/mvn_public/ + + + diff --git a/txw-common/src/main/java/com/css/txw/common/configuration/SMSConfig.java b/txw-common/src/main/java/com/css/txw/common/configuration/SMSConfig.java new file mode 100644 index 0000000..c7af893 --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/configuration/SMSConfig.java @@ -0,0 +1,30 @@ +package com.css.txw.common.configuration; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * @Description: 短信配置 + * @Autor wujy + * @Date 2025/11/21 + */ +@Data +@RefreshScope +@Configuration +@ConfigurationProperties(prefix = "css.txw.sms") +public class SMSConfig { + + private String host; + + //app:请求应用的唯一标识,例如:OA + private String app; + + //key:双方系统约定的密钥 + private String key; + + //短信内容模版 + private String template; + +} diff --git a/txw-common/src/main/java/com/css/txw/common/configuration/SMSConstant.java b/txw-common/src/main/java/com/css/txw/common/configuration/SMSConstant.java new file mode 100644 index 0000000..169459f --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/configuration/SMSConstant.java @@ -0,0 +1,11 @@ +package com.css.txw.common.configuration; + +/** + * @Description: 短信服务相关 + * @Autor wujy + * @Date 2025/11/21 + */ +public class SMSConstant { + public static final String SEND_SM_URI = "/nbsgd/messageApi/smsmessage/send"; + +} diff --git a/txw-common/src/main/java/com/css/txw/common/configuration/TxwCommonConfiguration.java b/txw-common/src/main/java/com/css/txw/common/configuration/TxwCommonConfiguration.java new file mode 100644 index 0000000..9ea963b --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/configuration/TxwCommonConfiguration.java @@ -0,0 +1,10 @@ +package com.css.txw.common.configuration; + +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@AutoConfiguration +@ComponentScan("com.css.txw.common") +public class TxwCommonConfiguration { + +} diff --git a/txw-common/src/main/java/com/css/txw/common/net/HttpHutoolImpl.java b/txw-common/src/main/java/com/css/txw/common/net/HttpHutoolImpl.java new file mode 100644 index 0000000..465bd22 --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/net/HttpHutoolImpl.java @@ -0,0 +1,87 @@ +package com.css.txw.common.net; + +import cn.hutool.http.Header; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.http.HttpUtil; +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.util.Map; + +@Slf4j +@Service +public class HttpHutoolImpl implements IHttpService { + + public final static String CONTENT_TYPE_JSON = "application/json"; + public final static String CONTENT_TYPE_FORM = "multipart/form-data;"; + public final static String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"; + public final static String ACCEPT = "application/json, text/plain, */*"; + + public HttpResponse get(String url) { + HttpRequest request = HttpUtil.createGet(url); + return this.executeReq(request); + } + + @Override + public HttpResponse get(String url, Map params) { + HttpRequest request = HttpUtil.createGet(url); + request.form(params); + return this.executeReq(request); + } + + @Override + public HttpResponse postForm(String url, Map form) { + HttpRequest request = HttpUtil.createPost(url); + request.form(form); + return this.executeReq(request, CONTENT_TYPE_FORM); + } + + @Override + public HttpResponse postForm(String url, Map form, Map files) { + HttpRequest request = HttpUtil.createPost(url); + request.form(form); + if (null != files) { + for (String key : files.keySet()) { + request.form(key, files.get(key), files.get(key).getName()); + } + request.timeout(1000 * 60); + } + return this.executeReq(request, CONTENT_TYPE_FORM); + } + + @Override + public T postJson(String url, String body, Class resType) { + HttpRequest request = HttpUtil.createPost(url); + if (StringUtils.isNotBlank(body)) { + request.body(body); + } + try { + HttpResponse response = this.executeReq(request); + if (response.isOk()) { + String resBody = response.body(); + log.info("Hutool http response body: {}", resBody); + return new Gson().fromJson(resBody, resType); + } else { + log.info("请求失败,状态码:{}", response.getStatus()); + } + } catch (Exception e) { + log.error("error:", e); + } + return null; + } + + private HttpResponse executeReq(HttpRequest request) { + return this.executeReq(request, CONTENT_TYPE_JSON); + } + + private HttpResponse executeReq(HttpRequest request,String contentType) { + request.contentType(contentType).header(Header.USER_AGENT, USER_AGENT).header(Header.ACCEPT, ACCEPT); + return request.execute(); + } + + +} diff --git a/txw-common/src/main/java/com/css/txw/common/net/IHttpService.java b/txw-common/src/main/java/com/css/txw/common/net/IHttpService.java new file mode 100644 index 0000000..3539dda --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/net/IHttpService.java @@ -0,0 +1,17 @@ +package com.css.txw.common.net; + +import cn.hutool.http.HttpResponse; + +import java.io.File; +import java.util.Map; + +public interface IHttpService { + + HttpResponse get(String url, Map params); + + HttpResponse postForm(String url, Map form); + + HttpResponse postForm(String url, Map form, Map files); + + T postJson(String url, String body, Class resType); +} diff --git a/txw-common/src/main/java/com/css/txw/common/pojo/ExcelVerifyInfo.java b/txw-common/src/main/java/com/css/txw/common/pojo/ExcelVerifyInfo.java new file mode 100644 index 0000000..a6587bd --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/pojo/ExcelVerifyInfo.java @@ -0,0 +1,10 @@ +package com.css.txw.common.pojo; + +import lombok.Data; + +@Data +public class ExcelVerifyInfo { + private String errorMsg; + private Integer rowNum; + +} diff --git a/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMCaptchaDTO.java b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMCaptchaDTO.java new file mode 100644 index 0000000..44c1a3d --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMCaptchaDTO.java @@ -0,0 +1,17 @@ +package com.css.txw.common.pojo.dto.sms; + +import lombok.Data; + +/** + * @Description: 发送短信验证码,根据配置模版格式发送验证码 + * @Autor wujy + * @Date 2025/11/21 + */ +@Data +public class SMCaptchaDTO { + //接收手机号码 "1311111111,1352222222" + private String receiveMobile; + //验证码 + private String captcha; + +} diff --git a/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSReqDTO.java b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSReqDTO.java new file mode 100644 index 0000000..34665a9 --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSReqDTO.java @@ -0,0 +1,19 @@ +package com.css.txw.common.pojo.dto.sms; + +import lombok.Data; + +/** + * @Description: 短信发送报文 + * @Autor wujy + * @Date 2025/11/21 + */ +@Data +public class SMSReqDTO { + //接收手机号码 "1311111111,1352222222" + private String receiveMobile; + //短信内容 + private String content; + //发送时间, 自定义发送时间,空或小于当前时间立即发送 + private String sendTime; + +} diff --git a/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSResDTO.java b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSResDTO.java new file mode 100644 index 0000000..f30cccb --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/pojo/dto/sms/SMSResDTO.java @@ -0,0 +1,17 @@ +package com.css.txw.common.pojo.dto.sms; + +import lombok.Data; + +/** + * @Description: 短信服务响应报文 + * @Autor wujy + * @Date 2025/11/21 + */ +@Data +public class SMSResDTO { + private String code;//返回代码值 + private String type;//枚举型,包括:success、error + private String token;//请求服务时传递的唯一标识UUID + private String message;//返回消息 + private T data;//返回数据内容 +} diff --git a/txw-common/src/main/java/com/css/txw/common/service/ISMService.java b/txw-common/src/main/java/com/css/txw/common/service/ISMService.java new file mode 100644 index 0000000..b3447cc --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/service/ISMService.java @@ -0,0 +1,9 @@ +package com.css.txw.common.service; + +import com.css.txw.common.pojo.dto.sms.SMCaptchaDTO; +import com.css.txw.common.pojo.dto.sms.SMSResDTO; + +public interface ISMService { + + SMSResDTO sendCaptcha(String phone, String code); +} diff --git a/txw-common/src/main/java/com/css/txw/common/service/impl/SMServiceImpl.java b/txw-common/src/main/java/com/css/txw/common/service/impl/SMServiceImpl.java new file mode 100644 index 0000000..e46b7d2 --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/service/impl/SMServiceImpl.java @@ -0,0 +1,62 @@ +package com.css.txw.common.service.impl; + +import cn.hutool.crypto.digest.DigestUtil; +import com.css.ggzc.framework.common.util.gy.GyUtils; +import com.css.txw.common.configuration.SMSConfig; +import com.css.txw.common.configuration.SMSConstant; +import com.css.txw.common.net.IHttpService; +import com.css.txw.common.pojo.dto.sms.SMSReqDTO; +import com.css.txw.common.pojo.dto.sms.SMSResDTO; +import com.css.txw.common.service.ISMService; +import com.css.txw.common.util.TxwHttpUtils; +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Date; + +/** + * @Description: 短信服务 + * @Autor wujy + * @Date 2025/11/21 + */ +@Slf4j +@Service +public class SMServiceImpl implements ISMService { + + @Resource + private SMSConfig config; + @Resource + private IHttpService httpService; + + //发送短信验证码 + @Override + public SMSResDTO sendCaptcha(String phone, String code) { + //时间戳,如:1611472667681 + long timestamp = new Date().getTime(); + String app = config.getApp(); + //请求唯一标识,使用UUID + String token = GyUtils.getUuid(); + //校验码,使用timestamp+app+token+key进行MD5加密后的字符再进行性一次加密最后形成校验码 + String vcode = DigestUtil.md5Hex(DigestUtil.md5Hex(timestamp + app + token + config.getKey())); + String url = config.getHost() + SMSConstant.SEND_SM_URI + "?timestamp=" + timestamp + "&token=" + token + + "&app=" + app + "&vcode=" + vcode; + //构建报文 + String content = String.format(config.getTemplate(), code); + SMSReqDTO smReqDTO = new SMSReqDTO(); + smReqDTO.setReceiveMobile(phone); + smReqDTO.setContent(content); + //发送 + SMSResDTO res = httpService.postJson(url, new Gson().toJson(smReqDTO), SMSResDTO.class); + log.info("短信发送 Response {}, code:{} message:{}", res.getType(),res.getCode(), res.getMessage()); + return res; + } + + // 发送其他短信 + public String sendMsg(SMSReqDTO reqDTO) { + // to do something + return null; + } + +} diff --git a/txw-common/src/main/java/com/css/txw/common/util/TxwHttpUtils.java b/txw-common/src/main/java/com/css/txw/common/util/TxwHttpUtils.java new file mode 100644 index 0000000..ba35261 --- /dev/null +++ b/txw-common/src/main/java/com/css/txw/common/util/TxwHttpUtils.java @@ -0,0 +1,289 @@ +package com.css.txw.common.util; + +import com.css.ggzc.framework.cache.utils.XtcsUtils; +import com.css.ggzc.framework.common.util.gy.GyUtils; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.net.Proxy; +import java.util.Map; + +/** + * 基于Spring Cloud Alibaba的HTTP工具类 + * 支持GET、POST、PUT、DELETE请求,兼容HTTP/HTTPS协议 + * 支持Nacos服务发现和负载均衡 + * 版本:Spring Cloud Alibaba 2021.0.6.0 + */ +@Slf4j +@Component +public class TxwHttpUtils { + + @Resource + private RestTemplate restTemplate = new RestTemplate(); + + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @PostConstruct + public void init() { + log.info("SpringCloudAlibabaHttpUtil initialized successfully with Spring Cloud Alibaba 2021.0.6.0"); + } + + // ========== GET请求方法 ========== + + /** + * GET请求 - 直接URL调用 + */ + public T get(String url, Class responseType) { + return get(url, null, responseType, null); + } + + public T get(String url, Map params, Class responseType) { + return get(url, params, responseType, null); + } + + public T get(String url, Map params, Class responseType, + Map headers) { + try { + HttpEntity entity = createHttpEntity(null, headers); + ResponseEntity response = restTemplate.exchange( + buildUrlWithParams(url, params), + HttpMethod.GET, + entity, + responseType + ); + return handleResponse(response); + } catch (Exception e) { + log.error("GET请求失败, url: {}", url, e); + throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); + } + } + + // ========== POST请求方法 ========== + + /** + * POST请求 - 直接URL调用 + */ + public T post(String url, Object requestBody, Class responseType) { + return post(url, requestBody, responseType, null); + } + + public T post(String url, Object requestBody, Class responseType, + Map headers) { + try { + HttpEntity entity = createHttpEntity(requestBody, headers); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.POST, + entity, + responseType + ); + return handleResponse(response); + } catch (Exception e) { + log.error("POST请求失败, url: {}", url, e); + throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); + } + } + + // ========== PUT请求方法 ========== + + /** + * PUT请求 - 直接URL调用 + */ + public T put(String url, Object requestBody, Class responseType) { + return put(url, requestBody, responseType, null); + } + + public T put(String url, Object requestBody, Class responseType, + Map headers) { + try { + HttpEntity entity = createHttpEntity(requestBody, headers); + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.PUT, + entity, + responseType + ); + return handleResponse(response); + } catch (Exception e) { + log.error("PUT请求失败, url: {}", url, e); + throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); + } + } + + // ========== DELETE请求方法 ========== + + /** + * DELETE请求 - 直接URL调用 + */ + public T delete(String url, Class responseType) { + return delete(url, null, responseType, null); + } + + public T delete(String url, Map params, Class responseType) { + return delete(url, params, responseType, null); + } + + public T delete(String url, Map params, Class responseType, + Map headers) { + try { + HttpEntity entity = createHttpEntity(null, headers); + ResponseEntity response = restTemplate.exchange( + buildUrlWithParams(url, params), + HttpMethod.DELETE, + entity, + responseType + ); + return handleResponse(response); + } catch (Exception e) { + log.error("DELETE请求失败, url: {}", url, e); + throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); + } + } + + // ========== 通用请求方法 ========== + + /** + * 通用请求方法 + */ + public T exchange(String url, HttpMethod method, Object requestBody, + Map headers, Class responseType) { + try { + ResponseEntity response; + RestTemplate restTemplateWithProxy = createRestTemplateWithProxy(); + HttpEntity entity = createHttpEntity(requestBody, headers); + if (GyUtils.isNotNull(restTemplateWithProxy)) { + response = restTemplateWithProxy.exchange(url, method, entity, responseType); + } else { + response = restTemplate.exchange(url, method, entity, responseType); + } + return handleResponse(response); + } catch (Exception e) { + log.error("{}请求失败, url: {}", method.name(), url, e); + throw new RuntimeException("HTTP请求失败: " + e.getMessage(), e); + } + } + + // ========== 辅助方法 ========== + + /** + * 构建带参数的URL + */ + private String buildUrlWithParams(String url, Map params) { + if (params == null || params.isEmpty()) { + return url; + } + + StringBuilder urlBuilder = new StringBuilder(url); + boolean hasQuery = url.contains("?"); + + for (Map.Entry entry : params.entrySet()) { + if (entry.getValue() == null) continue; + + if (!hasQuery) { + urlBuilder.append("?"); + hasQuery = true; + } else { + urlBuilder.append("&"); + } + + urlBuilder.append(entry.getKey()) + .append("=") + .append(encodeParam(entry.getValue().toString())); + } + + return urlBuilder.toString(); + } + + /** + * 参数编码 + */ + private String encodeParam(String param) { + try { + return java.net.URLEncoder.encode(param, "UTF-8"); + } catch (Exception e) { + log.warn("参数编码失败: {}", param, e); + return param; + } + } + + /** + * 创建HTTP实体 + */ + private HttpEntity createHttpEntity(Object requestBody, Map headers) { + HttpHeaders httpHeaders = new HttpHeaders(); + + // 设置默认头 + if (requestBody instanceof MultiValueMap) { + httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + } else if (requestBody != null) { + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + } + + // 添加自定义头 + if (headers != null) { + headers.forEach(httpHeaders::add); + } + + return new HttpEntity<>(requestBody, httpHeaders); + } + + /** + * 处理响应 + */ + private T handleResponse(ResponseEntity response) { + if (response.getStatusCode().is2xxSuccessful()) { + return response.getBody(); + } else { + String errorMsg = String.format("HTTP请求失败, 状态码: %d, 响应: %s", + response.getStatusCodeValue(), response.getBody()); + log.error(errorMsg); + throw new RuntimeException(errorMsg); + } + } + + /** + * 将对象转换为MultiValueMap(用于表单提交) + */ + public MultiValueMap convertToFormData(Object obj) { + try { + MultiValueMap formData = new LinkedMultiValueMap<>(); + Map map = objectMapper.convertValue(obj, new TypeReference>() {}); + + map.forEach((key, value) -> { + if (value != null) { + formData.add(key, value.toString()); + } + }); + + return formData; + } catch (Exception e) { + log.error("对象转换表单数据失败", e); + throw new RuntimeException("对象转换失败", e); + } + } + + public RestTemplate createRestTemplateWithProxy() { + // 设置代理 + Proxy proxy = XtcsUtils.getSystemHttpProxy(); + if (GyUtils.isNotNull(proxy)) { + SimpleClientHttpRequestFactory requestFactory = + new SimpleClientHttpRequestFactory(); + // 设置超时时间 + requestFactory.setConnectTimeout(5000); + requestFactory.setReadTimeout(10000); + requestFactory.setProxy(proxy); + return new RestTemplate(requestFactory); + } + return null; + } +} \ No newline at end of file diff --git a/txw-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/txw-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..30f92f1 --- /dev/null +++ b/txw-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.css.txw.common.configuration.TxwCommonConfiguration \ No newline at end of file diff --git a/txw-common/src/main/resources/spring-configuration-metadata.json b/txw-common/src/main/resources/spring-configuration-metadata.json new file mode 100644 index 0000000..b614960 --- /dev/null +++ b/txw-common/src/main/resources/spring-configuration-metadata.json @@ -0,0 +1,37 @@ +{ + "groups": [ + { + "name": "css.txw.sms", + "type": "com.css.txw.common.configuration.SMSConfig", + "sourceType": "com.css.txw.common.configuration.SMSConfig" + } + ], + "properties": [ + { + "name": "css.txw.sms.host", + "type": "java.lang.String", + "description": "short message service host", + "sourceType": "com.css.txw.common.configuration.SMSConfig" + }, + { + "name": "css.txw.sms.app", + "type": "java.lang.String", + "description": "app name", + "sourceType": "com.css.txw.common.configuration.SMSConfig" + }, + { + "name": "css.txw.sms.key", + "type": "java.lang.String", + "description": "app key", + "sourceType": "com.css.txw.common.configuration.SMSConfig" + }, + { + "name": "css.txw.sms.template", + "type": "java.lang.String", + "description": "short message content template", + "sourceType": "com.css.txw.common.configuration.SMSConfig" + } + ], + "hints": [ + ] +}