All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.anyline.aliyun.sms.util.SMSUtil Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2006-2023 www.anyline.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */




package org.anyline.aliyun.sms.util;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import org.anyline.sms.entity.SMSResult;
import org.anyline.sms.util.SMSListener;
import org.anyline.util.AnylineConfig;
import org.anyline.util.BasicUtil;
import org.anyline.util.BeanUtil;
import org.anyline.util.DateUtil;
import org.anyline.log.Log;
import org.anyline.log.LogProxy;

import java.util.*;

/** 
 * 短信服务 
 *  
 * @author zh 
 *  
 */ 
public class SMSUtil {
	private static final Log log = LogProxy.get(SMSUtil.class); 
	private SMSConfig config = null;
	private Client client;
	private static Hashtable instances = new Hashtable();

	public Template template= new SMSUtil.Template();
	private SMSListener listener;
 
    // 产品名称:云通信短信API产品,开发者无需替换 
    static final String product = "Dysmsapi"; 
    // 产品域名,开发者无需替换 
    static final String endpoint = "dysmsapi.aliyuncs.com";


	static {
		Hashtable configs = SMSConfig.getInstances();
		for(String key:configs.keySet()){
			instances.put(key, getInstance(key));
		}
	}
	public static Hashtable getInstances(){
		return instances;
	}
	public static SMSUtil getInstance(){
		return getInstance(SMSConfig.DEFAULT_INSTANCE_KEY);
	} 
	public static SMSUtil getInstance(String key){
		if(BasicUtil.isEmpty(key)){
			key = SMSConfig.DEFAULT_INSTANCE_KEY;
		} 
		SMSUtil util = instances.get(key); 
		if(null == util){
			SMSConfig config = SMSConfig.getInstance(key);
			if(null != config) {
				util = new SMSUtil();
				util.config = config;
				try {
					Config cfg = new Config();
					cfg.setAccessKeyId(config.ACCESS_KEY);
					cfg.setAccessKeySecret(config.ACCESS_SECRET);
					cfg.endpoint = endpoint;
					util.listener = SMSBean.getListener();
					util.client = new Client(cfg);
				} catch (Exception e) {
					e.printStackTrace();
				}
				instances.put(key, util);
			}
		}
		return util; 
	}

	/**
	 * 发送短信
	 * @param sign 签名(如果不指定则使用配置文件中默认签名)
	 * @param template 模板code(SMS_88550009,注意不要写成工单号)
	 * @param mobile 手机号,多个以逗号分隔
	 * @param params 参数
	 * @param extend 上行短信扩展码。上行短信指发送给通信服务提供商的短信,用于定制某种服务、完成查询,或是办理某种业务等,需要收费,按运营商普通短信资费进行扣费。
	 * @param out 外部流水扩展字段。
	 * @return SMSResult
	 */
	public SMSResult send(String sign, String template, String extend, String out, String mobile, Map params) {
		SMSResult result = new SMSResult();
		if(null != listener && !listener.before(config.INSTANCE_KEY, sign, template, extend, out, mobile, params)){
			return result;
		}
		try {
			if(BasicUtil.isEmpty(sign)){
				sign = config.SIGN; 
			}
			SendSmsRequest request = new SendSmsRequest()
					.setSignName(sign)
					.setTemplateCode(template)
					.setPhoneNumbers(mobile)
					.setTemplateParam(BeanUtil.map2json(params));
			if(BasicUtil.isNotEmpty(extend)){
				request.setSmsUpExtendCode(extend);
			}
			if(BasicUtil.isNotEmpty(out)){
				request.setOutId(out);
			}
			RuntimeOptions runtime = new RuntimeOptions();
			SendSmsResponse response = client.sendSmsWithOptions(request, runtime);
	        result.setStatus(response.getStatusCode());
			SendSmsResponseBody body = response.getBody();
			result.setRequestId(body.getRequestId());
			result.setCode(body.getCode());
	        result.setMsg(body.getMessage());
			result.setBiz(body.getBizId());
	        result.setResult(true);
		} catch (Exception e) {
			e.printStackTrace();
			result.setResult(false);
			result.setMsg(e.toString());
		}
		if(null != listener){
			listener.after(result, config.INSTANCE_KEY, sign, template, extend, out, mobile, params);
		}
		return result; 
	}

	public SMSResult send(String sign, String template, String mobile, Map params) {
		return send(sign, template, null, null, mobile, params);
	}

	/**
	 * 发送短信
	 * send("sign","SMS_000000","15800000000", new User()/new DataRow(), ["id","name:userNmae","age:userAge"])
	 * @param sign 签名(如果不指定则使用配置文件中默认签名)
	 * @param template 模板code(SMS_88550009,注意不要写成工单号)
	 * @param mobile 手机号,多个以逗号分隔
	 * @param entity 实体对象
	 * @param keys 对象属性(根据keys从entity中取值生成短信参数),如果参数名与属性名不一致通过 短信参数名:属性名 转换
	 * @return SMSResult
	 */
	public SMSResult send(String sign, String template, String mobile, Object entity, List keys) {
		return send(sign, template, mobile, object2map(entity, keys));
	}

	public SMSResult send(String sign, String template, String mobile, Object entity, String ... keys) {
		return send(sign, template, mobile, object2map(entity, keys));
	}
		/**
         * 发送短信
         * @param sign 签名(如果不指定则使用配置文件中默认签名)
         * @param template 模板code(SMS_88550009,注意不要写成工单号)
         * @param mobiles 手机号
         * @param params 参数
         * @return SMSResult
         */
	public SMSResult send(String sign, String template, List mobiles, Map params) {
		String mobile = ""; 
		for(String item:mobiles){
			if("".equals(mobile)){
				mobile = item; 
			}else{
				mobile += "," + item; 
			} 
		} 
		return send(sign, template, mobile, params); 
	}
	public SMSResult send(String sign, String template, List mobiles, Object entity, List keys) {
		return send(sign, template, mobiles, object2map(entity, keys));
	}
	public SMSResult send(String sign, String template, List mobiles, Object entity, String ... keys) {
		return send(sign, template, mobiles, object2map(entity, keys));
	}
		/**
         * 发送短信(使用配置文件中的默认签名)
         * @param template 模板code(SMS_88550009,注意不要写成工单号)
         * @param mobile 手机号
         * @param params 参数
         * @return SMSResult
         */
	public SMSResult send(String template, String mobile, Map params) {
		return send(config.SIGN, template, mobile, params);
	}
	public SMSResult send(String template, String mobile, Object entity, List keys) {
		return send(config.SIGN, template, mobile, object2map(entity, keys));
	}
	public SMSResult send(String template, String mobile, Object entity, String ... keys) {
		return send(config.SIGN, template, mobile, object2map(entity, keys));
	}
	/**
	 * 发送短信(使用配置文件中的默认签名)
	 * @param template 模板code(SMS_88550009,注意不要写成工单号)
	 * @param mobiles 手机号
	 * @param params 参数
	 * @return SMSResult
	 */
	public SMSResult send(String template, List mobiles, Map params) {
		return send(config.SIGN, template, mobiles, params);
	}
	public SMSResult send(String template, List mobiles, Object entity, List keys) {
		return send(config.SIGN, template, mobiles, object2map(entity, keys));
	}
	public SMSResult send(String template, List mobiles, Object entity, String ... keys) {
		return send(config.SIGN, template, mobiles, object2map(entity, keys));
	}

	/**
	 * 查询发送状态,有可能查出多个发送记录,按时间倒序
	 * @param mobile 手机号
	 * @param biz 回执号
	 * @param date 发送日期(yyyyMMdd) 不传默认当天 支持查询最近30天的记录。
	 * @param vol 每页多少条
	 * @param page 当前第几页
	 * @return List 根据 SMSMResult.status 1:等待回执 2:发送失败 3:发送成功。
	 * @throws RuntimeException RuntimeException
	 */
	public List status(String mobile, String biz, String date, int vol, int page) throws RuntimeException{
		if(BasicUtil.isEmpty(date)){
			date = DateUtil.format("yyyyMMdd");
		}
		List results = new ArrayList<>();
		QuerySendDetailsRequest query = new QuerySendDetailsRequest()
			.setPhoneNumber(mobile)
			.setSendDate(date)
			.setPageSize((long)vol)
			.setCurrentPage((long)page);

		if(BasicUtil.isNotEmpty(biz)){
			query.setBizId(biz);
		}
		try {

			QuerySendDetailsResponse queryResp = client.querySendDetails(query);
			List list = queryResp.getBody().getSmsSendDetailDTOs().getSmsSendDetailDTO();
			for (QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO item : list) {
				SMSResult result = new SMSResult();
				result.setStatus(item.getSendStatus().intValue());
				result.setContent(item.getContent());
				result.setCode(item.getErrCode());
				result.setMobile(item.getPhoneNum());
				result.setRequestId(queryResp.getBody().getRequestId());
				result.setOut(item.getOutId());
				result.setReceiveTime(item.getReceiveDate());
				result.setSendTime(item.getSendDate());
				result.setTemplate(item.getTemplateCode());
				results.add(result);
			}
		}catch (Exception e){
			 throw new RuntimeException(e);
		}
		return results;
	}

	/**
	 * 最后一次发送状态
	 * @param mobile 手机号
	 * @param biz 回执号
	 * @param date 发送日期
	 * @return SMSResult 根据 SMSMResult.status 1:等待回执 2:发送失败 3:发送成功。
	 */
	public SMSResult status(String mobile, String biz, String date){
		List results = status(mobile, biz, date, 1,1);
		if(results.size()>0){
			return results.get(0);
		}
		return null;
	}

	public SMSResult status(String mobile, String biz){
		return status(mobile, biz, DateUtil.format("yyyyMMdd"));
	}
	public SMSResult status(String mobile){
		return status(mobile, null, DateUtil.format("yyyyMMdd"));
	}


	public SMSConfig getConfig() {
		return config; 
	}

	private Map object2map(Object entity, List keys){
		Map params = new HashMap<>();
		if(null != keys){
			for(String key:keys){
				String field = key;
				if(key.contains(":")){
					String[] tmps = key.split(":");
					key = tmps[0];
					field = tmps[1];
				}
				Object value = BeanUtil.getFieldValue(entity, field);
				if(null != value){
					params.put(key, value.toString());
				}
			}
		}
		return params;
	}
	private Map object2map(Object entity, String ... keys){
		return object2map(entity, BeanUtil.array2list(keys));
	}
	public class Sign{
		public void request(String name, int source, String remark, List files){
		}
	}

	public class Template{
		/**
		 * 申请短信模板
		 * @param name 名称
		 * @param type 0:验证码 1:通知短信 2:推广短信
		 * @param content 内容,如果type=1内容中需要有变量,如:${code}
		 * @param remark 备注
		 * @return 返回模板编号 SMS_000000
		 * @throws RuntimeException RuntimeException
		 */
		public String request(String name, int type, String content, String remark) throws RuntimeException {
			String code = null;
			AddSmsTemplateRequest req = new AddSmsTemplateRequest()
					.setTemplateType(type)
					.setTemplateName(name)
					.setTemplateContent(content)
					.setRemark(remark);
			try {
				AddSmsTemplateResponse response = SMSUtil.this.client.addSmsTemplate(req);
				if("OK".equalsIgnoreCase(response.getBody().getCode())){
					code = response.getBody().getTemplateCode();
				}else{
					throw new RuntimeException("模板申请失败:"+response.getBody().getCode());
				}
			}catch (Exception e){
				throw new RuntimeException(e);
			}
			return code;
		}

		/**
		 * 修改未审核通过的模板(只能侯审核失败的,不能侯未审核及撤销的)
		 * @param code request()返回的编号
		 * @param name 名称
		 * @param type 0:验证码 1:通知短信 2:推广短信
		 * @param content 内容,如果type=1内容中需要有变量,如:${code}
		 * @param remark remark
		 * @return boolean
		 * @throws RuntimeException RuntimeException
		 */
		public boolean update(String code, String name, int type, String content, String remark) throws RuntimeException {
			ModifySmsTemplateRequest req = new ModifySmsTemplateRequest()
					.setTemplateType(type)
					.setTemplateName(name)
					.setTemplateCode(code)
					.setTemplateContent(content)
					.setRemark(remark);
			try {
				ModifySmsTemplateResponse resp = client.modifySmsTemplate(req);
				if ("OK".equalsIgnoreCase(resp.getBody().getCode())) {
					throw new Exception("修改失败:" + resp.getBody().getMessage());
				}
			}catch (Exception e){
				throw new RuntimeException(e);
			}
			return true;
		}
		/**
		 * 查询全部模板列表
		 * @return list
		 */
		public List list(){
			List templates = new ArrayList<>();
			int page = 1;
			while (true){
				List list = list(page, 10);
				if(null == list || list.isEmpty()){
					break;
				}
				templates.addAll(list);
				page ++;
			}
			return templates;
		}

		/**
		 * 根据状态查询模板列表
		 * @param status 状态
		 * @return List
		 */
		public List list(SMSTemplate.STATUS status){
			List all = list();
			List templates = new ArrayList<>();
			for(SMSTemplate item:all){
				if(status.getCode().equals(item.getStatus())){
					templates.add(item);
				}
			}
			return templates;
		}

		/**
		 * 根据可用状态查询模板列表
		 * @param enable 是否可用
		 * @return List
		 */
		public List list(boolean enable){
			List all = list();
			List templates = new ArrayList<>();
			for(SMSTemplate item:all){
				if(enable){
					if(SMSTemplate.STATUS.AUDIT_STATE_PASS.getCode().equals(item.getStatus())) {
						templates.add(item);
					}
				}else{
					if(!SMSTemplate.STATUS.AUDIT_STATE_PASS.getCode().equals(item.getStatus())) {
						templates.add(item);
					}
				}
			}
			return templates;
		}

		/**
		 * 分页查询模板列表
		 * @param page 当前第几页
		 * @param vol 每页多少条
		 * @return list
		 * @throws RuntimeException RuntimeException
		 */
		public List list(int page, int vol) throws RuntimeException{
			List templates = new ArrayList<>();

				QuerySmsTemplateListRequest req = new QuerySmsTemplateListRequest()
						.setPageIndex(page)
						.setPageSize(vol);
				try {
					QuerySmsTemplateListResponse resp = SMSUtil.this.client.querySmsTemplateList(req);

					if (null == resp || 200 != resp.getStatusCode()) {
						throw new RuntimeException("查询失败:" + resp.getStatusCode());

					}
					QuerySmsTemplateListResponseBody body = resp.getBody();
					if (null == body || !"OK".equalsIgnoreCase(body.getCode())) {
						throw new RuntimeException("查询失败:" + body.getMessage());
					}
					List list = body.getSmsTemplateList();
					if (null == list) {
						return templates;
					}
					for (QuerySmsTemplateListResponseBody.QuerySmsTemplateListResponseBodySmsTemplateList item : list) {
						SMSTemplate template = new SMSTemplate();
						template.setCode(item.getTemplateCode());
						template.setContent(item.getTemplateContent());
						template.setStatus(item.getAuditStatus());
						template.setCreateTime(item.getCreateDate());
						template.setName(item.getTemplateName());
						template.setType(item.getTemplateType());
						QuerySmsTemplateListResponseBody.QuerySmsTemplateListResponseBodySmsTemplateListReason reason = item.getReason();
						if (null != reason) {
							template.setRejectInfo(reason.getRejectInfo());
							template.setRejectTime(reason.getRejectDate());
							template.setRejectSubInfo(reason.getRejectSubInfo());
						}
						templates.add(template);
					}
				}catch (Exception e){
					throw new RuntimeException(e);
				}
			return templates;
		}

		public List list(int page){
			return list(page, 10);
		}

		/**
		 * 根据编号查询模板信息(主要查询审核状态)
		 * @param code code
		 * @return SMSTemplate
		 * @throws RuntimeException RuntimeException
		 */
		public SMSTemplate info(String code) throws RuntimeException{
			SMSTemplate template = new SMSTemplate();
			template.setCode(code);
			template.setStatus(SMSTemplate.STATUS.ERROR);
			QuerySmsTemplateRequest req = new QuerySmsTemplateRequest().setTemplateCode(code);
			try {
				QuerySmsTemplateResponse resp = client.querySmsTemplate(req);

				if (null != resp && resp.getStatusCode() == 200) {
					QuerySmsTemplateResponseBody body = resp.getBody();
					if ("OK".equalsIgnoreCase(body.getCode())) {
						template.setCode(code);
						template.setType(body.getTemplateType());
						template.setName(body.getTemplateName());
						template.setContent(body.getTemplateContent());
						template.setCreateTime(body.getCreateDate());
						int status = body.getTemplateStatus();
						// 0:审核中。
						// 1:审核通过。
						// 2:审核失败,请在返回参数Reason中查看审核失败原因。
						// 10:取消审核。
						if (status == 0) {
							template.setStatus(SMSTemplate.STATUS.AUDIT_STATE_INIT);
						} else if (status == 1) {
							template.setStatus(SMSTemplate.STATUS.AUDIT_STATE_PASS);
						} else if (status == 2) {
							template.setStatus(SMSTemplate.STATUS.AUDIT_STATE_NOT_PASS);
							template.setRejectInfo(body.getReason());
						}else if(status == 10){
							template.setStatus(SMSTemplate.STATUS.AUDIT_SATE_CANCEL);
						}else{
							template.setStatus(SMSTemplate.STATUS.ERROR);
						}

					}
				}
			}catch (Exception e){
				throw new RuntimeException(e);
			}
			return template;
		}
		/**
		 * 删除模板
		 * @param code 模板编号
		 * @return boolean
		 * @throws RuntimeException RuntimeException
		 */
		public boolean delete(String code) throws RuntimeException{
			DeleteSmsTemplateRequest req = new DeleteSmsTemplateRequest()
					.setTemplateCode(code);
			try {
				DeleteSmsTemplateResponse resp = client.deleteSmsTemplate(req);
				if (!"OK".equalsIgnoreCase(resp.getBody().getCode())) {
					throw new Exception("删除失败:" + resp.getBody().getMessage());
				}
			}catch (Exception e){
				throw new RuntimeException(e);
			}
			return true;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy