批量发送API
提示:#
- 因为运营商政策,请先在后台完成企业认证、报备签名、模板及做相关设置,再开发 API。
- 批量接口上限为1000,发送验证码短信不建议使用一次发送多条,可能会造成验证码发送延迟。
HTTP 头信息(具体参考调用说明):#
Accept:application/json;charset=utf-8; Content-Type:application/json;charset=utf-8; X-SIGNATURE: $signature; X-APIKEY: $APIKEY; X-TIMESTAMP: $timestamp; X-NONCE: $nonce;请求#
URL:`https://gateway.yihuitong.top/openapi/sms/batchSend` 访问方式:POST请求参数#
| 参数名 | 类型 | 是否必传 | 是否默认开放 | 描述 | 示例 |
|---|---|---|---|---|---|
| data | object[] | 是 | 是 | 数据对象 | |
| callbackUrl | string | 否 | 是 | 短信发送后将向这个地址推送(运营商返回的)发送报告。 如推送地址固定,建议在"数据推送与获取”做批量设置。 如后台已设置地址,且请求内也包含此参数,将以请求内地址为准 | http://your_receive_url_address |
data[] 参数子项#
| 参数名 | 类型 | 是否必传 | 是否默认开放 | 描述 | 示例 |
|---|---|---|---|---|---|
| text | string | 是 | 是 | 需要发送的短信内容,需要与已审核的短信模板相匹配。短信内容须在最前面携带审核通过的签名。 | 【易荟通】尊敬的用户:您的验证码:707892,工作人员不会索取,请勿泄漏。 |
| mobile | string | 是 | 是 | 接收的手机号,不需要带+86 前缀 | 18011111111 |
| busId | string | 否 | 是 | 该条短信在您业务系统内的 ID,如订单号或者短信发送记录流水号。 | 10001 |
代码示例(头信息加密验签参考)#
- Java
- C#
- PHP
/** * 批量发送短信,相同内容多个号码,智能匹配短信模板 * * @param apikey 成功注册后登录云片官网,进入后台可查看 * @param text 需要使用已审核通过的模板或者默认模板 * @param mobile 接收的手机号,多个手机号用英文逗号隔开 * @return json格式字符串 */public static String batchSend(String apikey, String text, String mobile) throws NoSuchAlgorithmException , InvalidKeyException { String smsUrl = "https://gateway.yihuitong.top/openapi/sms/batchSend"; String nonce = "bc9efee185e64ab9bc0b07a2785c4660"; Integer timestamp = 1626856279; String apikey = "123456789"; String secretKey = "1234567890"; String method = "POST"; String path = "/openapi/sms/batchSend"; String contentType = "json"; List<Map<String, String>> dataList = new ArrayList<>(); Map<String, String> dataMap = new HashMap<>(); dataMap.put("text", "【易荟通】尊敬的用户:您的验证码:707892,工作人员不会索取,请勿泄漏。"); dataMap.put("mobile", "11111111111"); dataList.add(dataMap); Map<String, Object> parameters = new HashMap<>(); parameters.put("data", dataList); StringBuilder sb = new StringBuilder(); sb.append(method).append("\n") .append(path).append("\n") .append(apikey).append("\n") .append(timestamp).append("\n") .append(nonce).append("\n"); if(parameters!=null && !parameters.isEmpty()) { if("json".equals(contentType) ) { sb.append(JSON.toJSONString(parameters)).append("\n"); }else { String canonical_query_string = formatUrlMap(parameters, true, false); sb.append(canonical_query_string).append("\n"); } }
Mac hasher = Mac.getInstance("HmacSHA256"); hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256")); byte[] hash = hasher.doFinal(sb.toString().getBytes()); Map<String,String> headers = new HashMap<String, String>(); headers.put("X-SIGNATURE", DatatypeConverter.printBase64Binary(hash)); headers.put("X-APIKEY", apikey); headers.put("X-TIMESTAMP", timestamp.toString()); headers.put("X-NONCE", nonce); return HttpUtil.postForJson(smsUrl, parameters, headers);//请自行使用post方式请求,可使用Apache HttpClient}
//编译版本 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;using System.Collections.Generic;using System.Linq;using System.Text.RegularExpressions;using Newtonsoft.Json;using System.Security.Cryptography;using System.Net;using System.IO;using System.Text;
namespace YiHuiTong{ public class Signature { public static void Main(string[] args) { string smsUrl = "https://gateway.yihuitong.top/openapi/sms/batchSend"; string nonce = System.Guid.NewGuid().ToString("N"); string timestamp = time(); string apikey = "123456789"; string secretKey = "1234567890"; string method = "POST"; string path = "/openapi/sms/batchSend"; Dictionary<string, string> dataMap = new Dictionary<string, string>(); dataMap.Add("text", "【易荟通】尊敬的用户:您的验证码:707892,工作人员不会索取,请勿泄漏。"); dataMap.Add("mobile","11111111111"); List<Dictionary<string, string>> dataList = new List<Dictionary<string, string>>(); dataList.Add(dataMap); Dictionary<string, Object> map = new Dictionary<string, Object>(); map.Add("data",dataList); string message = new HmacStringBuild(SigningHeadersContentType.JSON) .setMethod(method) .setPath(path) .setApikey(apikey) .setTimestamp(timestamp) .setNonce(nonce) .setData(map) .build(); Console.WriteLine(message); string SIGNATURE = CreateToken(message,secretKey); Console.WriteLine(SIGNATURE); Dictionary<string, string> headers = new Dictionary<string, string>(); headers.Add("X-SIGNATURE",SIGNATURE); headers.Add("X-TIMESTAMP",timestamp); headers.Add("X-APIKEY",apikey); headers.Add("X-NONCE",nonce); string returnData = Post(smsUrl,JsonConvert.SerializeObject(map).ToString(),headers); Console.WriteLine(returnData); } public static string CreateToken(string message, string secretKey) { secretKey = secretKey ?? ""; var encoding = new System.Text.UTF8Encoding(); byte[] keyByte = encoding.GetBytes(secretKey); byte[] messageBytes = encoding.GetBytes(message); using (var hmacsha256 = new HMACSHA256(keyByte)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashmessage); } } public static string time() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } public static string formatUrlMap(Dictionary<string, Object> paraMap,bool urlEncode) { string para = ""; foreach (KeyValuePair<string, Object> kvp in paraMap) { string key = kvp.Key; string _value = kvp.Value.ToString(); if(urlEncode) { key = System.Web.HttpUtility.UrlEncode(key); if(_value!=null && _value.Length==0){ _value = System.Web.HttpUtility.UrlEncode(_value); } } para += key + "=" + _value + "&"; } return para.Substring(0,para.Length - 1); } public static string Post(string serviceUrl, string parameterData,Dictionary<string, string> headers) {
//创建Web访问对象 HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl); //把用户传过来的数据转成“UTF-8”的字节流 byte[] buf = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(parameterData);
myRequest.Method = "POST"; myRequest.Accept = "application/json"; myRequest.AutomaticDecompression = DecompressionMethods.GZip; myRequest.ContentType = "application/json; charset=UTF-8"; myRequest.ContentLength = buf.Length; myRequest.MaximumAutomaticRedirections = 1; myRequest.AllowAutoRedirect = true;
myRequest.Headers.Add("X-SIGNATURE", headers["X-SIGNATURE"]); myRequest.Headers.Add("X-TIMESTAMP", headers["X-TIMESTAMP"]); myRequest.Headers.Add("X-APIKEY", headers["X-APIKEY"]); myRequest.Headers.Add("X-NONCE", headers["X-NONCE"]);
//发送请求 Stream stream = myRequest.GetRequestStream(); stream.Write(buf, 0, buf.Length); stream.Close();
//通过Web访问对象获取响应内容 HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse(); //通过响应内容流创建StreamReader对象,因为StreamReader更高级更快 StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8); //string returnXml = HttpUtility.UrlDecode(reader.ReadToEnd());//如果有编码问题就用这个方法 string returnData = reader.ReadToEnd();//利用StreamReader就可以从响应内容从头读到尾
reader.Close(); myResponse.Close();
return returnData; } } class HmacStringBuild { private SigningHeadersContentType contentType; private string method; private string path; private string apikey; private string timestamp; private string nonce; private Dictionary<string, System.Object> data; public HmacStringBuild(SigningHeadersContentType contentType){ this.contentType = contentType; } public HmacStringBuild setMethod(string method){ this.method = method; return this; } public HmacStringBuild setPath(string path){ this.path = path; return this; } public HmacStringBuild setApikey(string apikey){ this.apikey = apikey; return this; } public HmacStringBuild setTimestamp(string timestamp){ this.timestamp = timestamp; return this; } public HmacStringBuild setNonce(string nonce){ this.nonce = nonce; return this; } public HmacStringBuild setData(Dictionary<string, System.Object> data){ this.data = data; return this; } public string build(){ String str = this.method + "\n" + this.path + "\n" + this.apikey + "\n" + this.timestamp + "\n" + this.nonce + "\n"; if(string.Equals("GET",this.method)){ str = str + Signature.formatUrlMap(this.data,true) + "\n"; }else if(contentType == SigningHeadersContentType.JSON){ str = str + JsonConvert.SerializeObject(this.data) + "\n"; }else{ str = str + Signature.formatUrlMap(this.data,false) + "\n"; } return str; } } enum SigningHeadersContentType{ JSON,FORM };}<?php
function uuid() { $chars = md5(uniqid(mt_rand(), true)); $uuid = substr ( $chars, 0, 8 ) . '-' . substr ( $chars, 8, 4 ) . '-' . substr ( $chars, 12, 4 ) . '-' . substr ( $chars, 16, 4 ) . '-' . substr ( $chars, 20, 12 ); return $uuid ; } function http_post_data($url, $data_string, $header) {
echo json_encode($header); $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_HTTPHEADER, $header ); ob_start(); curl_exec($ch); $return_content = ob_get_contents(); ob_end_clean();
$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); return array($return_code, $return_content); } $smsUrl = "https://gateway.yihuitong.top/openapi/sms/batchSend"; $nonce = uuid(); $timestamp = time(); $apikey = "123456789"; $secretKey = "1234567890"; $method = "POST"; $path = "/openapi/sms/batchSend"; $dataMap = array(['text'=> '【易荟通】尊敬的用户:您的验证码:707892,工作人员不会索取,请勿泄漏。','mobile'=> '11111111111']); $data = json_encode(array('data'=> $dataMap)); echo $data; $message = $method . "\n" . $path . "\n" . $apikey . "\n" . $timestamp . "\n" . $nonce . "\n" . $data . "\n";
$SIGNATURE = base64_encode(hash_hmac('sha256', $message, $secretKey,true)); // to base64
$header = array( 'X-SIGNATURE: ' . $SIGNATURE, 'X-TIMESTAMP: ' . $timestamp, 'X-APIKEY: ' . $apikey, 'X-NONCE: ' . $nonce, 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($data) );
list($return_code, $return_content) = http_post_data($smsUrl, $data, $header);
echo $return_code; echo $return_content;?>响应参数#
| 名称 | 类型 | 描述 |
|---|---|---|
| success | boolean | 是否请求成功 false 为接口请求失败,请求失败 data 中无数据 |
| errorCode | string | 错误码 200 代表成功 |
| errorMessage | string | 错误提示 |
| data | object[] | 报告数据,是一个数组;格式参考下面 |
data 响应参数#
| 名称 | 类型 | 描述 |
|---|---|---|
| totalCount | integer | 扣费条数,70 个字一条,超出 70 个字时按每 67 字一条计 |
| totalFee | double | 扣费金额,单位:元 类型:双精度浮点型/double |
| unit | string | 计费单位;例如:“RMB” |
| data | object[] | 短信发送返回的数据 |
短信发送 data 响应参数#
| 名称 | 类型 | 描述 |
|---|---|---|
| sid | long(64 位) | 短信 id,64 位整型, 对应 Java 和 C#的 long,不可用 int 解析 |
| code | string | 00-提交中;01-提交失败;02-提交成功 |
| errorCode | string | 提交失败错误码 |
| count | integer | 发送成功短信的计费条数(计费条数:70 个字一条,超出 70 个字时按每 67 字一条计费) |
| fee | double | 扣费金额,单位:元,类型:双精度浮点型/double |
| mobile | string | 发送手机号 |
| msg | string | 例如""发送成功"",或者相应错误信息 |
| busId | string | 该条短信在您业务系统内的 ID,如订单号或者短信发送记录流水号。 |
| unit | string | 计费单位;例如:“RMB” |
JSON 响应示例#
{ "success": true, "errorCode": "200", "errorMessage": "成功", "data": { "totalCount": 1, "totalFee": 0.0500, "unit": "RMB", "data": [ { "code": "02", "errorCode": "", "count": 1, "fee": 0.05, "unit": "RMB", "mobile": "1234567890123456", "msg": "", "busId": "123456", "sid": 42007252230 }, { "code": "01", "errorCode": "4404", "count": 0, "fee": 0, "mobile": "15800000000", "msg": "扣款失败", "busId": "123456", "sid": 0, "unit": "RMB" } ] }}errorCode 状态码列表#
| errorCode | 描述 |
|---|---|
| 4001 | 用户信息不正确 |
| 4100 | 参数错误 |
| 4300 | 金额不足 |
| 4301 | 账号未认证,请先认证通过后访问 |
| 4400 | 短信签名错误 |
| 4401 | 模板错误 |
| 4402 | 提交失败 |
| 4404 | 扣费失败 |
| 5000 | 内部错误 |