|
v7: Отправка СМС из 1С через SMS-Fly | ☑ | ||
---|---|---|---|---|
0
Anempadest
11.06.15
✎
14:18
|
Решаю задачу по отправке СМС из 1С. Использую API сервиса SMS-Fly (Украина).
Всё уже написал (соединение, отправка запроса XML, разбор ответа), но есть одно препятствие: не могу авторизироваться. От службы поддержки получил пример на PHP: *** Если коротко, то алгоритм действий для разных языков одинаков. 1) Открывается сокет на наш ресурс на 80 порт (стандартный порт http протокола); 2) Формируется XML $data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><request><operation>GETBALANCE</operation></request>"; 3) Формируются заголовки для передаваемых данных. в PHP это выглядит $headers = "POST $path HTTP/1.1\r\n"; $headers .= "Host: $hostname\r\n"; $headers .= 'Authorization: Basic '.base64_encode($user.':'.$pwd)."\r\n"; $headers .= "Content-type: text/xml\r\n"; $headers .= "Content-Length: ".strlen($data)."\r\n\r\n"; 4) данные записываются в открытое соединение. 5) читаются данные из открытого соединения для получения ответа от сервера. 6) полученные данные анализируются приложением, отслеживается результат выполнения команды. *** Я не большой специалист по HTTP протоколу и отправке POST запросов, поэтому с трудом понимаю написанное. Написал так: *** Анализатор=СоздатьОбъект("AddIn.XMLParser"); //соединение Соединение=СоздатьОбъект("Addin.V7HttpReader"); Соединение.КоличествоПопытокАвторизации=3; //заголовок Заголовок= "POST http://sms-fly.com/api/api.php HTTP/1.1 |Host: http://sms-fly.com |Authorization: Basic "+СокрЛП(Рассылка.Логин)+":"+СокрЛП(Рассылка.Пароль)+" |Content-type: text/xml |Content-Length: 1000"; //отправка заголовка Приемник=""; Соединение.ОтправитьДляОбработки(Рассылка.Адрес,Заголовок,2,Приемник,2); *** В переменную приёмник получаю ответ "HTTP/1.1 401 Unauthorized", то есть авторизация не выполнена. Уже не знаю, что делать. Поможете? |
|||
1
EverGreenMouse
11.06.15
✎
14:27
|
|Authorization: Basic "+СокрЛП(Рассылка.Логин)+":"+СокрЛП(Рассылка.Пароль)+"
не тут ли косяк? Может так? |Authorization: Basic "СокрЛП(Рассылка.Логин)+":"+СокрЛП(Рассылка.Пароль)" |
|||
2
Anempadest
11.06.15
✎
14:29
|
(1) Я же создаю текстовую строку с разделителями строк.
|
|||
3
AMKahm
11.06.15
✎
14:47
|
А где конвертация в base64 в вашем коде?
типа Authorization: Basic "+base64_encode(СокрЛП(Рассылка.Логин)+":"+СокрЛП(Рассылка.Пароль)) |
|||
4
Anempadest
11.06.15
✎
14:58
|
(3) Да, ТП написала про конвертацию. А оно обязательно?
Логин - это номер телефона, то есть numeric. А пароль состоит из латинских символов. Мне кажется, перекодировать ничего не нужно. Или я ошибаюсь? |
|||
5
AMKahm
11.06.15
✎
15:01
|
Ошибаетесь. Вот - посмотрите здесь:
http://ostermiller.org/calc/encode.html |
|||
6
AMKahm
11.06.15
✎
15:02
|
login:pass
кодируются в bG9naW46cGFzcw== |
|||
7
Anempadest
11.06.15
✎
15:04
|
(8) Я понял. Спасибо. Сейчас буду делать.
Простое кодирование и декодирование base64 |
|||
8
Anempadest
11.06.15
✎
21:35
|
Хорошие новости.
[code] Анализатор=СоздатьОбъект("AddIn.XMLParser"); //соединение Соединение=СоздатьОбъект("Addin.V7HttpReader"); Соединение.КоличествоПопытокАвторизации=3; //кодирование Проход=СокрЛП(Рассылка.Логин)+":"+СокрЛП(Рассылка.Пароль); Если гКодировать(Проход,"base64")=0 Тогда Возврат(0); КонецЕсли; //создание Файл=КаталогВременныхФайлов()+"sms_send.xml"; Смс_Создать(Анализатор,Файл); //тело Текст=гСодержимоеФайла(Файл); //заголовок Заголовок= "POST http://sms-fly.com/api/api.php HTTP/1.1\r\n |Host: http://sms-fly.com\r\n |Authorization: Basic "+Проход+"\r\n |Content-Type: text/xml\r\n |Content-Length: "+СтрДлина(Текст)+"\r\n\r\n"; //отправка Приемник=КаталогВременныхФайлов()+"sms_send_а.xml"; Соединение.ОтправитьДляОбработки(Рассылка.Адрес,Заголовок+Текст,2,Приемник,1); [/code] Удалось авторизоваться на сайте. Но желаемый результат не достигнут. В файл Приемник сервер возвращает просто Главную страницу сайта, а должен вернуть ответ в формате XML. Есть какие-то идеи? |
|||
9
Garykom
гуру
11.06.15
✎
22:10
|
(8) сменить оператора рассылки смс
ЗЫ это послать по адресу... |
|||
10
Garykom
гуру
11.06.15
✎
22:10
|
(9)+ у нормальных даже готовые примеры для разных 1С выложены..
|
|||
11
Anempadest
12.06.15
✎
03:38
|
(10) Истину говоришь, товарищ!
Но у этой конторы - самая низкая стоимость СМС в Украине: 0,159 грн. |
|||
12
Anempadest
12.06.15
✎
14:03
|
Работающий код:
<code> Соединение=СоздатьОбъект("WinHttp.WinHttpRequest.5.1"); Соединение.Option(2,"utf-8"); Соединение.Open("POST","http://sms-fly.com/api/api.php",0); Соединение.SetRequestHeader("Authorization","Basic "+Ключ); Соединение.SetRequestHeader("Content-Type","text/xml"); Соединение.SetRequestHeader("Content-Length",СтрДлина(Запрос)); Соединение.Send(Запрос); </code> |
|||
13
Anempadest
12.06.15
✎
14:42
|
Внешнюю компоненту V7PLUS для отправки данного запроса использовать не получилось. Сервер не авторизует соединение, то есть метод не работает:
Соединение.УстановитьЗаголовокЗапроса("Authorization","Basic "+Ключ); |
|||
14
oleg_km
12.06.15
✎
16:38
|
(12) Вообще-то метод SetCredentials должен это вроде делать.
|
|||
15
Anempadest
12.06.15
✎
17:10
|
(14) Присмотритесь внимательней к коду. Сервер просит отправить Логин и Пароль в закодированном виде.
'Authorization: Basic '.base64_encode($user.':'.$pwd)."\r\n"; |
|||
16
Serginio1
12.06.15
✎
18:54
|
||||
17
oleg_km
12.06.15
✎
19:53
|
(15) А может теорию почитаешь? В протоколе HTTP есть авторизация Basic, Digest, NTLM, SSL. Как правило, разработчики API уже реализуют эту реализацию на уровне своего API. Ты лучше попробуй
|
|||
18
Anempadest
13.06.15
✎
02:24
|
(17) Только ради вас попробовал. И получил ошибку:
Соединение.SetCredentials(Логин,Пароль); {Обработка.Извещение.Форма.Модуль(272)}: WinHttp.WinHttpRequest: Нельзя вызвать этот метод до вызова метода Send Мне специалист из СП дал чёткие инструкции, что нужно использовать заголовок: 'Authorization: Basic '.base64_encode($user.':'.$pwd)."\r\n"; |
|||
19
Serginio1
13.06.15
✎
10:03
|
(18) Ты бы 16 почитал внимательно
|
|||
20
Serginio1
13.06.15
✎
10:24
|
Там пример на JavaScript вполне читаемый. Дело в том, что при отсутствии авторизации сервер возвращает еще и какую авторизацию он хочет
|
|||
21
Anempadest
13.06.15
✎
14:45
|
(20) Прости, что я тебя не понимаю, но мне кажется, что ты меня троллишь.
Смотри. Эта служба просит у меня послать запрос для отправки СМС. Для авторизации на сервере нужно в заголовке запроса разместить переменную "Authorization" и значение. Обрати внимание, что значение переменной - это не просто строка "Логин:Пароль". Эта строка должна быть ещё закодирована по протоколу Base64. Понял? В заголовке есть переменная и значение. И только так. По-другому работать не будет. Если бы работало, то Служба Поддержки бы этого не скрывала. Не согласен? |
|||
22
Serginio1
13.06.15
✎
15:44
|
Какой смысл мне тебя троллить? Почитай про авторизацию например http://samag.ru/archive/article/1631
Обычно авотризация отдается на откуп Api. Например в Net https://msdn.microsoft.com/ru-ru/library/system.net.networkcredential(v=vs.110).aspx Класс NetworkCredential является базовым классом, который поддерживает учетные данные в схемах аутентификации на основе пароля, таких как "Обычная", "Дайджест", "NTLM" и "Kerberos". Классы, реализующие интерфейс ICredentials, например класс CredentialCache, возвращают объекты NetworkCredential. Ты не заботишься какую авторизацию поддерживает сервер и как данные авторизации нужно записать. |
|||
23
Serginio1
13.06.15
✎
15:57
|
И если вдруг на сервере изменят тип авторизации тебе не нежно будет править код
|
|||
24
ДенисЧ
13.06.15
✎
16:58
|
Кто о чём, а лыс^W Serginio1 о дотнете....
|
|||
25
Serginio1
13.06.15
✎
17:49
|
(24) А что в этом плохого? Так или иначе он использует не родные компоненты. Я же ему не предлагаю v8: v8: Использование сборок .NET в 1С 7.x и 8.x
Просто даю понять как правильно использовать инструменты. Просто в Net куча библиотек на все случаи жизни. Что тебя так коробит? |
|||
26
oleg_km
13.06.15
✎
18:06
|
(25) "Православные 1сники все остальное считают ересью
|
|||
27
vladimirmir2012
13.06.15
✎
18:12
|
(26) Да нет просто 1С прекрасно интегрирована с automation и не сложно написать ВК, использующую .Net.
Отсюда и приверженность к .Net /в частности/. |
|||
28
oleg_km
13.06.15
✎
18:21
|
(27) Вот и непонятно, почему многим упоминание дотнета вызывает ассоциацию чуть ли не с ассемблером
|
|||
29
vladimirmir2012
13.06.15
✎
18:24
|
(28) Так для 1С .Net и есть своего рода ассемблер
|
|||
30
Serginio1
13.06.15
✎
22:26
|
(29) Да нет ассемблер это низкоуровневый код которым пользуются гики. C# уже давно один из самых распространенных инструментов. Да и ВК давно уже писать не надо. Посмотри v8: v8: Использование сборок .NET в 1С 7.x и 8.x
В 8 ке есть подключение событий. А для 7 ки можно использовать только ВК достающий AppDispatch с передачей в нетовские сборки. |
|||
31
Anempadest
14.06.15
✎
03:06
|
(22) Я в (18) написал, что при использовании предлагаемого тобой метода 1С выдаёт ошибку. Говорит, что сначала нужно установить связь, а только после этого использовать SetCredentials(Логин,Пароль). Если ты считаешь себя правым в теории, то докажи свою уверенность на практике и покажи, какой код нужно написать в 1С 7.7, чтобы предлагаемый тобой метод заработал.
Например, после прочтения литературы о HTTP я понял, что 1С 7.7 не способна выполнить нечто наподобие такого: Соединение.Open("POST","http://sms-fly.com/api/api.php",0); У неё есть только одна команда: Соединение.ОтправитьДляОбработки(Адрес,Источник,2,Приемник,2); И я так понимаю, что внутри 1С одновременно открывает, делает запрос POST и закрывает (?). И мне, кстати, очень жаль, что как бы встроенный функционал 1С не способен выполнить такую казалось бы популярную и простую задачу. При этом, в 1С 8 подобная команда уже есть. |
|||
32
Serginio1
14.06.15
✎
09:05
|
Вот пример на JavaScript
TTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0; HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1; // Instantiate a WinHttpRequest object. var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1"); // Specify the target resource. var targURL = "http://msdn.microsoft.com/downloads/samples/"+ "internet/winhttp/auth/authenticate.asp"; WinHttpReq.open("GET", targURL, false); var Done = false; var LastStatus=0; do { // Send a request to the server and wait for a response. WinHttpReq.send(); // Obtain the status code from the response. var Status = WinHttpReq.Status; switch (Status){ // A 200 status indicates that the resource was retrieved. case 200: Done = true; break; // A 401 status indicates that the server // requires authentication. case 401: WScript.Echo("Requires Server UserName and Password."); // Specify the target resource. WinHttpReq.open("GET", targURL, false); // Set credentials for the server. WinHttpReq.SetCredentials("User Name", "Password", HTTPREQUEST_SETCREDENTIALS_FOR_SERVER); // If the same credentials are requested twice, abort // the request. For simplicity, this sample does not // check for a repeated sequence of status codes. if (LastStatus==401) Done = true; break; // A 407 status indicates that the proxy // requires authentication. case 407: WScript.Echo("Requires Proxy UserName and Password."); // Specify the target resource. WinHttpReq.open("GET", targURL, false); // Set credentials for the proxy. WinHttpReq.SetCredentials("User Name", "Password", HTTPREQUEST_SETCREDENTIALS_FOR_PROXY); // If the same credentials are requested twice, abort // the request. For simplicity, this sample does not // check for a repeated sequence of status codes. if (LastStatus==407) Done = true; break; // Any other status is unexpected. default: WScript.Echo("Unexpected Status: "+Status); Done = true; break; } // Keep track of the last status code. LastStatus = Status; } while (!Done); // Display the results of the request. WScript.Echo(WinHttpReq.Status + " " + WinHttpReq.StatusText); WScript.Echo(WinHttpReq.GetAllResponseHeaders()); |
|||
33
Serginio1
14.06.15
✎
09:08
|
Из примера видно, что мы сначала посылаем WinHttpReq.send(); и обрабатываем какой получили ответ.
Если он case 401: WScript.Echo("Requires Server UserName and Password."); // Specify the target resource. WinHttpReq.open("GET", targURL, false); // Set credentials for the server. WinHttpReq.SetCredentials("User Name", "Password", HTTPREQUEST_SETCREDENTIALS_FOR_SERVER); То авторизуемся. |
|||
34
Serginio1
14.06.15
✎
09:31
|
(31) А где это в семерке Соединение.ОтправитьДляОбработки
Если тебе, что то не хватает в семерке используй Net. v8: v8: Использование сборок .NET в 1С 7.x и 8.x Там будет что типа врап=СоздатьОбъект("NetObjectToIDispatch45"); врап.УстЭтоСемерка(); request = Врап.ПолучитьТип("System.Net.WebRequest").Create ("http://sms-fly.com/api/api.php"); // Set the Method property of the request to POST. request.Method = "POST"; request.Credentials = Врап.СоздатьОбъект("System.Net.NetworkCredential",Логин,Пароль); // Get the stream containing content returned by the server. dataStream = response.GetResponseStream (); // Open the stream using a StreamReader for easy access. reader = врап.СоздатьОбъект(System.IO.StreamReader",dataStream); // Read the content. responseFromServer = reader.ReadToEnd (); |
|||
35
Serginio1
14.06.15
✎
09:40
|
Если тебе нужно послать данные то
$data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><request><operation>GETBALANCE</operation></request>"; buffer = Врап.ПолучитьТип("System.Encoding").UTF8.GetBytes(sXml); // Tried ASCII...same result request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; // tried "text/xml"... same result request.ContentLength = buffer.Length; ReqStream = request.GetRequestStream(); ReqStream.Write(buffer, 0, buffer.Length); ReqStream.Close(); |
|||
36
Serginio1
14.06.15
✎
10:02
|
request.ContentType = "text/xml; encoding='utf-8'";
|
|||
37
Serginio1
14.06.15
✎
10:06
|
например этот пример легко переделать https://secure.safeshop.co.za/documentation/code/codingexample_csharp.htm
|
|||
38
Anempadest
14.06.15
✎
23:53
|
(37) В посте (12) то же, только короче. В общем, спасибо. А я потихоньку буду на 8 переходить.
|
|||
39
Serginio1
15.06.15
✎
00:16
|
(38) Восьмерка не все решает Доменная аутентификация WS. Как?
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |