.NET код для смс - PullRequest
       10

.NET код для смс

7 голосов
/ 09 февраля 2009

Привет всем.

Я работаю над кодом для отправки / получения SMS-сообщений через Zeep Mobile (http://zeepmobile.com/developers/).

Я посмотрел на их группы Google и даже связался с их поддержкой, но они не очень хорошо общались, и сейчас я действительно слепой.

Я должен интегрироваться с ними (работа требовала этого), и я не уверен, почему мой код не работает. Поэтому мне интересно, есть ли у кого-нибудь какой-нибудь код на C # .Net, которым он не против поделиться, чтобы я мог интегрировать его в свое приложение.

Конечно, все зависит от того, имеете ли вы опыт работы с Zeep или нет. Если вы хотите, чтобы я опубликовал свой код, я тоже могу это сделать. Дайте мне знать.

Спасибо, и я очень ценю помощь.

**

РЕДАКТИРОВАТЬ: Я ДОБАВИЛ КОД ИСТОЧНИКА ЗДЕСЬ В СЛУЧАЕ, В КОТОРОМ ЭТО МОЖЕТ ПОМОЧЬ!

**

Пожалуйста, прости небрежный код. Это просто то, что я бросил вместе, чтобы проверить Zeep, и я надеюсь, что кто-то может сделать это. (Консольное приложение .Net 3.5 на случай, если вы захотите его собрать).

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Web;
using System.Web.Handlers;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;


namespace ConsoleApplication1
{


    class Program
    {
        public static string API_KEY = "MY_API_KEY";
        public static string SECRET_ACCESS_KEY = "MY_SECRET_KEY";
        public static string PATTERN_RFC1123 = "ddd, dd MMM yyyy HH:mm:ss " + "GMT";

        static void Main(string[] args)
        {
            // URL for sending message - 
            //      send_message = "https://api.zeepmobile.com/messaging/2008-07-14/send_message";
            //      blast_message = "https://api.zeepmobile.com/messaging/2008-07-14/blast_message";
            string apiurl = "https://api.zeepmobile.com/messaging/2008-07-14/blast_message";


            // FORMAT must be Sun, 06 Nov 1994 08:49:37 GMT
            string http_date = DateTime.UtcNow.ToString("r");
            // Text to send
            string body = HttpUtility.UrlEncode("Test message.", System.Text.Encoding.UTF8);
            // NOTE: Use 'user_id=22&body=' instead of just 'body=' when sending a message to a user.
            // 22 is a user I have previously registered with ZEEP and is used for testing purposes.
            string parameters = "body=" + body; 
            // String that will be converted into a signature.
            string canonicalString = API_KEY + http_date + parameters;


            //------------START HASH COMPUTATION---------------------
            // Compute the Base64 HMACSHA1 value
            HMACSHA1 hmacsha1 = new HMACSHA1(SECRET_ACCESS_KEY.ToByteArray());

            // Compute the hash of the input file.
            byte[] hashValue = hmacsha1.ComputeHash(canonicalString.ToByteArray());

            String b64Mac = hashValue.ToBase64String();
            String authentication = String.Format("Zeep {0}:{1}", API_KEY, b64Mac);
            //-----------END HASH COMPUTATION------------------------


            // We are using TCPClient instead of an HTTPWebRequest because we need to manually
            // set the "Headers" such as Date, Authorization etc which cannot easily be done with HTTPWebRequest.
            Uri reqUrl = new Uri(apiurl);
            TcpClient client = new TcpClient(reqUrl.Host, reqUrl.Port);
            NetworkStream netStream = client.GetStream();
            // SSLStream is used for secure communication. ZEEP requires the use of SSL to send and SMS.
            System.Net.Security.SslStream sslStream = new System.Net.Security.SslStream(
                netStream, 
                false, 
                new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate));
            sslStream.AuthenticateAsClient(reqUrl.Host);


            // POST content we are going to transmit over the SSL channel. 
            // See. http://zeepmobile.com/developers/documentation/messaging/2008-07-14/rest_api#send_message
            System.IO.StreamWriter s = new System.IO.StreamWriter(sslStream);
            s.WriteLine(String.Format("POST {0} HTTP/1.1", "/api/blast"));
            s.WriteLine(String.Format("Host: {0}", "api.zeepmobile.com"));
            s.WriteLine(String.Format("Authorization: Zeep {0}:{1}", API_KEY, b64Mac));
            s.WriteLine(String.Format("Date: {0}", http_date));
            s.WriteLine(String.Format("Content-Type: {0}", "application/x-www-form-urlencoded"));
            s.WriteLine(String.Format("Content-Length: {0}", parameters.Length));
            s.WriteLine(String.Format("{0}", parameters));
            s.Flush();


            System.IO.StreamReader r = new StreamReader(sslStream);
            string resp = r.ReadToEnd();
            Console.WriteLine(resp);
            r.Close();

        }

        // The following method is invoked by the RemoteCertificateValidationDelegate.
        // We want to make sure the SSL has no Policy errors and is safe.
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers.
            return false;
        }

    }

    public static class Extensions
    {
        public static byte[] ToByteArray(this string input)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetBytes(input);
        }

        public static string ToBase64String(this byte[] input)
        {
            return Convert.ToBase64String(input);
        }
    }
}

Error

Когда я запускаю этот код, происходит ошибка, показанная на следующем рисунке.

alt text

Ответы [ 2 ]

5 голосов
/ 09 февраля 2009

РЕШЕНИЕ:

OK. Я работал над этим всю прошлую ночь, и я добился определенного прогресса. Я использовал Fiddler для создания сообщения POST, чтобы увидеть любые расхождения между тем, что у меня было выше, и тем, что ожидал сервер.

Я получил его, отправив сообщение и вернув ответ HTTP 200 OK. Опять же, этот код не готов к работе, его просто нужно протестировать и посмотреть, смогу ли я заставить работать Zeep. Спасибо всем, кто откликнулся, и если вы ищете код ZEEP, я надеюсь, что это поможет вам.


using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Web;
using System.Web.Handlers;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;


namespace ConsoleApplication1
{
    class Program
    {
        public static string API_KEY = "YOUR_API_KEY_GOES_HERE! INCLUDE DASHES!";
        public static string SECRET_ACCESS_KEY = "YOUR_SECRET_KEY_GOES_HERE!";

        static void Main(string[] args)
        {
            Console.WriteLine("BLAST - \r\n\r\n");
            BlastTcpPost();

            Console.WriteLine("SEND - \r\n\r\n");
            SendTcpPost();
        }

        /// <summary>
        /// Send a BLAST to all users in your ZEEP account.
        /// </summary>
        public static void BlastTcpPost()
        {
            SendSMS(
                "https://api.zeepmobile.com/messaging/2008-07-14/blast_message",    // URL for Send_Message 
                "You are on blast",                                                 // Message to send
                string.Empty                                                        // No UserId to send.
                );
        }

        /// <summary>
        /// Send a single message to a user in your ZEEP account.
        /// </summary>
        public static void SendTcpPost()
        {
            // Note:- 22 I use for the UserId is just a user I have signed up. Yours may be different and you 
            // might want to pass that in as a parameter.

            SendSMS(
                "https://api.zeepmobile.com/messaging/2008-07-14/send_message",     // URL for Send_Message
                "You are a user...good job!",                                       // Message to send
                "22"                                                                // User Id in your system.
                );

        }

        /// <summary>
        /// Uses a TCPClient and SSLStream to perform a POST.
        /// </summary>
        /// <param name="requestUrl">URL that the POST must be directed to.</param>
        /// <param name="body">Message that is to be sent.</param>
        /// <param name="user">UserId in your Zeep System. Only required if your sending a Single Message to a User. 
        /// Otherwise, just send a string.Empty.</param>
        /// <returns>Response from the server. (although it will write the response to console)</returns>
        public static string SendSMS(string requestUrl, string body, string user)
        {
            string parameters = "";
            string requestHeaders = "";
            string responseData = "";

            // FORMAT must be Sun, 06 Nov 1994 08:49:37 GMT
            string http_date = DateTime.UtcNow.ToString("r");

            // Clean the text to send
            body = HttpUtility.UrlEncode(body, System.Text.Encoding.UTF8);

            if (user.Length > 0) parameters += "user_id=" + user + "&";
            if (body.Length > 0) parameters += "body=" + body;


            // String that will be converted into a signature.
            string canonicalString = API_KEY + http_date + parameters;


            //------------START HASH COMPUTATION---------------------
            // Compute the Base64 HMACSHA1 value
            HMACSHA1 hmacsha1 = new HMACSHA1(SECRET_ACCESS_KEY.ToByteArray());

            // Compute the hash of the input file.
            byte[] hashValue = hmacsha1.ComputeHash(canonicalString.ToByteArray());

            String b64Mac = hashValue.ToBase64String();
            String authentication = String.Format("Zeep {0}:{1}", API_KEY, b64Mac);
            //-----------END HASH COMPUTATION------------------------


            string auth = String.Format("Zeep {0}:{1}", API_KEY, b64Mac);


            System.Uri uri = new Uri(requestUrl);
            System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(uri.Host, uri.Port);
            string requestMethod = "POST " + uri.LocalPath + " HTTP/1.1\r\n";

            // Set Headers for the POST message
            requestHeaders += "Host: api.zeepmobile.com\r\n";
            requestHeaders += "Authorization: " + auth + "\r\n";
            requestHeaders += "Date: " + DateTime.UtcNow.ToString("r") + "\r\n";
            requestHeaders += "Content-Type: application/x-www-form-urlencoded\r\n";
            requestHeaders += "Content-Length: " + parameters.ToByteArray().Length + "\r\n";
            requestHeaders += "\r\n";


            // Get the data to be sent as a byte array.
            Byte[] data = System.Text.Encoding.UTF8.GetBytes(requestMethod + requestHeaders + parameters + "\r\n");
            // Send the message to the connected TcpServer.
            NetworkStream stream = client.GetStream();


            // SSL Authentication is used because the Server requires https.
            System.Net.Security.SslStream sslStream = new System.Net.Security.SslStream(
                stream,
                false,
                new System.Net.Security.RemoteCertificateValidationCallback(ValidateServerCertificate));
            sslStream.AuthenticateAsClient(uri.Host);

            // Send the data over the SSL stream.
            sslStream.Write(data, 0, data.Length);
            sslStream.Flush();


            // Receive the TcpServer.response.
            for (int i = 0; i < 100; i++)
            {
                if (stream.DataAvailable)
                {
                    break;
                }
                System.Threading.Thread.Sleep(100);
            }

            Byte[] bytes = new byte[1024];
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            while (stream.DataAvailable)
            {
                int count = sslStream.Read(bytes, 0, 1024);
                if (count == 0)
                {
                    break;
                }
                sb.Append(System.Text.Encoding.UTF8.GetString(bytes, 0, count));
            }

            responseData = sb.ToString();
            Console.WriteLine(responseData);
            // Close everything.
            client.Close();

            return responseData;
        }



        // The following method is invoked by the RemoteCertificateValidationDelegate.
        // We want to make sure the SSL has no Policy errors and is safe.
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            // Somehow the cert always has PolicyErrors so I am returning true regardless.
            return true;
            //if (sslPolicyErrors == SslPolicyErrors.None)
            //    return true;

            //Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            //// Do not allow this client to communicate with unauthenticated servers.
            //return false;
        }
    }

    public static class Extensions
    {
        public static byte[] ToByteArray(this string input)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            return encoding.GetBytes(input);
        }

        public static string ToBase64String(this byte[] input)
        {
            return Convert.ToBase64String(input);
        }
    }
}
2 голосов
/ 09 февраля 2009

Вы уверены, что вам нужно вручную реализовать протокол HTTP в коде, используя TcpClient и SslStream для связи с Zeep? Я бы попытался просто использовать объект HttpWebRequest и позволить .NET Framework обрабатывать биты протокола HTTP для вас. Тем более что сообщение об ошибке, которое вы получаете, похоже, указывает на направление отправляемого вами запроса, так как удаленный сервер не может его понять.

(Не было ли необходимости в дополнительной пустой строке между заголовком HTTP и реальным содержимым? Я никогда не помню, и мне не нужно , если я просто делаю правильную .NET Framework WebRequest ...)

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...