短信平台使用的是阿裡雲的短信服務,jeecgboot已內建短信發送功能,但沒有儲存短信結果,不友善一些業務的統計
建立一個短信結果對象
@Data
public class SmsResult implements Serializable {
private String mobile;
private Boolean success;
private String code;
private String message;
private String requestId;
private String bizId;
private Integer smsType;
}
DySmsHelper中新增一個短信發送方法
/**
* @param phone 短信号碼,可以是用逗号分隔的字元串,此時是群發,最多是1000個号碼
* @param templateParamJson
* @param dySmsEnum
* @return
* @throws ClientException
*/
public static SmsResult sendSmsForResult(String phone, JSONObject templateParamJson, DySmsEnum dySmsEnum) throws ClientException {
//可自助調整逾時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//update-begin-author:taoyan date:20200811 for:配置類資料擷取
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
setAccessKeyId(staticConfig.getAccessKeyId());
setAccessKeySecret(staticConfig.getAccessKeySecret());
//update-end-author:taoyan date:20200811 for:配置類資料擷取
//初始化acsClient,暫不支援region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//驗證json參數
validateParam(templateParamJson, dySmsEnum);
//組裝請求對象-具體描述見控制台-文檔部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待發送手機号
request.setPhoneNumbers(phone);
//必填:短信簽名-可在短信控制台中找到
request.setSignName(dySmsEnum.getSignName());
//必填:短信模闆-可在短信控制台中找到
request.setTemplateCode(dySmsEnum.getTemplateCode());
//可選:模闆中的變量替換JSON串,如模闆内容為"親愛的${name},您的驗證碼為${code}"時,此處的值為
request.setTemplateParam(templateParamJson.toJSONString());
//選填-上行短信擴充碼(無特殊需求使用者請忽略此字段)
//request.setSmsUpExtendCode("90997");
//可選:outId為提供給業務方擴充字段,最終在短信回執消息中将此值帶回給調用者
//request.setOutId("yourOutId");
//hint 此處可能會抛出異常,注意catch
SmsResult result = new SmsResult();
result.setMobile(phone);
switch (dySmsEnum) {
case REGISTER_TEMPLATE_CODE:
result.setSmsType(SmsTypeEnum.Reg.getCode());
break;
case FORGET_PASSWORD_TEMPLATE_CODE:
result.setSmsType(SmsTypeEnum.Forget.getCode());
break;
case MEET_NOTICE_TEMPLATE_CODE:
result.setSmsType(SmsTypeEnum.Notice.getCode());
break;
default:
result.setSmsType(SmsTypeEnum.Other.getCode());
}
try {
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
logger.info("短信接口傳回的資料----------------");
String bizId = sendSmsResponse.getBizId();
logger.info("{Code:" + sendSmsResponse.getCode() + ",Message:" + sendSmsResponse.getMessage() + ",RequestId:" + sendSmsResponse.getRequestId() + ",BizId:" + bizId + "}");
result.setSuccess(true);
result.setCode(sendSmsResponse.getCode());
result.setMessage(sendSmsResponse.getMessage());
result.setRequestId(sendSmsResponse.getRequestId());
result.setBizId(bizId);
} catch (Exception e) {
result.setSuccess(false);
result.setMessage(e.getMessage());
}
return result;
}
建立一個用于儲存的短信結果對象(建表後生成相關的實體,mapper,業務類)
/**
* @Description: 短信結果
* @Author: jeecg-boot
* @Date: 2022-03-23
* @Version: V1.0
*/
@Data
@TableName("meet_sms_result")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="meet_sms_result對象", description="短信結果")
public class SmsResult implements Serializable {
private static final long serialVersionUID = 1L;
/**id*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "id")
private java.lang.String id;
/**手機号碼*/
@Excel(name = "手機号碼", width = 15)
@ApiModelProperty(value = "手機号碼")
private java.lang.String mobile;
/**類型*/
@Excel(name = "類型", width = 15)
@ApiModelProperty(value = "類型")
private java.lang.Integer smsType;
/**是否成功*/
@Excel(name = "是否成功", width = 15)
@ApiModelProperty(value = "是否成功")
private java.lang.Boolean success;
/**代碼*/
@Excel(name = "代碼", width = 15)
@ApiModelProperty(value = "代碼")
private java.lang.String code;
/**傳回消息*/
@Excel(name = "傳回消息", width = 15)
@ApiModelProperty(value = "傳回消息")
private java.lang.String message;
/**requestId*/
@Excel(name = "requestId", width = 15)
@ApiModelProperty(value = "requestId")
private java.lang.String requestId;
/**bizId*/
@Excel(name = "bizId", width = 15)
@ApiModelProperty(value = "bizId")
private java.lang.String bizId;
/**建立人*/
@ApiModelProperty(value = "建立人")
private java.lang.String createBy;
/**建立日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "建立日期")
private java.util.Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private java.lang.String updateBy;
/**更新日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern="yyyy-MM-dd")
@ApiModelProperty(value = "更新日期")
private java.util.Date updateTime;
@ApiModelProperty(value = "發送時間")
private String sendDate;
@ApiModelProperty(value = "接收時間")
private String receiveDate;
@ApiModelProperty(value = "營運商狀态碼,DELIVERED是成功")
private String errCode;
/**
* 1:等待回執。
* 2:發送失敗。
* 3:發送成功。
*/
@ApiModelProperty(value = "短信發送狀态")
private String sendStatus;
public static SmsResult fromSendResult(org.jeecg.modules.base.entity.SmsResult result){
SmsResult r = new SmsResult();
r.setMobile(result.getMobile());
r.setSmsType(result.getSmsType());
r.setSuccess(result.getSuccess());
r.setCode(result.getCode());
r.setMessage(result.getMessage());
r.setRequestId(result.getRequestId());
r.setBizId(result.getBizId());
return r;
}
}
SmsResultServiceImpl中增加查詢短信結果并儲存的方法
/**
* 查詢發送結果
*
* @param phones
* @param bizId
* @return
*/
@Override
@Async("asyncServiceExecutor")
public void getSendDetail(String phones, String bizId, String sendDate, Integer smsType, String reserveRoomId, Boolean saveSmsResult) {
try {
Thread.sleep(10000L);
//可自助調整逾時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//update-begin-author:taoyan date:20200811 for:配置類資料擷取
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
DySmsHelper.setAccessKeyId(staticConfig.getAccessKeyId());
DySmsHelper.setAccessKeySecret(staticConfig.getAccessKeySecret());
//update-end-author:taoyan date:20200811 for:配置類資料擷取
//初始化acsClient,暫不支援region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", DySmsHelper.getAccessKeyId(), DySmsHelper.getAccessKeySecret());
try {
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
} catch (ClientException e) {
return;
}
IAcsClient acsClient = new DefaultAcsClient(profile);
String[] phoneList = phones.split(",");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat sendDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<SmsResult> list = new ArrayList<>();
List<ReservePerson> personList = new ArrayList<>();
for (String s : phoneList) {
QuerySendDetailsRequest detailsRequest = new QuerySendDetailsRequest();
detailsRequest.setPhoneNumber(s);
detailsRequest.setBizId(bizId);
if (StrUtil.isEmpty(sendDate)) {
detailsRequest.setSendDate(dateFormat.format(new Date()));
} else {
try {
Date parse = sendDateFormat.parse(sendDate);
String format = dateFormat.format(parse);
detailsRequest.setSendDate(format);
} catch (ParseException e) {
detailsRequest.setSendDate(dateFormat.format(new Date()));
}
}
detailsRequest.setPageSize(1L);
detailsRequest.setCurrentPage(1L);
QuerySendDetailsResponse acsResponse = null;
try {
acsResponse = acsClient.getAcsResponse(detailsRequest);
List<QuerySendDetailsResponse.SmsSendDetailDTO> smsSendDetailDTOs = acsResponse.getSmsSendDetailDTOs();
for (QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : smsSendDetailDTOs) {
log.info("查詢結果:{} , 接收時間:{},錯誤代碼:{},内容:{},電話号碼:{}",
smsSendDetailDTO.getSendStatus(), smsSendDetailDTO.getReceiveDate(),
smsSendDetailDTO.getErrCode(), smsSendDetailDTO.getContent(),
smsSendDetailDTO.getPhoneNum());
SmsResult result = new SmsResult();
result.setMobile(s);
result.setBizId(bizId);
result.setSmsType(smsType);
result.setSendDate(smsSendDetailDTO.getSendDate());
result.setReceiveDate(smsSendDetailDTO.getReceiveDate());
result.setSendStatus(smsSendDetailDTO.getSendStatus().toString());
result.setErrCode(smsSendDetailDTO.getErrCode());
list.add(result);
//如果是通知類短信,生成通知對象,儲存到參會人員表中
if (smsType.equals(SmsTypeEnum.Notice.getCode())) {
ReservePerson reservePerson = createReservePerson(result, reserveRoomId);
personList.add(reservePerson);
}
}
} catch (ClientException e) {
e.printStackTrace();
}
}
if (saveSmsResult) {
this.saveBatch(list);
}
if (smsType.equals(SmsTypeEnum.Notice.getCode())) {
this.saveNoticeResult(personList, reserveRoomId);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 使用短信結果生成參會人員短信通知對象
*
* @param smsResult
* @param reserveRoomId
* @return
*/
private ReservePerson createReservePerson(SmsResult smsResult, String reserveRoomId) {
ReservePerson reservePerson = new ReservePerson();
reservePerson.setReserveRoomId(reserveRoomId);
reservePerson.setBizId(smsResult.getBizId());
reservePerson.setMobile(smsResult.getMobile());
reservePerson.setSendSms(true);
reservePerson.setSendDate(smsResult.getSendDate());
reservePerson.setReceiveDate(smsResult.getReceiveDate());
reservePerson.setSendStatus(smsResult.getSendStatus().toString());
reservePerson.setErrCode(smsResult.getErrCode());
return reservePerson;
}
/**
* 儲存短信通知結果
*
* @param list
*/
private void saveNoticeResult(List<ReservePerson> list, String reserveRoomId) {
if (list.size() == 0) return;
List<String> phones = list.stream().map(f -> f.getMobile()).collect(Collectors.toList());
List<ReservePerson> records = reservePersonService.list(new LambdaQueryWrapper<ReservePerson>()
.eq(ReservePerson::getReserveRoomId, reserveRoomId)
.in(ReservePerson::getMobile, phones));
for (ReservePerson reservePerson : list) {
ReservePerson reservePerson1 = records.stream().filter(f -> f.getMobile().equals(reservePerson.getMobile())).findFirst().orElse(null);
if (reservePerson1 != null) {
reservePerson.setId(reservePerson1.getId());
}
}
reservePersonService.updateBatchById(list);
}
@ApiOperation(value = "參會人員-發送短信")
@PostMapping(value = "/sendSms")
public Result<?> sendSms(@RequestBody JSONObject jObj) {
Integer type = jObj.getInteger("type"); //發送類型: 1=全部發送,2=給選擇的号碼發送
String reserveRoomId = jObj.getString("reserveRoomId");
ReserveRoomVo vo = reserveRoomService.getVoByReserveRoomId(reserveRoomId);
if (vo == null) {
return Result.error("未找到預約會議室記錄");
}
List<String> phoneList = new ArrayList<>();
if(type==1){
phoneList=reservePersonService.getPhones(reserveRoomId);
}else{
JSONArray phones = jObj.getJSONArray("phones");
for (Object phone : phones) {
phoneList.add(phone.toString());
}
}
if(phoneList.size()==0){
return Result.error("未找到任何電話号碼");
}
if(phoneList.size()>1000){
return Result.error("一次最多發送1000條短信");
}
//短信參數
JSONObject obj = new JSONObject();
obj.put("time", String.format("%s %s - %s", vo.getMeetDate(), vo.getBeginTime(), vo.getEndTime()));
obj.put("place", vo.getCompanyName());
obj.put("content", vo.getTitle());
String phones = String.join(",",phoneList);
try {
SmsResult smsResult = DySmsHelper.sendSmsForResult(phones, obj, DySmsEnum.MEET_NOTICE_TEMPLATE_CODE);
if (smsResult.getCode().equals("OK")) {
smsResultService.getSendDetail(smsResult.getMobile(), smsResult.getBizId(),null, smsResult.getSmsType(), reserveRoomId,true);//開啟線程,查詢發送結果
return Result.OK();
}else{
return Result.error(smsResult.getMessage());
}
} catch (ClientException e) {
return Result.error(e.getMessage());
}
}
@ApiOperation(value = "參會人員-查詢短信發送結果")
@PostMapping(value="/getSmsResultDetail")
public Result<?> getSmsResultDetail(@RequestBody JSONObject jObj){
String reserveRoomId = jObj.getString("reserveRoomId");
String bizId = jObj.getString("bizId");
String sendDate = jObj.getString("sendDate");
List<ReservePerson> list = reservePersonService.list(new LambdaQueryWrapper<ReservePerson>().eq(ReservePerson::getReserveRoomId, reserveRoomId)
.eq(ReservePerson::getBizId, bizId));
List<String> collect = list.stream().map(f -> f.getMobile()).collect(Collectors.toList());
if(collect.size()>0){
String phones = String.join(",", collect);
smsResultService.getSendDetail(phones, bizId,sendDate, SmsTypeEnum.Notice.getCode(), reserveRoomId,false);//開啟線程,查詢發送結果
}
return Result.OK();
}
提醒您有一條會議短消息,茲定于${time}于${place}召開${content}會議,請準時參加。特此通知。