diff --git a/austin-common/src/main/java/com/java3y/austin/common/constant/AustinConstant.java b/austin-common/src/main/java/com/java3y/austin/common/constant/AustinConstant.java index dd060f0..2794c3a 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/constant/AustinConstant.java +++ b/austin-common/src/main/java/com/java3y/austin/common/constant/AustinConstant.java @@ -54,4 +54,12 @@ public class AustinConstant { public static final String CHARSET_NAME = "UTF-8"; + /** + * HTTP 请求方法 + */ + public static final String REQUEST_METHOD_GET = "GET"; + public static final String REQUEST_METHOD_POST = "POST"; + + + } diff --git a/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java new file mode 100644 index 0000000..f5aa376 --- /dev/null +++ b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java @@ -0,0 +1,54 @@ +package com.java3y.austin.common.constant; + + +/** + * 发送账号的常量信息汇总 + *

+ * (读取apollo的key和前缀) + *

+ * 约定:所有的账号都从10开始,步长为10 + * + * @author 3y + */ +public class SendAccountConstant { + + /** + * 钉钉 工作应用消息 账号 + */ + public static final String DING_DING_WORK_NOTICE_ACCOUNT_KEY = "dingDingWorkNoticeAccount"; + public static final String DING_DING_WORK_NOTICE_PREFIX = "ding_ding_work_notice_"; + public static final String DING_DING_ACCESS_TOKEN_PREFIX = "ding_ding_access_token_"; + + + /** + * 邮件 账号 + */ + public static final String EMAIL_ACCOUNT_KEY = "emailAccount"; + public static final String EMAIL_ACCOUNT_PREFIX = "email_"; + + + /** + * 钉钉群自定义机器人 账号 + */ + public static final String DING_DING_ROBOT_ACCOUNT_KEY = "dingDingRobotAccount"; + public static final String DING_DING_ROBOT_PREFIX = "ding_ding_robot_"; + + /** + * 企业微信 应用消息 账号 + */ + public static final String ENTERPRISE_WECHAT_ACCOUNT_KEY = "enterpriseWechatAccount"; + public static final String ENTERPRISE_WECHAT_PREFIX = "enterprise_wechat_"; + + + /** + * 短信 账号 + */ + public static final String SMS_ACCOUNT_KEY = "smsAccount"; + public static final String SMS_PREFIX = "sms_"; + + /** + * 账号约定:所有的账号都从10开始,步长为10 + */ + public static final Integer START = 10; + public static final Integer STEP = 10; +} diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/ContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/ContentModel.java index 03397e1..f71a0af 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/dto/model/ContentModel.java +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/ContentModel.java @@ -1,9 +1,14 @@ package com.java3y.austin.common.dto.model; +import java.io.Serializable; + /** * 发送内容的模型 * (不同的渠道会有不同的消息体) + * * @author 3y */ -public class ContentModel { +public class ContentModel implements Serializable { + + } diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/DingDingContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/DingDingContentModel.java index 3973258..18ac2f4 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/dto/model/DingDingContentModel.java +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/DingDingContentModel.java @@ -18,5 +18,21 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class DingDingContentModel extends ContentModel { + + /** + * 发送类型 + */ + private String sendType; + + /** + * 【文本消息】需要发送的内容 + */ private String content; + + /** + * 图片、文件、语音消息 需要发送使用的素材ID字段 + */ + private String mediaId; + + // ... } diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/EmailContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/EmailContentModel.java index 2764627..4b81311 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/dto/model/EmailContentModel.java +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/EmailContentModel.java @@ -7,6 +7,9 @@ import lombok.NoArgsConstructor; /** * @author 3y + *

+ *

+ * 邮件消息体 */ @Data @Builder diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/EnterpriseWeChatContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/EnterpriseWeChatContentModel.java index fc7dda5..2ff2209 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/dto/model/EnterpriseWeChatContentModel.java +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/EnterpriseWeChatContentModel.java @@ -18,7 +18,7 @@ public class EnterpriseWeChatContentModel extends ContentModel { /** * 下发企业微信消息的类型 */ - private String messageType; + private String sendType; /** * 文本消息 - 文案 diff --git a/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java b/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java index 645e7ec..3f9ce31 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java +++ b/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java @@ -14,7 +14,7 @@ import lombok.ToString; @AllArgsConstructor public enum SendMessageType { - TEST(10, "文本"), + TEXT(10, "文本"), VOICE(20, "语音"), VIDEO(30, "视频"), NEWS(40, "图文"), diff --git a/austin-cron/src/main/java/com/java3y/austin/cron/handler/RefreshDingDingAccessTokenHandler.java b/austin-cron/src/main/java/com/java3y/austin/cron/handler/RefreshDingDingAccessTokenHandler.java index e4b38d2..f2ce549 100644 --- a/austin-cron/src/main/java/com/java3y/austin/cron/handler/RefreshDingDingAccessTokenHandler.java +++ b/austin-cron/src/main/java/com/java3y/austin/cron/handler/RefreshDingDingAccessTokenHandler.java @@ -1,16 +1,20 @@ package com.java3y.austin.cron.handler; +import cn.hutool.core.util.StrUtil; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.DingTalkClient; import com.dingtalk.api.request.OapiGettokenRequest; import com.dingtalk.api.response.OapiGettokenResponse; +import com.google.common.base.Throwables; +import com.java3y.austin.common.constant.AustinConstant; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.dto.account.DingDingWorkNoticeAccount; import com.java3y.austin.support.config.SupportThreadPoolConfig; import com.java3y.austin.support.utils.AccountUtils; -import com.java3y.austin.support.utils.RedisUtils; import com.xxl.job.core.handler.annotation.XxlJob; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @@ -25,16 +29,11 @@ import org.springframework.stereotype.Service; @Slf4j public class RefreshDingDingAccessTokenHandler { - private static final String DING_DING_ROBOT_ACCOUNT_KEY = "dingDingWorkNoticeAccount"; - private static final String PREFIX = "ding_ding_work_notice_"; - private static final String URL = "https://oapi.dingtalk.com/gettoken"; - - @Autowired - private RedisUtils redisUtils; + private StringRedisTemplate redisTemplate; @Autowired private AccountUtils accountUtils; @@ -46,35 +45,38 @@ public class RefreshDingDingAccessTokenHandler { public void execute() { log.info("refreshAccessTokenJob#execute!"); SupportThreadPoolConfig.getPendingSingleThreadPool().execute(() -> { - for (int index = 10; index < 1000; index = index + 10) { - DingDingWorkNoticeAccount account = accountUtils.getAccount(10, DING_DING_ROBOT_ACCOUNT_KEY, PREFIX, new DingDingWorkNoticeAccount()); + for (int index = SendAccountConstant.START; true; index = index + SendAccountConstant.STEP) { + DingDingWorkNoticeAccount account = accountUtils.getAccount(index, SendAccountConstant.DING_DING_WORK_NOTICE_ACCOUNT_KEY, SendAccountConstant.DING_DING_WORK_NOTICE_PREFIX, new DingDingWorkNoticeAccount()); if (account == null) { break; } String accessToken = getAccessToken(account); - + if (StrUtil.isNotBlank(accessToken)) { + redisTemplate.opsForValue().set(SendAccountConstant.DING_DING_ACCESS_TOKEN_PREFIX + index, accessToken); + } } }); } /** * 获取 access_token + * * @param account * @return */ private String getAccessToken(DingDingWorkNoticeAccount account) { + String accessToken = ""; try { DingTalkClient client = new DefaultDingTalkClient(URL); OapiGettokenRequest req = new OapiGettokenRequest(); req.setAppkey(account.getAppKey()); req.setAppsecret(account.getAppSecret()); - req.setHttpMethod("GET"); + req.setHttpMethod(AustinConstant.REQUEST_METHOD_GET); OapiGettokenResponse rsp = client.execute(req); - System.out.println(rsp.getBody()); + accessToken = rsp.getAccessToken(); } catch (Exception e) { - + log.error("RefreshDingDingAccessTokenHandler#getAccessToken fail:{}", Throwables.getStackTraceAsString(e)); } - - return null; + return accessToken; } } diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/HandlerHolder.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/HandlerHolder.java index afe9915..31cb8c7 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/handler/HandlerHolder.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/HandlerHolder.java @@ -14,7 +14,7 @@ import java.util.Map; @Component public class HandlerHolder { - private Map handlers = new HashMap(32); + private Map handlers = new HashMap(128); public void putHandler(Integer channelCode, Handler handler) { handlers.put(channelCode, handler); diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingRobotHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingRobotHandler.java index bfa56eb..9a1ed77 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingRobotHandler.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingRobotHandler.java @@ -6,10 +6,11 @@ import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.google.common.base.Throwables; import com.java3y.austin.common.constant.AustinConstant; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.domain.TaskInfo; +import com.java3y.austin.common.dto.account.DingDingRobotAccount; import com.java3y.austin.common.dto.model.DingDingContentModel; import com.java3y.austin.common.enums.ChannelType; -import com.java3y.austin.common.dto.account.DingDingRobotAccount; import com.java3y.austin.handler.domain.dingding.DingDingRobotParam; import com.java3y.austin.handler.domain.dingding.DingDingRobotResult; import com.java3y.austin.handler.handler.BaseHandler; @@ -34,9 +35,6 @@ import java.util.ArrayList; @Service public class DingDingRobotHandler extends BaseHandler implements Handler { - private static final String DING_DING_ROBOT_ACCOUNT_KEY = "dingDingRobotAccount"; - private static final String PREFIX = "ding_ding_robot_"; - @Autowired private AccountUtils accountUtils; @@ -47,7 +45,7 @@ public class DingDingRobotHandler extends BaseHandler implements Handler { @Override public boolean handler(TaskInfo taskInfo) { try { - DingDingRobotAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), DING_DING_ROBOT_ACCOUNT_KEY, PREFIX, new DingDingRobotAccount()); + DingDingRobotAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), SendAccountConstant.DING_DING_ROBOT_ACCOUNT_KEY, SendAccountConstant.DING_DING_ROBOT_PREFIX, new DingDingRobotAccount()); DingDingRobotParam dingDingRobotParam = assembleParam(taskInfo); String httpResult = HttpUtil.post(assembleParamUrl(account), JSON.toJSONString(dingDingRobotParam)); DingDingRobotResult dingDingRobotResult = JSON.parseObject(httpResult, DingDingRobotResult.class); diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingWorkNoticeHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingWorkNoticeHandler.java index 9fec412..f6211bc 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingWorkNoticeHandler.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/DingDingWorkNoticeHandler.java @@ -1,13 +1,25 @@ package com.java3y.austin.handler.handler.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.dingtalk.api.DefaultDingTalkClient; +import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request; +import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response; +import com.google.common.base.Throwables; +import com.java3y.austin.common.constant.AustinConstant; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.domain.TaskInfo; import com.java3y.austin.common.dto.account.DingDingWorkNoticeAccount; +import com.java3y.austin.common.dto.model.DingDingContentModel; import com.java3y.austin.common.enums.ChannelType; import com.java3y.austin.handler.handler.BaseHandler; import com.java3y.austin.handler.handler.Handler; import com.java3y.austin.support.utils.AccountUtils; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; /** @@ -21,24 +33,68 @@ import org.springframework.stereotype.Service; @Service public class DingDingWorkNoticeHandler extends BaseHandler implements Handler { - private static final String DING_DING_ROBOT_ACCOUNT_KEY = "dingDingWorkNoticeAccount"; - private static final String PREFIX = "ding_ding_work_notice_"; - @Autowired private AccountUtils accountUtils; + @Autowired + private StringRedisTemplate redisTemplate; + + public DingDingWorkNoticeHandler() { channelCode = ChannelType.DING_DING_WORK_NOTICE.getCode(); } - @Override - public boolean handler(TaskInfo taskInfo) { + private static final String URL = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"; - DingDingWorkNoticeAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), DING_DING_ROBOT_ACCOUNT_KEY, PREFIX, new DingDingWorkNoticeAccount()); + @Override + public boolean handler(TaskInfo taskInfo) { + try { + DingDingWorkNoticeAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), SendAccountConstant.DING_DING_WORK_NOTICE_ACCOUNT_KEY, SendAccountConstant.DING_DING_WORK_NOTICE_PREFIX, new DingDingWorkNoticeAccount()); + OapiMessageCorpconversationAsyncsendV2Request request = assembleParam(account, taskInfo); + String accessToken = redisTemplate.opsForValue().get(SendAccountConstant.DING_DING_ACCESS_TOKEN_PREFIX + taskInfo.getSendAccount()); + OapiMessageCorpconversationAsyncsendV2Response response = new DefaultDingTalkClient(URL).execute(request, accessToken); + if (response.getErrcode() == 0) { + return true; + } + // 常见的错误 应当 关联至 AnchorState,由austin后台统一透出失败原因 + log.error("DingDingWorkNoticeHandler#handler fail!result:{},params:{}", JSON.toJSONString(response), JSON.toJSONString(taskInfo)); + } catch (Exception e) { + log.error("DingDingWorkNoticeHandler#handler fail!{},params:{}", Throwables.getStackTraceAsString(e), taskInfo); + } return false; } + /** + * 拼装参数 + * + * @param account + * @param taskInfo + */ + private OapiMessageCorpconversationAsyncsendV2Request assembleParam(DingDingWorkNoticeAccount account, TaskInfo taskInfo) { + OapiMessageCorpconversationAsyncsendV2Request req = new OapiMessageCorpconversationAsyncsendV2Request(); + DingDingContentModel contentModel = (DingDingContentModel) taskInfo.getContentModel(); + try { + // 接收者相关 + if (AustinConstant.SEND_ALL.equals(CollUtil.getFirst(taskInfo.getReceiver()))) { + req.setToAllUser(true); + } else { + req.setUseridList(StringUtils.join(taskInfo.getReceiver(), StrUtil.C_COMMA)); + } + req.setAgentId(Long.parseLong(account.getAgentId())); + // 内容相关 + OapiMessageCorpconversationAsyncsendV2Request.Msg message = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); + message.setMsgtype("text"); + OapiMessageCorpconversationAsyncsendV2Request.Text textObj = new OapiMessageCorpconversationAsyncsendV2Request.Text(); + textObj.setContent(contentModel.getContent()); + message.setText(textObj); + + req.setMsg(message); + } catch (Exception e) { + log.error("assembleParam fail:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo)); + } + return req; + } } diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EmailHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EmailHandler.java index 300f112..64e71ee 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EmailHandler.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EmailHandler.java @@ -4,6 +4,7 @@ package com.java3y.austin.handler.handler.impl; import cn.hutool.extra.mail.MailAccount; import cn.hutool.extra.mail.MailUtil; import com.google.common.base.Throwables; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.domain.TaskInfo; import com.java3y.austin.common.dto.model.EmailContentModel; import com.java3y.austin.common.enums.ChannelType; @@ -24,9 +25,6 @@ import org.springframework.stereotype.Component; @Slf4j public class EmailHandler extends BaseHandler implements Handler { - private static final String EMAIL_ACCOUNT_KEY = "emailAccount"; - private static final String PREFIX = "email_"; - @Autowired private AccountUtils accountUtils; @@ -54,7 +52,7 @@ public class EmailHandler extends BaseHandler implements Handler { * @return */ private MailAccount getAccountConfig(Integer sendAccount) { - MailAccount account = accountUtils.getAccount(sendAccount, EMAIL_ACCOUNT_KEY, PREFIX, new MailAccount()); + MailAccount account = accountUtils.getAccount(sendAccount, SendAccountConstant.EMAIL_ACCOUNT_KEY, SendAccountConstant.EMAIL_ACCOUNT_PREFIX, new MailAccount()); try { MailSSLSocketFactory sf = new MailSSLSocketFactory(); sf.setTrustAllHosts(true); diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EnterpriseWeChatHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EnterpriseWeChatHandler.java index 85517e4..bee72a6 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EnterpriseWeChatHandler.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/EnterpriseWeChatHandler.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSON; import com.google.common.base.Throwables; import com.java3y.austin.common.constant.AustinConstant; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.domain.TaskInfo; import com.java3y.austin.common.dto.model.EnterpriseWeChatContentModel; import com.java3y.austin.common.enums.ChannelType; @@ -35,12 +36,6 @@ public class EnterpriseWeChatHandler extends BaseHandler implements Handler { */ private static final String DELIMITER = "|"; - /** - * 账号信息 - */ - private static final String ENTERPRISE_WECHAT_ACCOUNT_KEY = "enterpriseWechatAccount"; - private static final String PREFIX = "enterprise_wechat_"; - @Autowired private AccountUtils accountUtils; @@ -51,7 +46,7 @@ public class EnterpriseWeChatHandler extends BaseHandler implements Handler { @Override public boolean handler(TaskInfo taskInfo) { try { - WxCpDefaultConfigImpl accountConfig = accountUtils.getAccount(taskInfo.getSendAccount(), ENTERPRISE_WECHAT_ACCOUNT_KEY, PREFIX, new WxCpDefaultConfigImpl()); + WxCpDefaultConfigImpl accountConfig = accountUtils.getAccount(taskInfo.getSendAccount(), SendAccountConstant.ENTERPRISE_WECHAT_ACCOUNT_KEY, SendAccountConstant.ENTERPRISE_WECHAT_PREFIX, new WxCpDefaultConfigImpl()); WxCpMessageServiceImpl messageService = new WxCpMessageServiceImpl(initService(accountConfig)); WxCpMessageSendResult result = messageService.send(buildWxCpMessage(taskInfo, accountConfig.getAgentId())); if (Integer.valueOf(WxMpErrorMsgEnum.CODE_0.getCode()).equals(result.getErrCode())) { diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/TencentSmsScript.java b/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/TencentSmsScript.java index 4d31384..1a1201e 100644 --- a/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/TencentSmsScript.java +++ b/austin-handler/src/main/java/com/java3y/austin/handler/script/impl/TencentSmsScript.java @@ -4,6 +4,7 @@ import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.IdUtil; +import com.java3y.austin.common.constant.SendAccountConstant; import com.java3y.austin.common.enums.SmsStatus; import com.java3y.austin.handler.domain.sms.SmsParam; import com.java3y.austin.common.dto.account.TencentSmsAccount; @@ -37,16 +38,13 @@ import java.util.List; public class TencentSmsScript implements SmsScript { private static final Integer PHONE_NUM = 11; - private static final String SMS_ACCOUNT_KEY = "smsAccount"; - private static final String PREFIX = "sms_"; @Autowired private AccountUtils accountUtils; - @Override public List send(SmsParam smsParam) throws Exception { - TencentSmsAccount tencentSmsAccount = accountUtils.getAccount(smsParam.getSendAccount(), SMS_ACCOUNT_KEY, PREFIX, TencentSmsAccount.builder().build()); + TencentSmsAccount tencentSmsAccount = accountUtils.getAccount(smsParam.getSendAccount(), SendAccountConstant.SMS_ACCOUNT_KEY, SendAccountConstant.SMS_PREFIX, TencentSmsAccount.builder().build()); SmsClient client = init(tencentSmsAccount); SendSmsRequest request = assembleReq(smsParam, tencentSmsAccount); SendSmsResponse response = client.SendSms(request);