云片网短信发送工作记录

由于我这儿云片网发送短信少,所以直接写死,这儿封装了阿里华为云片等发送短信的方法

public class SmsUtil {
    private static final String YUNPIAN_SEND_SMS_URL = "https://sms.yunpian.com/v2/sms/single_send.json";
    private static final String API_KEY = "xxxxxxxxxxxx"; // 云片网API Key
    private static final String SIGN_NAME = "xxxxxxx"; // 短信签名

    public static SendSmsResponse send(Record smsConfig, String phone, String data) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, IOException {
        String url = "https://rtcsms.cn-north-1.myhuaweicloud.com:10743/sms/batchSendSms/v1";
        //String sender = "8822021405177";
        String sender = smsConfig.getStr("sender");
        String accessKeyId = smsConfig.getStr("access_key");
        String accessKeySecret = smsConfig.getStr("access_key_secret");
        String templateId = smsConfig.getStr("template_code");
        String signature = smsConfig.getStr("sign_name");
        String statusCallBack = "";
        String templateParas = data;
        String receiver = phone;
        if (!phone.startsWith("+86")) {
            receiver = "+86" + phone;
        }
        String body = buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, signature);
        if (null != body && !body.isEmpty()) {
            String wsseHeader = buildWsseHeader(accessKeyId, accessKeySecret);
            if (null != wsseHeader && !wsseHeader.isEmpty()) {
                CloseableHttpClient client = HttpClients.custom().setSSLContext((new SSLContextBuilder()).loadTrustMaterial((KeyStore) null, (x509CertChain, authType) -> {
                    return true;
                }).build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
                HttpResponse response = client.execute(RequestBuilder.create("POST").setUri(url).addHeader("Content-Type", "application/x-www-form-urlencoded").addHeader("Authorization", "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"").addHeader("X-WSSE", wsseHeader).setEntity(new StringEntity(body)).build());
                System.out.println(response.toString());
                String enitiyResult = EntityUtils.toString(response.getEntity());
                System.out.println(enitiyResult);
                Map<String, Object> result = (Map) JSON.parseObject(enitiyResult, new TypeReference<Map<String, Object>>() {
                }, new Feature[0]);
                System.out.println(result);
                SendSmsResponse sendSmsResponse = new SendSmsResponse();
                String resultCode = "";
                if (result.containsKey("code")) {
                    resultCode = result.get("code").toString();
                    if ("000000".equals(resultCode)) {
                        resultCode = "OK";
                    }
                }

                sendSmsResponse.setCode(resultCode);
                sendSmsResponse.setMessage(String.valueOf(result.get("description")));
                return sendSmsResponse;
            } else {
                System.out.println("wsse header is null.");
                return null;
            }
        } else {
            System.out.println("body is null.");
            return null;
        }
    }
//阿里发送短信的发送方法如下
    public static com.aliyun.dysmsapi20170525.models.SendSmsResponse newSend(Record smsConfig, String phone, String data) throws Exception {
        // 从配置中获取阿里云短信服务的参数
        String accessKeyId = smsConfig.getStr("access_key");
        String accessKeySecret = smsConfig.getStr("access_key_secret");
        String signName = smsConfig.getStr("sign_name");
        String templateCode = smsConfig.getStr("template_code");
        // 配置阿里云客户端
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "dysmsapi.aliyuncs.com";

        // 创建客户端
        Client client = new Client(config);

        // 构造请求参数
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam("{\"code\":\"" + data + "\"}");

        // 发送短信
        com.aliyun.dysmsapi20170525.models.SendSmsResponse response = client.sendSms(sendSmsRequest);
        return response;
    }

//  云片网发送云片网的短信如下。如果模板审核原因,只能申请到注册的模板,其它模板无法通过。
//  所以估记这个方法估记很少用,临时用一下,所以参数直接写死算了
    public static String yunSend(String phone, String data) {
        String text = "" + SIGN_NAME + "】正在进行登录操作,您的验证码是" + data; // 短信内容

        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpPost post = new HttpPost(YUNPIAN_SEND_SMS_URL);
            List<NameValuePair> params = new ArrayList<>();
            params.add(new BasicNameValuePair("apikey", API_KEY));
            params.add(new BasicNameValuePair("mobile", phone));
            params.add(new BasicNameValuePair("text", text));
            post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            try (CloseableHttpResponse response = client.execute(post)) {
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                return result;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "Error: " + e.getMessage();
        }
    }


    static String buildRequestBody(String sender, String receiver, String templateId, String templateParas, String statusCallbackUrl, String signature) {
        if (null != sender && null != receiver && null != templateId && !sender.isEmpty() && !receiver.isEmpty() && !templateId.isEmpty()) {
            List<NameValuePair> keyValues = new ArrayList();
            keyValues.add(new BasicNameValuePair("from", sender));
            keyValues.add(new BasicNameValuePair("to", receiver));
            keyValues.add(new BasicNameValuePair("templateId", templateId));
            if (null != templateParas && !templateParas.isEmpty()) {
                keyValues.add(new BasicNameValuePair("templateParas", templateParas));
            }

            if (null != statusCallbackUrl && !statusCallbackUrl.isEmpty()) {
                keyValues.add(new BasicNameValuePair("statusCallback", statusCallbackUrl));
            }

            if (null != signature && !signature.isEmpty()) {
                keyValues.add(new BasicNameValuePair("signature", signature));
            }

            return URLEncodedUtils.format(keyValues, Charset.forName("UTF-8"));
        } else {
            System.out.println("buildRequestBody(): sender, receiver or templateId is null.");
            return null;
        }
    }

    static String buildWsseHeader(String appKey, String appSecret) {
        if (null != appKey && null != appSecret && !appKey.isEmpty() && !appSecret.isEmpty()) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            String time = sdf.format(new Date());
            String nonce = UUID.randomUUID().toString().replace("-", "");
            byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret);
            String hexDigest = Hex.encodeHexString(passwordDigest);
            String passwordDigestBase64Str = Base64.getEncoder().encodeToString(hexDigest.getBytes());
            return String.format("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"", appKey, passwordDigestBase64Str, nonce, time);
        } else {
            System.out.println("buildWsseHeader(): appKey or appSecret is null.");
            return null;
        }
    }

    public static void main(String[] args) throws Exception {


        String phone = "18675918218"; // 替换为实际测试手机号
        // 测试验证码
        String data = "123456"; // 验证码

        // 调用yunSend方法发送短信
        String result = SmsUtil.yunSend(phone, data);

        // 打印发送结果
        System.out.println("发送结果: " + result);
    }


}

最后是关于如何发送短信的代码

    public void sendVcode() {
        String ct = getPara("ct");
        Long companyId;
        if (StringUtil.isNotEmpty(ct)) {
            companyId = Db.queryLong("select id from fr_company where token = ? ", ct);
        } else {
            Record user = getRequestUser();
            if (null != user) {
                companyId = user.getLong("company_id");
            } else {
                companyId = CompanyData.getPlatformId();
            }
        }

        String phone = getPara("phone");
        Integer type = getParaToInt("type");
        Random ran = new Random();
        Integer icode;
        // 验证码是随机的
        while ((icode = ran.nextInt(10000)) < 1000) {
            icode = ran.nextInt();
        }
        String vcode = String.valueOf(icode);
        logger.info("手机号码:{},验证码:{},type={},companyId={}", phone, vcode, type, companyId);

        Integer timeToLive = 900; // 默认900秒
        Record smsConfig = CompanyExtendResource.loadSmsConfig(companyId, type);
        if (null == smsConfig) {
            smsConfig = CompanyExtendResource.loadSmsConfig(CompanyData.getPlatformId(), type);
            logger.info("can not find smsConfig by companyId:{}", companyId);
            renderJson(JsonResult.fail("-1").show("发送失败"));
            return;
        }

        logger.info("smsConfig:{}", smsConfig.getColumns());
        Integer status = smsConfig.getInt("status");

        if (status == 1) {
            try {
                // 先尝试使用云片网发送短信
                String yunpianResponse = SmsUtil.yunSend(phone, vcode);
                logger.info("云片网发送结果: {}", yunpianResponse);

                // 解析云片网返回的 JSON 结果
                String code = null;
                try {
                    JSONObject responseJson = new JSONObject(yunpianResponse);
                    code = responseJson.getString("code");
                } catch (Exception e) {
                    logger.error("解析云片网返回的 JSON 数据时出错: {}", yunpianResponse, e);
                    renderJson(JsonResult.fail("-1").show("解析云片网返回的 JSON 数据时出错"));
                    return;
                }
                if ("0".equals(code)) {
                    // 云片网发送成功
                    logger.info("云片网发送成功,手机号:{}", phone);
                    renderJson(JsonResult.success());
                } else {
                    // 云片网发送失败,记录日志并尝试使用阿里云发送短信
                    logger.info("云片网发送失败,正在调用阿里云发送短信,手机号:{}", phone);
                    SendSmsResponse aliResponse = SmsUtil.newSend(smsConfig, phone, vcode);
                    if (aliResponse != null) {
                        logger.info("阿里云发送结果: code:{}, message:{}", aliResponse.getBody().getCode(), aliResponse.getBody().getMessage());
                        if ("OK".equalsIgnoreCase(aliResponse.getBody().getCode())) {
                            // 阿里云发送成功
                            logger.info("阿里云发送成功,手机号:{}", phone);
                            renderJson(JsonResult.success());
                        } else {
                            // 阿里云发送失败
                            logger.info("阿里云发送失败,手机号:{}", phone);
                            if (aliResponse.getBody().getCode().indexOf("BUSINESS_LIMIT_CONTROL") > -1) {
                                renderJson(JsonResult.fail("-1").show("验证码发送已达上限"));
                            } else {
                                renderJson(JsonResult.fail("-1").show("验证码发送失败"));
                            }
                        }
                    } else {
                        logger.info("阿里云发送失败,未获取到响应,手机号:{}", phone);
                        renderJson(JsonResult.fail("-1").show("验证码发送失败"));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("发送短信时发生异常,手机号:{}", phone, e);
                renderJson(JsonResult.fail("-1").show("验证码发送失败"));
            }
        } else {
            renderJson(JsonResult.successWithData(vcode));
        }

        // 保存到 Redis
        String key = "user:" + type + ":" + phone;
        RedisManager.handler().set(key, vcode, timeToLive);
    }

 

posted @ 2025-04-17 17:33  稷下元歌  阅读(52)  评论(0)    收藏  举报