短信接入示例

更新时间: 2025/09/22 16:36:13

短信服务(Short Message Service)是网易云信为用户提供的一种通信服务能力。本文介绍如何使用常见编程语言发起 HTTP 请求,帮助开发者高效接入短信服务。

短信类型

网易云信支持发送以下类型的短信,短信接口为标准的 HTTP 接口:

  • 验证码类短信:用于发送验证码进行身份验证
  • 通知类短信:用于发送系统通知、订单状态等信息
  • 运营类短信:用于发送营销推广内容
  • 语音类短信:语音验证码或语音通知
  • 国际短信:支持全球国家区号号码发送

调用说明

应用服务端调用 API 向网易云信服务端发起请求时,需遵循固定的请求结构和请求方式。详细规范请参考 API 调用方式说明

服务地址

为保障业务稳定性,网易云信短信服务提供主备域名机制。当主域名发生故障时,可使用备用域名继续访问。

域名类型 服务地址 说明
主域名 sms.yunxinapi.com 优先使用
备用域名 sms-backup.yunxinapi.com 主域名不可用时使用

为确保服务的高可用性,建议:

  • 配置多域名访问:在业务系统中同时配置主备域名,检测到主域名无法访问时自动切换至备用域名。
  • 定期健康检查:实现定期检查域名可用性的机制,及时发现访问问题。

请求 URL

不同类型的短信使用不同的 API 端点,请确保模板类型与 URL 对应,否则将返回 404 错误:

短信类型 API 端点 说明
验证码短信 https://{endpoint}/sms/sendcode.action 用于发送验证码
通知类短信 https://{endpoint}/sms/sendtemplate.action 用于发送通知消息
运营类短信 https://{endpoint}/sms/sendtemplate.action 用于发送营销消息

{endpoint} 需要替换为实际的服务地址(主域名或备用域名)。

请求头

所有 API 请求都必须在 Header 中包含以下认证参数,缺少任一参数将返回错误 {"desc":"bad http header","code":414}

参数名 数据类型 是否必填 说明
AppKey String 应用的唯一标识,从 网易云信控制台 获取,AppKey 和 AppSecret 的获取方式请参考 创建应用并获取 AppKey
Nonce String 随机数,最大长度 128 字符,每次请求应不同。
CurTime String 当前 UTC 时间戳(秒级),从 1970-01-01 00:00:00 开始计算。
CheckSum String 签名的 SHA1 哈希计算校验值,计算方式:SHA1(AppSecret + Nonce + CurTime)

CheckSum 计算示例

CheckSum 是重要的安全校验参数,计算步骤如下:

  1. 将 AppSecret、Nonce、CurTime 按顺序拼接成字符串。
  2. 对拼接后的字符串进行 SHA1 哈希计算。
  3. 将结果转换为小写的 16 进制字符串。
Java
Javaimport java.security.MessageDigest;

public class CheckSumBuilder {
    /**
     * 计算并获取 CheckSum 签名
     * @param appSecret 应用密钥
     * @param nonce 随机数
     * @param curTime 当前时间戳
     * @return CheckSum 签名
     */
    public static String getCheckSum(String appSecret, String nonce, String curTime) {
        return encode("sha1", appSecret + nonce + curTime);
    }

    /**
     * 计算 MD5 值
     * @param requestBody 请求体
     * @return MD5 值
     */
    public static String getMD5(String requestBody) {
        return encode("md5", requestBody);
    }

    private static String encode(String algorithm, String value) {
        if (value == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(value.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}
Node.js
JavaScriptconst { SHA1 } = require("crypto-js");

// 生成指定长度的随机字符串
function randString(length) {
  let result = "";
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * characters.length));
  }
  return result;
}

// 生成请求参数
const nonce = randString(20);
const curTime = Math.floor(Date.now() / 1000).toString();

// 计算 CheckSum
function getCheckSum(appSecret, nonce, curTime) {
  return SHA1(appSecret + nonce + curTime).toString();
}
Python
Pythonimport hashlib
import time
import random
import string

def generate_nonce(length=32):
    """生成指定长度的随机字符串"""
    return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

def get_checksum(app_secret, nonce, cur_time):
    """计算 CheckSum 签名"""
    text = app_secret + nonce + cur_time
    return hashlib.sha1(text.encode('utf-8')).hexdigest()

# 示例用法
app_secret = "your_app_secret"  # 替换为实际的 AppSecret
nonce = generate_nonce()
cur_time = str(int(time.time()))
checksum = get_checksum(app_secret, nonce, cur_time)

print(f"Nonce: {nonce}")
print(f"CurTime: {cur_time}")
print(f"CheckSum: {checksum}")

发送验证码短信

验证码短信用于发送数字验证码,支持文本和语音两种形式。

请求参数

参数名 数据类型 是否必填 说明
templateid String 短信模板 ID,需在 网易云信控制台 预先创建
mobile String 接收短信的手机号码(单个号码)
codeLen Integer 验证码长度,范围 4-10,默认为 4
deviceId String 设备标识,可用于防刷

代码示例

Java
Javapackage com.netease.sms;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.netease.checksum.CheckSumBuilder;
/**
 * 发送验证码
 * @author liuxuanlin
 *
 */
public class SendCode {
    //发送验证码的请求路径 URL
    private static final String
            SERVER_URL="https://sms.yunxinapi.com/sms/sendcode.action";
    //网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
    private static final String
            APP_KEY="fd460d34e786e7754e505bc4fab0f027";
    //网易云信分配的密钥,请替换您在网易云信控制台应用下创建的 appSecret
    private static final String APP_SECRET="xxxxxxxx";
    //随机数
    private static final String NONCE="123456";
    //短信模板 ID
    private static final String TEMPLATEID="3057527";
    //手机号
    private static final String MOBILE="13888888888";
    //验证码长度,范围 4~10,默认为 4
    private static final Int CODELEN=6;

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

        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(SERVER_URL);
        String curTime = String.valueOf((new Date()).getTime() / 1000L);
        /*
         * 参考计算 CheckSum 的 java 代码,在上述文档的参数列表中,有 CheckSum 的计算文档示例
         */
        String checkSum = CheckSumBuilder.getCheckSum(APP_SECRET, NONCE, curTime);

        // 设置请求的 header
        httpPost.addHeader("AppKey", APP_KEY);
        httpPost.addHeader("Nonce", NONCE);
        httpPost.addHeader("CurTime", curTime);
        httpPost.addHeader("CheckSum", checkSum);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

        // 设置请求的的参数,requestBody 参数
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        /*
         * 1.如果是模板短信,请注意参数 mobile 是有 s 的,详细参数配置请参考 **发送模板短信文档**
         * 2.参数格式是 jsonArray 的格式,例如 "['13888888888','13666666666']"
         * 3.params 是根据您模板里面有几个参数,那里面的参数也是 jsonArray 格式
         */
        nvps.add(new BasicNameValuePair("templateid", TEMPLATEID));
        nvps.add(new BasicNameValuePair("mobile", MOBILE));
        nvps.add(new BasicNameValuePair("codeLen", CODELEN));

        httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));

        // 执行请求
        HttpResponse response = httpClient.execute(httpPost);
        /*
         * 1.打印执行结果,打印结果一般会 200、315、403、404、413、414、500
         * 2.具体的 code 有问题的可以参考官网的 Code 状态表
         */
        System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));
    }
}
C#
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Net;
using System.IO;

namespace server_http_api
{
    class CheckSumBuilder
    {
        // 计算并获取 CheckSum
        public static String getCheckSum(String appSecret, String nonce, String curTime)
        {
            byte[] data = Encoding.Default.GetBytes(appSecret + nonce + curTime);
            byte[] result;

            SHA1 sha = new SHA1CryptoServiceProvider();
            // This is one implementation of the abstract class SHA1.
            result = sha.ComputeHash(data);

            return getFormattedText(result);
        }

        // 计算并获取 md5 值
        public static String getMD5(String requestBody)
        {
            if (requestBody == null)
                return null;

            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(requestBody));

            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return getFormattedText(Encoding.Default.GetBytes(sBuilder.ToString()));
        }

        private static String getFormattedText(byte[] bytes)
        {
            char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            int len = bytes.Length;
            StringBuilder buf = new StringBuilder(len * 2);
            for (int j = 0; j < len; j++) {
                buf.Append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
                buf.Append(HEX_DIGITS[bytes[j] & 0x0f]);
            }
            return buf.ToString();
        }
    }

    class HttpClient
    {
        //发起 HTTP 请求
        public static void HttpPost(string url, Stream data, IDictionary<object, string> headers = null)
        {
            System.Net.WebRequest request = HttpWebRequest.Create(url);
            request.Method = "POST";
            if (data != null)
            request.ContentLength = data.Length;
            //request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";

            if (headers != null)
            {
                foreach (var v in headers)
                {
                    if (v.Key is HttpRequestHeader)
                        request.Headers[(HttpRequestHeader)v.Key] = v.Value;
                    else
                        request.Headers[v.Key.ToString()] = v.Value;
                }
            }
            HttpWebResponse response = null;
            try
            {
                // Get the response.
                response = (HttpWebResponse)request.GetResponse();
                // Display the status.
                Console.WriteLine(response.StatusDescription);
                // Get the stream containing content returned by the server.
                Stream dataStream = response.GetResponseStream();
                // Open the stream using a StreamReader for easy access.
                StreamReader reader = new StreamReader(dataStream);
                // Read the content.
                string responseFromServer = reader.ReadToEnd();
                // Display the content.
                Console.WriteLine(responseFromServer);
                // Cleanup the streams and the response.
                reader.Close();
                dataStream.Close();
                response.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(response.StatusDescription);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            String url = "https://sms.yunxinapi.com/sms/sendcode.action";
            url += "?templateid=3030410&mobile=13888888888";//请输入正确的手机号

            //网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
            String appKey = "fd460d34e786e7754e505bc4fab0f027";
            //网易云信分配的密钥,请替换您在网易云信控制台应用下创建的 appSecret
            String appSecret = "xxxxxxxx";
            //随机数(最大长度 128 个字符)
            String nonce = "12345";

            TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1);
            Int32 ticks = System.Convert.ToInt32(ts.TotalSeconds);
            //当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
            String curTime = ticks.ToString();
            //SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
            String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce, curTime);

            IDictionary<object, String> headers = new Dictionary<object, String>();
            headers["AppKey"] = appKey;
            headers["Nonce"] = nonce;
            headers["CurTime"] = curTime;
            headers["CheckSum"] = checkSum;
            headers["ContentType"] = "application/x-www-form-urlencoded;charset=utf-8";
            //执行 HTTP 请求
            HttpClient.HttpPost(url, null, headers);
        }
    }
}
Python
Python# coding=utf-8
import hashlib
import time
import requests

def send_code(mobile):
    url = 'https://sms.yunxinapi.com/sms/sendcode.action'
    """
    AppKey    网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
    Nonce    随机数(最大长度 128 个字符)
    CurTime    当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
    CheckSum    SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
    """
    AppKey = ""
    # 生成 128 个长度以内的随机字符串
    nonce = hashlib.new('sha512', str(time.time()).encode("utf-8")).hexdigest()
    # 获取当前时间戳
    curtime = str(int(time.time()))
    # 网易云信的 App Secret
    AppSecret = ""
    # 根据要求进行 SHA1 哈希计算
    check_sum = hashlib.sha1((AppSecret + nonce + curtime).encode("utf-8")).hexdigest()

    header = {
        "AppKey": AppKey,
        "Nonce": nonce,
        "CurTime": curtime,
        "CheckSum": check_sum
    }

    data = {
        'mobile': mobile, # 手机号
        "templateid": 123456,

    }

    resp = requests.post(url, data=data, headers=header)

    print("Response:", resp.content)

if __name__ == '__main__':
    send_code("12345678910") #要发送的手机号
PHP
PHP<?php

/**
 * 网易云信 server API 简单实例
 * Class ServerAPI
 * @author chensheng dengyuan
 * @created date    2018-02-02 13:45
 *
 *
 ***/

class ServerAPI
{
    public $AppKey;                //网易云信控制台分配的 AppKey
    public $AppSecret;             //网易云信控制台分配的 AppSecret,可刷新
    public $Nonce;                    //随机数(最大长度 128 个字符)
    public $CurTime;                 //当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
    public $CheckSum;                //SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
    const HEX_DIGITS = "0123456789abcdef";

    /**
     * 参数初始化
     * @param $AppKey
     * @param $AppSecret
     * @param $RequestType [选择 php 请求方式,fsockopen 或 curl,若为 curl 方式,请检查 php 配置是否开启]
     */
    public function __construct($AppKey, $AppSecret, $RequestType = 'curl')
    {
        $this->AppKey = $AppKey;
        $this->AppSecret = $AppSecret;
        $this->RequestType = $RequestType;
    }

    /**
     * API checksum 校验生成
     * @param void
     * @return $CheckSum(对象私有属性)
     */
    public function checkSumBuilder()
    {
        //此部分生成随机字符串
        $hex_digits = self::HEX_DIGITS;
        $this->Nonce;
        for ($i = 0; $i < 128; $i++) {            //随机字符串最大 128 个字符,也可以小于该数
            $this->Nonce .= $hex_digits[rand(0, 15)];
        }
        $this->CurTime = (string)(time());    //当前时间戳,以秒为单位

        $join_string = $this->AppSecret . $this->Nonce . $this->CurTime;
        $this->CheckSum = sha1($join_string);
        //print_r($this->CheckSum);
    }

    /**
     * 将 json 字符串转化成 php 数组
     * @param $json_str
     * @return $json_arr
     */
    public function json_to_array($json_str)
    {

        if (is_array($json_str) || is_object($json_str)) {
            $json_str = $json_str;
        } else if (is_null(json_decode($json_str))) {
            $json_str = $json_str;
        } else {
            $json_str = strval($json_str);
            $json_str = json_decode($json_str, true);
        }
        $json_arr = array();
        foreach ($json_str as $k => $w) {
            if (is_object($w)) {
                $json_arr[$k] = $this->json_to_array($w); //判断类型是不是 object
            } else if (is_array($w)) {
                $json_arr[$k] = $this->json_to_array($w);
            } else {
                $json_arr[$k] = $w;
            }
        }
        return $json_arr;
    }

    /**
     * 使用 CURL 方式发送 post 请求
     * @param $url     [请求地址]
     * @param $data    [array 格式数据]
     * @return $请求返回结果(array)
     */
    public function postDataCurl($url, $data)
    {
        $this->checkSumBuilder();       //发送请求前需先生成 checkSum

        $timeout = 5000;
        $http_header = array(
            'AppKey:' . $this->AppKey,
            'Nonce:' . $this->Nonce,
            'CurTime:' . $this->CurTime,
            'CheckSum:' . $this->CheckSum,
            'Content-Type:application/x-www-form-urlencoded;charset=utf-8'
        );
        //print_r($http_header);

        // $postdata = '';
        $postdataArray = array();
        foreach ($data as $key => $value) {
            array_push($postdataArray, $key . '=' . urlencode($value));
        }
        $postdata = join('&', $postdataArray);

        // var_dump($postdata);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //处理 http 证书问题
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $result = curl_exec($ch);
        if (false === $result) {
            $result = curl_errno($ch);
        }
        curl_close($ch);
        return $this->json_to_array($result);
    }

    /**
     * 使用 FSOCKOPEN 方式发送 post 请求
     * @param $url     [请求地址]
     * @param $data    [array 格式数据]
     * @return $请求返回结果(array)
     */
    public function postDataFsockopen($url, $data)
    {
        $this->checkSumBuilder();//发送请求前需先生成 checkSum

        $postdata = '';
        foreach ($data as $key => $value) {
            $postdata .= ($key . '=' . urlencode($value) . '&');
        }
        // building POST-request:
        $URL_Info = parse_url($url);
        if (!isset($URL_Info["port"])) {
            $URL_Info["port"] = 80;
        }
        $request = '';
        $request .= "POST " . $URL_Info["path"] . " HTTP/1.1\r\n";
        $request .= "Host:" . $URL_Info["host"] . "\r\n";
        $request .= "Content-type: application/x-www-form-urlencoded;charset=utf-8\r\n";
        $request .= "Content-length: " . strlen($postdata) . "\r\n";
        $request .= "Connection: close\r\n";
        $request .= "AppKey: " . $this->AppKey . "\r\n";
        $request .= "Nonce: " . $this->Nonce . "\r\n";
        $request .= "CurTime: " . $this->CurTime . "\r\n";
        $request .= "CheckSum: " . $this->CheckSum . "\r\n";
        $request .= "\r\n";
        $request .= $postdata . "\r\n";

        print_r($request);
        $fp = fsockopen($URL_Info["host"], $URL_Info["port"]);
        fputs($fp, $request);
        $result = '';
        while (!feof($fp)) {
            $result .= fgets($fp, 128);
        }
        fclose($fp);

        $str_s = strpos($result, '{');
        $str_e = strrpos($result, '}');
        $str = substr($result, $str_s, $str_e - $str_s + 1);
        print_r($result);
        return $this->json_to_array($str);
    }

    /**
     * 发送短信验证码
     * @param $templateid    [模板编号(由客服配置之后告知开发者)]
     * @param $mobile       [目标手机号]
     * @param $deviceId     [目标设备号,可选参数]
     * @return $codeLen      [验证码长度,范围 4~10,默认为 4]
     */
    public function sendSmsCode($templateid, $mobile, $deviceId = '', $codeLen)
    {
        $url = 'https://sms.yunxinapi.com/sms/sendcode.action';
        $data = array(
            'templateid' => $templateid,
            'mobile' => $mobile,
            'deviceId' => $deviceId,
            'codeLen' => $codeLen
        );
        if ($this->RequestType == 'curl') {
            $result = $this->postDataCurl($url, $data);
        } else {
            $result = $this->postDataFsockopen($url, $data);
        }
        return $result;
    }

    /**
     * 发送模板短信
     * @param $templateid       [模板编号(由客服配置之后告知开发者)]
     * @param $mobiles          [验证码]
     * @param $params          [短信参数列表,用于依次填充模板,JSONArray 格式,如["xxx","yyy"];对于不包含变量的模板,不填此参数表示模板即短信全文内容]
     * @return $result      [返回 array 数组对象]
     */
    public function sendSMSTemplate($templateid, $mobiles = array(), $params = '')
    {
        $url = 'https://sms.yunxinapi.com/sms/sendtemplate.action';
        $data = array(
            'templateid' => $templateid,
            'mobiles' => json_encode($mobiles),
            'params' => json_encode($params)
        );
        if ($this->RequestType == 'curl') {
            $result = $this->postDataCurl($url, $data);
        } else {
            $result = $this->postDataFsockopen($url, $data);
        }
        return $result;
    }

}

?>

发送通知类和运营类短信

通知类和运营类短信使用模板发送,支持批量发送和参数替换。

请求参数

参数名 数据类型 是否必填 说明
templateid String 短信模板 ID
mobiles String 接收方手机号列表,JSON 数组格式,如 ["13888888888","13666666666"]
最多支持 100 个号码
params String 模板参数列表,JSON 数组格式,如 ["参数1","参数2"]
用于填充模板中的变量,每个参数长度不超过 30 字符

重要说明

  1. 参数格式mobilesparams 都必须是 JSON 数组格式的字符串
  2. 参数对应params 中的参数按顺序填充模板中的 %s 占位符
  3. 批量限制:单次请求最多支持 100 个手机号
  4. 无变量模板:对于不包含变量的模板,可不传 params 参数
Java
Javapackage com.netease.code;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.netease.checksum.CheckSumBuilder;
/**
 * 发送模板短信请求
 * @author liuxuanlin
 *
 */
public class SendTemplate {
    //发送通知类和运营类短信的请求路径 URL
    private static final String
            SERVER_URL="https://sms.yunxinapi.com/sms/sendtemplate.action";
    //网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
    private static final String
            APP_KEY="fd460d34e786e7754e505bc4fab0f027";
    //网易云信分配的密钥,请替换您在网易云信控制台应用下创建的 appSecret
    private static final String APP_SECRET="xxxxxxxx";
    //随机数
    private static final String NONCE="123456";
    //短信模板 ID
    private static final String TEMPLATEID="3057527";
    //手机号,接收者号码列表,JSONArray 格式,限制接收者号码个数最多为 100 个
    private static final String MOBILES="['13888888888','13666666666']";
    //短信参数列表,用于依次填充模板,JSONArray 格式,每个变量长度不能超过 30 字,对于不包含变量的模板,不填此参数表示模板即短信全文内容
    private static final String PARAMS="['xxxx','xxxx']";

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

        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(SERVER_URL);
        String curTime = String.valueOf((new Date()).getTime() / 1000L);
        /*
         * 参考计算 CheckSum 的 java 代码,在上述文档的参数列表中,有 CheckSum 的计算文档示例
         */
        String checkSum = CheckSumBuilder.getCheckSum(APP_SECRET, NONCE, curTime);

        // 设置请求的 header
        httpPost.addHeader("AppKey", APP_KEY);
        httpPost.addHeader("Nonce", NONCE);
        httpPost.addHeader("CurTime", curTime);
        httpPost.addHeader("CheckSum", checkSum);
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

        // 设置请求的的参数,requestBody 参数
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        /*
         * 1.如果是模板短信,请注意参数 mobile 是有 s 的,详细参数配置请参考 **发送模板短信文档**
         * 2.参数格式是 jsonArray 的格式,例如 "['13888888888','13666666666']"
         * 3.params 是根据您模板里面有几个参数,那里面的参数也是 jsonArray 格式
         */
        nvps.add(new BasicNameValuePair("templateid", TEMPLATEID));
        nvps.add(new BasicNameValuePair("mobiles", MOBILES));
        nvps.add(new BasicNameValuePair("params", PARAMS));

        httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));

        // 执行请求
        HttpResponse response = httpClient.execute(httpPost);
        /*
         * 1.打印执行结果,打印结果一般会 200、315、403、404、413、414、500
         * 2.具体的 code 有问题的可以参考官网的 Code 状态表
         */
        System.out.println(EntityUtils.toString(response.getEntity(), "utf-8"));

    }
}
C#
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Net;
using System.IO;

namespace server_http_api
{
    class CheckSumBuilder
    {
        // 计算并获取 CheckSum
        public static String getCheckSum(String appSecret, String nonce, String curTime)
        {
            byte[] data = Encoding.Default.GetBytes(appSecret + nonce + curTime);
            byte[] result;

            SHA1 sha = new SHA1CryptoServiceProvider();
            // This is one implementation of the abstract class SHA1.
            result = sha.ComputeHash(data);

            return getFormattedText(result);
        }

        // 计算并获取 md5 值
        public static String getMD5(String requestBody)
        {
            if (requestBody == null)
                return null;

            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(requestBody));

            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            // Return the hexadecimal string.
            return getFormattedText(Encoding.Default.GetBytes(sBuilder.ToString()));
        }

        private static String getFormattedText(byte[] bytes)
        {
            char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            int len = bytes.Length;
            StringBuilder buf = new StringBuilder(len * 2);
            for (int j = 0; j < len; j++) {
                buf.Append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
                buf.Append(HEX_DIGITS[bytes[j] & 0x0f]);
            }
            return buf.ToString();
        }
    }

    class HttpClient
    {
        //发起 HTTP 请求
        public static void HttpPost(string url, Stream data, IDictionary<object, string> headers = null)
        {
            System.Net.WebRequest request = HttpWebRequest.Create(url);
            request.Method = "POST";
            if (data != null)
            request.ContentLength = data.Length;
            //request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";

            if (headers != null)
            {
                foreach (var v in headers)
                {
                    if (v.Key is HttpRequestHeader)
                        request.Headers[(HttpRequestHeader)v.Key] = v.Value;
                    else
                        request.Headers[v.Key.ToString()] = v.Value;
                }
            }
            HttpWebResponse response = null;
            try
            {
                // Get the response.
                response = (HttpWebResponse)request.GetResponse();
                // Display the status.
                Console.WriteLine(response.StatusDescription);
                // Get the stream containing content returned by the server.
                Stream dataStream = response.GetResponseStream();
                // Open the stream using a StreamReader for easy access.
                StreamReader reader = new StreamReader(dataStream);
                // Read the content.
                string responseFromServer = reader.ReadToEnd();
                // Display the content.
                Console.WriteLine(responseFromServer);
                // Cleanup the streams and the response.
                reader.Close();
                dataStream.Close();
                response.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(response.StatusDescription);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            String url = "https://sms.yunxinapi.com/sms/sendtemplate.action";
            url += "?templateid=3030410&mobiles=['13888888888','13666666666']&params=['xxxx','xxxx']";//请输入正确的手机号

            //网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
            String appKey = "fd460d34e786e7754e505bc4fab0f027";
            //网易云信分配的密钥,请替换您在网易云信控制台应用下创建的 appSecret
            String appSecret = "xxxxxxxx";
            //随机数(最大长度 128 个字符)
            String nonce = "12345";

            TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1);
            Int32 ticks = System.Convert.ToInt32(ts.TotalSeconds);
            //当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
            String curTime = ticks.ToString();
            //SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
            String checkSum = CheckSumBuilder.getCheckSum(appSecret, nonce, curTime);

            IDictionary<object, String> headers = new Dictionary<object, String>();
            headers["AppKey"] = appKey;
            headers["Nonce"] = nonce;
            headers["CurTime"] = curTime;
            headers["CheckSum"] = checkSum;
            headers["ContentType"] = "application/x-www-form-urlencoded;charset=utf-8";
            //执行 HTTP 请求
            HttpClient.HttpPost(url, null, headers);
        }
    }
}
Python
Python# coding=utf-8
import hashlib
import time
import requests
import json

def send_notice(mobiles,params):
    url = 'https://sms.yunxinapi.com/sms/sendtemplate.action'
    """
    AppKey    网易云信分配的账号,请替换您在网易云信控制台应用下创建的 Appkey
    Nonce    随机数(最大长度 128 个字符)
    CurTime    当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
    CheckSum    SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
    """
    AppKey = ""
    # 生成 128 个长度以内的随机字符串
    nonce = hashlib.new('sha512', str(time.time()).encode("utf-8")).hexdigest()
    # 获取当前时间戳
    curtime = str(int(time.time()))
    # 网易云信的 App Secret
    AppSecret = ""
    # 根据要求进行 SHA1 哈希计算
    check_sum = hashlib.sha1((AppSecret + nonce + curtime).encode("utf-8")).hexdigest()

    header = {
        "AppKey": AppKey,
        "Nonce": nonce,
        "CurTime": curtime,
        "CheckSum": check_sum
    }

    data = {
        'mobiles': json.dumps(mobiles), # 手机号
        "templateid": 123456, # 模板 ID
        "params":json.dumps(params),

    }

    resp = requests.post(url, data=data, headers=header)

    print("Response:", resp.content)

if __name__ == '__main__':
    mobiles = ["12345678910", "12345678911"] # 要发送的手机号
    params = ["name","day"] # 模板中的变量
    send_notice(mobiles,params)
PHP
PHP<?php

/**
 * 网易云信 server API 简单实例
 * Class ServerAPI
 * @author chensheng dengyuan
 * @created date    2018-02-02 13:45
 *
 *
 ***/

class ServerAPI
{
    public $AppKey;                //网易云信控制台分配的 AppKey
    public $AppSecret;             //网易云信控制台分配的 AppSecret,可刷新
    public $Nonce;                    //随机数(最大长度 128 个字符)
    public $CurTime;                 //当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数(String)
    public $CheckSum;                //SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行 SHA1 哈希计算,转化成 16 进制字符(String,小写)
    const HEX_DIGITS = "0123456789abcdef";

    /**
     * 参数初始化
     * @param $AppKey
     * @param $AppSecret
     * @param $RequestType [选择 php 请求方式,fsockopen 或 curl,若为 curl 方式,请检查 php 配置是否开启]
     */
    public function __construct($AppKey, $AppSecret, $RequestType = 'curl')
    {
        $this->AppKey = $AppKey;
        $this->AppSecret = $AppSecret;
        $this->RequestType = $RequestType;
    }

    /**
     * API checksum 校验生成
     * @param void
     * @return $CheckSum(对象私有属性)
     */
    public function checkSumBuilder()
    {
        //此部分生成随机字符串
        $hex_digits = self::HEX_DIGITS;
        $this->Nonce;
        for ($i = 0; $i < 128; $i++) {            //随机字符串最大 128 个字符,也可以小于该数
            $this->Nonce .= $hex_digits[rand(0, 15)];
        }
        $this->CurTime = (string)(time());    //当前时间戳,以秒为单位

        $join_string = $this->AppSecret . $this->Nonce . $this->CurTime;
        $this->CheckSum = sha1($join_string);
        //print_r($this->CheckSum);
    }

    /**
     * 将 json 字符串转化成 php 数组
     * @param $json_str
     * @return $json_arr
     */
    public function json_to_array($json_str)
    {

        if (is_array($json_str) || is_object($json_str)) {
            $json_str = $json_str;
        } else if (is_null(json_decode($json_str))) {
            $json_str = $json_str;
        } else {
            $json_str = strval($json_str);
            $json_str = json_decode($json_str, true);
        }
        $json_arr = array();
        foreach ($json_str as $k => $w) {
            if (is_object($w)) {
                $json_arr[$k] = $this->json_to_array($w); //判断类型是不是 object
            } else if (is_array($w)) {
                $json_arr[$k] = $this->json_to_array($w);
            } else {
                $json_arr[$k] = $w;
            }
        }
        return $json_arr;
    }

    /**
     * 使用 CURL 方式发送 post 请求
     * @param $url     [请求地址]
     * @param $data    [array 格式数据]
     * @return $请求返回结果(array)
     */
    public function postDataCurl($url, $data)
    {
        $this->checkSumBuilder();       //发送请求前需先生成 checkSum

        $timeout = 5000;
        $http_header = array(
            'AppKey:' . $this->AppKey,
            'Nonce:' . $this->Nonce,
            'CurTime:' . $this->CurTime,
            'CheckSum:' . $this->CheckSum,
            'Content-Type:application/x-www-form-urlencoded;charset=utf-8'
        );
        //print_r($http_header);

        // $postdata = '';
        $postdataArray = array();
        foreach ($data as $key => $value) {
            array_push($postdataArray, $key . '=' . urlencode($value));
        }
        $postdata = join('&', $postdataArray);

        // var_dump($postdata);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $http_header);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //处理 http 证书问题
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $result = curl_exec($ch);
        if (false === $result) {
            $result = curl_errno($ch);
        }
        curl_close($ch);
        return $this->json_to_array($result);
    }

    /**
     * 使用 FSOCKOPEN 方式发送 post 请求
     * @param $url     [请求地址]
     * @param $data    [array 格式数据]
     * @return $请求返回结果(array)
     */
    public function postDataFsockopen($url, $data)
    {
        $this->checkSumBuilder();//发送请求前需先生成 checkSum

        $postdata = '';
        foreach ($data as $key => $value) {
            $postdata .= ($key . '=' . urlencode($value) . '&');
        }
        // building POST-request:
        $URL_Info = parse_url($url);
        if (!isset($URL_Info["port"])) {
            $URL_Info["port"] = 80;
        }
        $request = '';
        $request .= "POST " . $URL_Info["path"] . " HTTP/1.1\r\n";
        $request .= "Host:" . $URL_Info["host"] . "\r\n";
        $request .= "Content-type: application/x-www-form-urlencoded;charset=utf-8\r\n";
        $request .= "Content-length: " . strlen($postdata) . "\r\n";
        $request .= "Connection: close\r\n";
        $request .= "AppKey: " . $this->AppKey . "\r\n";
        $request .= "Nonce: " . $this->Nonce . "\r\n";
        $request .= "CurTime: " . $this->CurTime . "\r\n";
        $request .= "CheckSum: " . $this->CheckSum . "\r\n";
        $request .= "\r\n";
        $request .= $postdata . "\r\n";

        print_r($request);
        $fp = fsockopen($URL_Info["host"], $URL_Info["port"]);
        fputs($fp, $request);
        $result = '';
        while (!feof($fp)) {
            $result .= fgets($fp, 128);
        }
        fclose($fp);

        $str_s = strpos($result, '{');
        $str_e = strrpos($result, '}');
        $str = substr($result, $str_s, $str_e - $str_s + 1);
        print_r($result);
        return $this->json_to_array($str);
    }

    /**
     * 发送模板短信
     * @param $templateid       [模板编号(由客服配置之后告知开发者)]
     * @param $mobiles          [验证码]
     * @param $params          [短信参数列表,用于依次填充模板,JSONArray 格式,如["xxx","yyy"];对于不包含变量的模板,不填此参数表示模板即短信全文内容]
     * @return $result      [返回 array 数组对象]
     */
    public function sendSMSTemplate($templateid, $mobiles = array(), $params = '')
    {
        $url = 'https://sms.yunxinapi.com/sms/sendtemplate.action';
        $data = array(
            'templateid' => $templateid,
            'mobiles' => json_encode($mobiles),
            'params' => json_encode($params)
        );
        if ($this->RequestType == 'curl') {
            $result = $this->postDataCurl($url, $data);
        } else {
            $result = $this->postDataFsockopen($url, $data);
        }
        return $result;
    }
}
?>

相关参考

余额预警设置

余额预警功能可帮助您及时了解账户余额状况,避免因余额不足导致服务中断。设置方法请参考 设置余额预警

短信回执抄送

网易云信支持短信回执抄送功能,详细配置请参考 消息抄送服务

抄送类型说明:

事件类型 类型值 说明
SMS_CALLBACK 11 短信回执抄送消息
SMS_REPLY 12 短信上行消息抄送

抄送规则:

  • 只有通道返回回执时才会抄送
  • 包含发送成功和失败的回执
  • 反垃圾拦截的短信不会抄送

配置抄送地址请参考 开通和配置消息抄送

依赖包下载

Java 开发所需 JAR 包:

或使用 Maven 依赖:

xml<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.1</version>
</dependency>
此文档是否对你有帮助?
有帮助
去反馈
  • 短信类型
  • 调用说明
  • 服务地址
  • 请求 URL
  • 请求头
  • CheckSum 计算示例
  • 发送验证码短信
  • 请求参数
  • 代码示例
  • 发送通知类和运营类短信
  • 请求参数
  • 重要说明
  • 相关参考
  • 余额预警设置
  • 短信回执抄送
  • 依赖包下载