Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

718 wiersze
22 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8. using Newtonsoft.Json;
  9. using Newtonsoft.Json.Linq;
  10. // newtonsoft json 模块请自行到 http://www.newtonsoft.com/json 下载
  11. // 注意 json 库中有 .net 的多个版本,请开发者集成自己项目相应 .net 版本的 json 库
  12. namespace Quanjiang.DigitalScholl.SendSms.Banling
  13. {
  14. namespace Sms
  15. {
  16. class SmsSingleSender
  17. {
  18. string sdkappid;
  19. string appkey;
  20. string url = "https://msg.yundashi.com/api/sms/sendsms";
  21. SmsSenderUtil util = new SmsSenderUtil();
  22. public SmsSingleSender(string sdkappid, string appkey)
  23. {
  24. this.sdkappid = sdkappid;
  25. this.appkey = appkey;
  26. }
  27. /**
  28. * 普通单发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名
  29. * @param type 短信类型,0 为普通短信,1 营销短信
  30. * @param nationCode 国家码,如 86 为中国
  31. * @param phoneNumber 不带国家码的手机号
  32. * @param msg 信息内容,必须与申请的模板格式一致,否则将返回错误
  33. * @param extend 扩展码,可填空
  34. * @param ext 服务端原样返回的参数,可填空
  35. * @return SmsSingleSenderResult
  36. */
  37. public SmsSingleSenderResult Send(
  38. int type,
  39. string nationCode,
  40. string phoneNumber,
  41. string msg,
  42. string extend,
  43. string ext)
  44. {
  45. /*
  46. 请求包体
  47. {
  48. "tel": {
  49. "nationcode": "86",
  50. "mobile": "13788888888"
  51. },
  52. "type": 0,
  53. "msg": "你的验证码是1234",
  54. "sig": "fdba654e05bc0d15796713a1a1a2318c",
  55. "time": 1479888540,
  56. "extend": "",
  57. "ext": ""
  58. }
  59. 应答包体
  60. {
  61. "result": 0,
  62. "errmsg": "OK",
  63. "ext": "",
  64. "sid": "xxxxxxx",
  65. "fee": 1
  66. }
  67. */
  68. if (0 != type && 1 != type)
  69. {
  70. throw new Exception("type " + type + " error");
  71. }
  72. if (null == extend)
  73. {
  74. extend = "";
  75. }
  76. if (null == ext)
  77. {
  78. ext = "";
  79. }
  80. long random = util.GetRandom();
  81. long curTime = util.GetCurTime();
  82. // 按照协议组织 post 请求包体
  83. JObject data = new JObject();
  84. JObject tel = new JObject();
  85. tel.Add("nationcode", nationCode);
  86. tel.Add("mobile", phoneNumber);
  87. data.Add("tel", tel);
  88. data.Add("msg", msg);
  89. data.Add("type", type);
  90. data.Add("sig", util.StrToHash(String.Format(
  91. "appkey={0}&random={1}&time={2}&mobile={3}",
  92. appkey, random, curTime, phoneNumber)));
  93. data.Add("time", curTime);
  94. data.Add("extend", extend);
  95. data.Add("ext", ext);
  96. string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random;
  97. HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
  98. byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
  99. request.ContentLength = requestData.Length;
  100. Stream requestStream = request.GetRequestStream();
  101. requestStream.Write(requestData, 0, requestData.Length);
  102. requestStream.Close();
  103. // 接收返回包
  104. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  105. Stream responseStream = response.GetResponseStream();
  106. StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
  107. string responseStr = streamReader.ReadToEnd();
  108. streamReader.Close();
  109. responseStream.Close();
  110. SmsSingleSenderResult result;
  111. if (HttpStatusCode.OK == response.StatusCode)
  112. {
  113. result = util.ResponseStrToSingleSenderResult(responseStr);
  114. }
  115. else
  116. {
  117. result = new SmsSingleSenderResult();
  118. result.result = -1;
  119. result.errmsg = "http error " + response.StatusCode + " " + responseStr;
  120. }
  121. return result;
  122. }
  123. /**
  124. * 指定模板单发
  125. * @param nationCode 国家码,如 86 为中国
  126. * @param phoneNumber 不带国家码的手机号
  127. * @param templId 模板 id
  128. * @param templParams 模板参数列表,如模板 {1}...{2}...{3},那么需要带三个参数
  129. * @param extend 扩展码,可填空
  130. * @param ext 服务端原样返回的参数,可填空
  131. * @return SmsSingleSenderResult
  132. */
  133. public SmsSingleSenderResult SendWithParam(
  134. string nationCode,
  135. string phoneNumber,
  136. string templId,
  137. List<string> templParams,
  138. string sign,
  139. string extend,
  140. string ext)
  141. {
  142. /*
  143. 请求包体
  144. {
  145. "tel": {
  146. "nationcode": "86",
  147. "mobile": "13788888888"
  148. },
  149. "sign": "云大师",
  150. "tpl_id": 19,
  151. "params": [
  152. "验证码",
  153. "1234",
  154. "4"
  155. ],
  156. "sig": "fdba654e05bc0d15796713a1a1a2318c",
  157. "time": 1479888540,
  158. "extend": "",
  159. "ext": ""
  160. }
  161. 应答包体
  162. {
  163. "result": 0,
  164. "errmsg": "OK",
  165. "ext": "",
  166. "sid": "xxxxxxx",
  167. "fee": 1
  168. }
  169. */
  170. if (null == sign)
  171. {
  172. sign = "";
  173. }
  174. if (null == extend)
  175. {
  176. extend = "";
  177. }
  178. if (null == ext)
  179. {
  180. ext = "";
  181. }
  182. long random = util.GetRandom();
  183. long curTime = util.GetCurTime();
  184. // 按照协议组织 post 请求包体
  185. JObject data = new JObject();
  186. JObject tel = new JObject();
  187. tel.Add("nationcode", nationCode);
  188. tel.Add("mobile", phoneNumber);
  189. data.Add("tel", tel);
  190. data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumber));
  191. data.Add("tpl_id", templId);
  192. data.Add("params", util.SmsParamsToJSONArray(templParams));
  193. data.Add("sign", sign);
  194. data.Add("time", curTime);
  195. data.Add("extend", extend);
  196. data.Add("ext", ext);
  197. string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random;
  198. HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
  199. byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
  200. request.ContentLength = requestData.Length;
  201. Stream requestStream = request.GetRequestStream();
  202. requestStream.Write(requestData, 0, requestData.Length);
  203. requestStream.Close();
  204. // 接收返回包
  205. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  206. Stream responseStream = response.GetResponseStream();
  207. StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
  208. string responseStr = streamReader.ReadToEnd();
  209. streamReader.Close();
  210. responseStream.Close();
  211. SmsSingleSenderResult result;
  212. if (HttpStatusCode.OK == response.StatusCode)
  213. {
  214. result = util.ResponseStrToSingleSenderResult(responseStr);
  215. }
  216. else
  217. {
  218. result = new SmsSingleSenderResult();
  219. result.result = -1;
  220. result.errmsg = "http error " + response.StatusCode + " " + responseStr;
  221. }
  222. return result;
  223. }
  224. }
  225. class SmsSingleSenderResult
  226. {
  227. /*
  228. {
  229. "result": 0,
  230. "errmsg": "OK",
  231. "ext": "",
  232. "sid": "xxxxxxx",
  233. "fee": 1
  234. }
  235. */
  236. public int result { set; get; }
  237. public string errmsg { set; get; }
  238. public string ext { set; get; }
  239. public string sid { set; get; }
  240. public int fee { set; get; }
  241. public override string ToString()
  242. {
  243. return string.Format(
  244. "SmsSingleSenderResult\nresult {0}\nerrMsg {1}\next {2}\nsid {3}\nfee {4}",
  245. result, errmsg, ext, sid, fee);
  246. }
  247. }
  248. class SmsMultiSender
  249. {
  250. string sdkappid;
  251. string appkey;
  252. string url = "https://sms.banling.com/intf/sendmultisms";
  253. SmsSenderUtil util = new SmsSenderUtil();
  254. public SmsMultiSender(string sdkappid, string appkey)
  255. {
  256. this.sdkappid = sdkappid;
  257. this.appkey = appkey;
  258. }
  259. /**
  260. * 普通群发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名
  261. * 【注意】海外短信无群发功能
  262. * @param type 短信类型,0 为普通短信,1 营销短信
  263. * @param nationCode 国家码,如 86 为中国
  264. * @param phoneNumbers 不带国家码的手机号列表
  265. * @param msg 信息内容,必须与申请的模板格式一致,否则将返回错误
  266. * @param extend 扩展码,可填空
  267. * @param ext 服务端原样返回的参数,可填空
  268. * @return SmsMultiSenderResult
  269. */
  270. public SmsMultiSenderResult Send(
  271. int type,
  272. string nationCode,
  273. List<string> phoneNumbers,
  274. string msg,
  275. string extend,
  276. string ext)
  277. {
  278. /*
  279. 请求包体
  280. {
  281. "tel": [
  282. {
  283. "nationcode": "86",
  284. "mobile": "13788888888"
  285. },
  286. {
  287. "nationcode": "86",
  288. "mobile": "13788888889"
  289. }
  290. ],
  291. "type": 0,
  292. "msg": "你的验证码是1234",
  293. "sig": "fdba654e05bc0d15796713a1a1a2318c",
  294. "time": 1479888540,
  295. "extend": "",
  296. "ext": ""
  297. }
  298. 应答包体
  299. {
  300. "result": 0,
  301. "errmsg": "OK",
  302. "ext": "",
  303. "detail": [
  304. {
  305. "result": 0,
  306. "errmsg": "OK",
  307. "mobile": "13788888888",
  308. "nationcode": "86",
  309. "sid": "xxxxxxx",
  310. "fee": 1
  311. },
  312. {
  313. "result": 0,
  314. "errmsg": "OK",
  315. "mobile": "13788888889",
  316. "nationcode": "86",
  317. "sid": "xxxxxxx",
  318. "fee": 1
  319. }
  320. ]
  321. }
  322. */
  323. if (0 != type && 1 != type)
  324. {
  325. throw new Exception("type " + type + " error");
  326. }
  327. if (null == extend)
  328. {
  329. extend = "";
  330. }
  331. if (null == ext)
  332. {
  333. ext = "";
  334. }
  335. long random = util.GetRandom();
  336. long curTime = util.GetCurTime();
  337. // 按照协议组织 post 请求包体
  338. JObject data = new JObject();
  339. data.Add("tel", util.PhoneNumbersToJSONArray(nationCode, phoneNumbers));
  340. data.Add("type", type);
  341. data.Add("msg", msg);
  342. data.Add("sig", util.CalculateSig(appkey, random, curTime, phoneNumbers));
  343. data.Add("time", curTime);
  344. data.Add("extend", extend);
  345. data.Add("ext", ext);
  346. string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random;
  347. HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
  348. byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
  349. request.ContentLength = requestData.Length;
  350. Stream requestStream = request.GetRequestStream();
  351. requestStream.Write(requestData, 0, requestData.Length);
  352. requestStream.Close();
  353. // 接收返回包
  354. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  355. Stream responseStream = response.GetResponseStream();
  356. StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
  357. string responseStr = streamReader.ReadToEnd();
  358. streamReader.Close();
  359. responseStream.Close();
  360. SmsMultiSenderResult result;
  361. if (HttpStatusCode.OK == response.StatusCode)
  362. {
  363. result = util.ResponseStrToMultiSenderResult(responseStr);
  364. }
  365. else
  366. {
  367. result = new SmsMultiSenderResult();
  368. result.result = -1;
  369. result.errmsg = "http error " + response.StatusCode + " " + responseStr;
  370. }
  371. return result;
  372. }
  373. /**
  374. * 指定模板群发
  375. * 【注意】海外短信无群发功能
  376. * @param nationCode 国家码,如 86 为中国
  377. * @param phoneNumbers 不带国家码的手机号列表
  378. * @param templId 模板 id
  379. * @param params 模板参数列表
  380. * @param sign 签名,如果填空,系统会使用默认签名
  381. * @param extend 扩展码,可以填空
  382. * @param ext 服务端原样返回的参数,可以填空
  383. * @return SmsMultiSenderResult
  384. */
  385. public SmsMultiSenderResult SendWithParam(
  386. String nationCode,
  387. List<string> phoneNumbers,
  388. string templId,
  389. List<string> templParams,
  390. string sign,
  391. string extend,
  392. string ext)
  393. {
  394. /*
  395. 请求包体
  396. {
  397. "tel": [
  398. {
  399. "nationcode": "86",
  400. "mobile": "13788888888"
  401. },
  402. {
  403. "nationcode": "86",
  404. "mobile": "13788888889"
  405. }
  406. ],
  407. "type": 0,
  408. "msg": "你的验证码是1234",
  409. "sig": "fdba654e05bc0d15796713a1a1a2318c",
  410. "time": 1479888540,
  411. "extend": "",
  412. "ext": ""
  413. }
  414. 应答包体
  415. {
  416. "result": 0,
  417. "errmsg": "OK",
  418. "ext": "",
  419. "detail": [
  420. {
  421. "result": 0,
  422. "errmsg": "OK",
  423. "mobile": "13788888888",
  424. "nationcode": "86",
  425. "sid": "xxxxxxx",
  426. "fee": 1
  427. },
  428. {
  429. "result": 0,
  430. "errmsg": "OK",
  431. "mobile": "13788888889",
  432. "nationcode": "86",
  433. "sid": "xxxxxxx",
  434. "fee": 1
  435. }
  436. ]
  437. }
  438. */
  439. if (null == sign)
  440. {
  441. sign = "";
  442. }
  443. if (null == extend)
  444. {
  445. extend = "";
  446. }
  447. if (null == ext)
  448. {
  449. ext = "";
  450. }
  451. long random = util.GetRandom();
  452. long curTime = util.GetCurTime();
  453. // 按照协议组织 post 请求包体
  454. JObject data = new JObject();
  455. data.Add("tel", util.PhoneNumbersToJSONArray(nationCode, phoneNumbers));
  456. data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumbers));
  457. data.Add("tpl_id", templId);
  458. data.Add("params", util.SmsParamsToJSONArray(templParams));
  459. data.Add("sign", sign);
  460. data.Add("time", curTime);
  461. data.Add("extend", extend);
  462. data.Add("ext", ext);
  463. string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random;
  464. HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
  465. byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
  466. request.ContentLength = requestData.Length;
  467. Stream requestStream = request.GetRequestStream();
  468. requestStream.Write(requestData, 0, requestData.Length);
  469. requestStream.Close();
  470. // 接收返回包
  471. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  472. Stream responseStream = response.GetResponseStream();
  473. StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
  474. string responseStr = streamReader.ReadToEnd();
  475. streamReader.Close();
  476. responseStream.Close();
  477. SmsMultiSenderResult result;
  478. if (HttpStatusCode.OK == response.StatusCode)
  479. {
  480. result = util.ResponseStrToMultiSenderResult(responseStr);
  481. }
  482. else
  483. {
  484. result = new SmsMultiSenderResult();
  485. result.result = -1;
  486. result.errmsg = "http error " + response.StatusCode + " " + responseStr;
  487. }
  488. return result;
  489. }
  490. }
  491. class SmsMultiSenderResult
  492. {
  493. /*
  494. {
  495. "result": 0,
  496. "errmsg": "OK",
  497. "ext": "",
  498. "detail": [
  499. {
  500. "result": 0,
  501. "errmsg": "OK",
  502. "mobile": "13788888888",
  503. "nationcode": "86",
  504. "sid": "xxxxxxx",
  505. "fee": 1
  506. },
  507. {
  508. "result": 0,
  509. "errmsg": "OK",
  510. "mobile": "13788888889",
  511. "nationcode": "86",
  512. "sid": "xxxxxxx",
  513. "fee": 1
  514. }
  515. ]
  516. }
  517. */
  518. public class Detail
  519. {
  520. public int result { get; set; }
  521. public string errmsg { get; set; }
  522. public string mobile { get; set; }
  523. public string nationcode { get; set; }
  524. public string sid { get; set; }
  525. public int fee { get; set; }
  526. public override string ToString()
  527. {
  528. return string.Format(
  529. "\tDetail result {0} errmsg {1} mobile {2} nationcode {3} sid {4} fee {5}",
  530. result, errmsg, mobile, nationcode, sid, fee);
  531. }
  532. }
  533. public int result;
  534. public string errmsg = "";
  535. public string ext = "";
  536. public IList<Detail> detail;
  537. public override string ToString()
  538. {
  539. if (null != detail)
  540. {
  541. return String.Format(
  542. "SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\ndetail:\n{3}",
  543. result, errmsg, ext, String.Join("\n", detail));
  544. }
  545. else
  546. {
  547. return String.Format(
  548. "SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\n",
  549. result, errmsg, ext);
  550. }
  551. }
  552. }
  553. class SmsSenderUtil
  554. {
  555. Random random = new Random();
  556. public HttpWebRequest GetPostHttpConn(string url)
  557. {
  558. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  559. request.Method = "POST";
  560. request.ContentType = "application/x-www-form-urlencoded";
  561. return request;
  562. }
  563. public long GetRandom()
  564. {
  565. return random.Next(999999)%900000 + 100000;
  566. }
  567. public long GetCurTime()
  568. {
  569. Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
  570. return unixTimestamp;
  571. }
  572. // 将二进制的数值转换为 16 进制字符串,如 "abc" => "616263"
  573. private static string ByteArrayToHex(byte[] byteArray)
  574. {
  575. string returnStr = "";
  576. if (byteArray != null)
  577. {
  578. for (int i = 0; i < byteArray.Length; i++)
  579. {
  580. returnStr += byteArray[i].ToString("x2");
  581. }
  582. }
  583. return returnStr;
  584. }
  585. public string StrToHash(string str)
  586. {
  587. SHA256 sha256 = SHA256Managed.Create();
  588. byte[] resultByteArray = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
  589. return ByteArrayToHex(resultByteArray);
  590. }
  591. // 将单发回包解析成结果对象
  592. public SmsSingleSenderResult ResponseStrToSingleSenderResult(string str)
  593. {
  594. SmsSingleSenderResult result = JsonConvert.DeserializeObject<SmsSingleSenderResult>(str);
  595. return result;
  596. }
  597. // 将群发回包解析成结果对象
  598. public SmsMultiSenderResult ResponseStrToMultiSenderResult(string str)
  599. {
  600. SmsMultiSenderResult result = JsonConvert.DeserializeObject<SmsMultiSenderResult>(str);
  601. return result;
  602. }
  603. public JArray SmsParamsToJSONArray(List<string> templParams)
  604. {
  605. JArray smsParams = new JArray();
  606. foreach (string templParamsElement in templParams)
  607. {
  608. smsParams.Add(templParamsElement);
  609. }
  610. return smsParams;
  611. }
  612. public JArray PhoneNumbersToJSONArray(string nationCode, List<string> phoneNumbers)
  613. {
  614. JArray tel = new JArray();
  615. int i = 0;
  616. do
  617. {
  618. JObject telElement = new JObject();
  619. telElement.Add("nationcode", nationCode);
  620. telElement.Add("mobile", phoneNumbers.ElementAt(i));
  621. tel.Add(telElement);
  622. } while (++i < phoneNumbers.Count);
  623. return tel;
  624. }
  625. public string CalculateSigForTempl(
  626. string appkey,
  627. long random,
  628. long curTime,
  629. List<string> phoneNumbers)
  630. {
  631. string phoneNumbersString = phoneNumbers.ElementAt(0);
  632. for (int i = 1; i < phoneNumbers.Count; i++)
  633. {
  634. phoneNumbersString += "," + phoneNumbers.ElementAt(i);
  635. }
  636. return StrToHash(String.Format(
  637. "appkey={0}&random={1}&time={2}&mobile={3}",
  638. appkey, random, curTime, phoneNumbersString));
  639. }
  640. public string CalculateSigForTempl(
  641. string appkey,
  642. long random,
  643. long curTime,
  644. string phoneNumber)
  645. {
  646. List<string> phoneNumbers = new List<string>();
  647. phoneNumbers.Add(phoneNumber);
  648. return CalculateSigForTempl(appkey, random, curTime, phoneNumbers);
  649. }
  650. public string CalculateSig(
  651. string appkey,
  652. long random,
  653. long curTime,
  654. List<string> phoneNumbers)
  655. {
  656. string phoneNumbersString = phoneNumbers.ElementAt(0);
  657. for (int i = 1; i < phoneNumbers.Count; i++)
  658. {
  659. phoneNumbersString += "," + phoneNumbers.ElementAt(i);
  660. }
  661. return StrToHash(String.Format(
  662. "appkey={0}&random={1}&time={2}&mobile={3}",
  663. appkey, random, curTime, phoneNumbersString));
  664. }
  665. }
  666. }
  667. }