PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/LittleSMS.pm

http://github.com/dapi/littlesms-perl
Perl | 362 lines | 220 code | 131 blank | 11 comment | 21 complexity | 8e3c962eac29aab284244feb6a597ef0 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. =encoding utf-8
  3. =head1 NAME
  4. LittleSMS - Perl модуль для работы с сервисом LittleSMS.ru
  5. =head1 SYNOPSIS
  6. use LittleSMS;
  7. my $l = LittleSMS->new(@ARGV); # login, key, useSSL, test, api_url
  8. print "Мой баланс: ", $l->getBalance(), "\n";
  9. print $l->sendSMS('79033781228','test message') ? "Успешно отправлено!\n" : "Ошибка!\n";
  10. print "На счету осталось: $l->{response}->{balance}\n";
  11. После инициализации обьекта LittleSMS можно использовать как
  12. Singleton:
  13. new LittleSMS(@ARGV); # login, key, useSSL, test, api_url
  14. sms()->getBalance();
  15. sms()->sendSMS(...);
  16. =head1 DESCRIPTION
  17. Функции:
  18. - отправка SMS
  19. - запрос баланса
  20. =head2 Methods:
  21. =over 6
  22. =item LittleSMS->new(login, key, useSSL, test, api_url)
  23. Все параметры, кроме login и key, указывать не обязательно. А api_url
  24. даже не нужно.
  25. =item sms()
  26. Singleton вызов обьекта. Возможно после только после его
  27. инициализации. Например:
  28. new LittleSMS(@ARGV); # login, key, useSSL, test, api_url
  29. sms()->getBalance();
  30. =item $object->getBalance()
  31. Возвращает баланс.
  32. =item $object->sendSMS(телефон, сообщение, [senderID] )
  33. Отправляет сообщение и возвращает true в случае удачи.
  34. $object->sendSMS( номер1, сообщение)
  35. Можно указывать
  36. массив телефонов для массовой рассылки:
  37. $object->sendSMS([ номер1, номер2, номер3 ], сообщение)
  38. А можно задать SenderID - строка (11 символов, латиница, цифры, * ()
  39. [] @ . , - _)
  40. $object->sendSMS( номер1, сообщение, 'zhazhda.ru');
  41. =item $object->checkStatus( messages_id );
  42. Запрос на сервер для проверки статусов сообщения. Параметр - массив
  43. messages_id вовзращенный через response().
  44. =item $object->makeRequest(function, parameters)
  45. - function - Строка с именем функции (balance или send)
  46. - parameters - hashref на параметры запроса. См: https://littlesms.ru/doc
  47. =item $object->setSender( senderID )
  48. Имя отправителя по-умолчанию для всех сообщений. Строка (11 символов,
  49. латиница, цифры, * () [] @ . , - _)
  50. $object->setSender('homesite.ru');
  51. P.S. В случае необходимости для каждого сообщения можно устанавливаеть
  52. собственный SenderID.
  53. =item $object->setBalanceControl( сумма, телефон, [сообщение] )
  54. Устанавливает значение баланса при котором на указанный телефон
  55. отправляется сообщение. Баланс проверяется автоматически каждый раз
  56. после вызова sendSMS.
  57. # Установить контроль с сообщенем по-умолчанию
  58. sms()->setBalanceControl( 100, '77777777777');
  59. # Определить свое сообщение
  60. sms()->setBalanceControl( 100, '77777777777', 'Кранты, пора платить в LittleSMS');
  61. # Отменить контроль.
  62. sms()->setBalanceControl( 0 );
  63. =item $object->response([key])
  64. Возвращает поседний ответ вызова makeRequest(), то есть и после
  65. getBalance и после sendSMS. В случае вызова без ключа возвращает весь HASH
  66. ответа, в случае вызова с ключем возвращает значение ключа.
  67. sms()->sendSMS('НОМЕР','test message') ? "Успешно отправлено!\n" : "Ошибка!\n";
  68. print "На счету осталось:", sms()->response('balance');
  69. ВНИМАНИЕ! При установленном контроле баланса response может возвращать
  70. результат отправки контрольного сообщения.
  71. =back
  72. =head1 AUTHOR
  73. Данил Письменный <danil@orionet.ru> http://dapi.ru/
  74. Взял пример с PHP класса http://github.com/pycmam/littlesms/blob/master/LittleSMS.class.php
  75. от Рустама Миниахметова <pycmam@gmail.com>
  76. =head1 COPYRIGHT
  77. Модуль представляется "как есть", без гарантий.
  78. Copyright 2010. All rights reserved.
  79. This library is free software; you can redistribute it and/or
  80. modify it under the same terms as Perl itself.
  81. =head1 SEE ALSO
  82. https://littlesms.ru/doc
  83. Github repo for this module: http://github.com/dapi/littlesms-perl
  84. =cut
  85. package LittleSMS;
  86. use strict;
  87. use warnings;
  88. #use Data::Dumper;
  89. use WWW::Curl::Easy;
  90. use URI::Escape;
  91. use Digest::MD5 qw(md5_hex);
  92. use Digest::SHA1 qw(sha1_hex);
  93. use JSON::XS;
  94. use Exporter;
  95. use base qw(Exporter);
  96. use vars qw(
  97. @EXPORT
  98. @SORTED_PARAMS
  99. $INSTANCE
  100. $VERSION
  101. $DEBUG
  102. );
  103. $VERSION = '0.3';
  104. $DEBUG = 0;
  105. @EXPORT = qw(sms);
  106. @SORTED_PARAMS = qw(user messages_id recipients message sender test sign);
  107. sub new {
  108. my ($class, $user, $key, $useSSL, $test, $url) = @_;
  109. my $self = bless {
  110. user => $user,
  111. key => $key,
  112. useSSL => defined $useSSL ? $useSSL : 1,
  113. test => $test || 0,
  114. url => $url || 'littlesms.ru/api/'
  115. }, $class;
  116. print STDERR "LittleSMS new: $user $key $useSSL $test $url\n" if $DEBUG;
  117. return $INSTANCE=$self;
  118. }
  119. sub sms {
  120. $INSTANCE
  121. }
  122. sub setSender {
  123. my ( $self, $sender) = @_;
  124. $self->{sender} = $sender;
  125. }
  126. sub sendSMS {
  127. my ($self, $recipients, $message, $sender, $dont_check ) = @_;
  128. my $h = {
  129. recipients => ref($recipients)=~/ARRAY/ ? join(',',@$recipients) : $recipients,
  130. message => $message,
  131. test => $self->{test}
  132. };
  133. $h->{sender} = $sender || $self->{sender};
  134. # 11 символов, латиница, цифры, * () [] @ . , - _)
  135. $h->{sender} =~ s/[^a-z0-9\(\)\[\]@.,\-_]+//ig;
  136. $h->{sender} = substr( $h->{sender}, 0, 11 );
  137. delete $h->{sender} unless $h->{sender}; # Удаляем если оказался
  138. # пустой
  139. print STDERR "SendSMS to: $h->{recipients}, $message\n" if $DEBUG;
  140. #print STDERR Data::Dumper->Dump($h) if $DEBUG;
  141. my $response = $self->makeRequest( 'send', $h );
  142. $self->checkBalance($response) unless $dont_check;
  143. print STDERR "SendSMS status: $response->{status}, balance $response->{balance}\n" if $DEBUG;
  144. return $response->{status} eq 'success';
  145. }
  146. sub setBalanceControl {
  147. my ( $self, $balance, $number, $message ) = @_;
  148. my $bc = $self->{balance_control};
  149. if ($balance>0) {
  150. $bc->{balance} = $balance;
  151. $bc->{number} = $number if $number;
  152. $bc->{message} = $message || $bc->{message} || "Баланс на LittleSMS опустился до $balance руб.";
  153. die "Не указан номер для контроля баланса" unless $bc->{number};
  154. } else {
  155. $bc->{balance} = 0; # Отключить контроль баланса;
  156. }
  157. $self->{balance_control}=$bc;
  158. }
  159. sub getBalance {
  160. my ( $self ) = @_;
  161. my $response = $self->makeRequest('balance');
  162. return $response->{status} eq 'success' ? $response->{balance} : undef;
  163. }
  164. sub makeRequest {
  165. my ( $self, $function, $params ) = @_;
  166. $params = {} unless $params;
  167. $params->{user} = $self->{user};
  168. $params->{sign} = $self->generateSign($params);
  169. my $url = ($self->{useSSL} ? 'https://' : 'http://') . $self->{url} . $function;
  170. my $curl = new WWW::Curl::Easy;
  171. $curl->setopt( CURLOPT_URL, $url );
  172. $curl->setopt( CURLOPT_HEADER, 1 );
  173. if ($self->{useSSL}) {
  174. $curl->setopt( CURLOPT_SSL_VERIFYPEER, 0 );
  175. $curl->setopt( CURLOPT_SSL_VERIFYHOST, 0 );
  176. }
  177. $curl->setopt( CURLOPT_POSTFIELDS, build_query( $params ) );
  178. $curl->setopt( CURLOPT_POST, 1 ); # $curl->setopt( CURLOPT_HTTPGET, 0 );
  179. my $content = "";
  180. open( my $fileb, ">", \$content );
  181. $curl->setopt( CURLOPT_WRITEDATA, $fileb );
  182. if ( $curl->perform == 0 ) {
  183. $content=~s/(\n|.)+\n//i; # Удаляем заголовок
  184. return $self->{response} = decode_json( $content );
  185. } else {
  186. croak("An error happened: Host $url");
  187. }
  188. }
  189. sub response {
  190. my ($self, $key) = @_;
  191. $key ? $self->{response}->{$key} : $self->{response};
  192. }
  193. sub checkStatus {
  194. my ($self, $messages_id) = @_;
  195. my $ids = ref($messages_id)=~/ARRAY/ ? join(',',@$messages_id) : $messages_id;
  196. $self->makeRequest('status',{messages_id=>$ids});
  197. }
  198. #
  199. # Private methods:
  200. #
  201. sub checkBalance {
  202. my ( $self, $response ) = @_;
  203. return undef unless $response && $self->balance_control('balance') && !$self->balance_control()->{status};
  204. if ($response->{balance}==$self->balance_control('balance')) {
  205. $self->balance_control()->{status} = 1;
  206. $self->sendSMS( $self->balance_control('number'), $self->balance_control('message'), '', 1 );
  207. $self->balance_control()->{sent} += 1;
  208. }
  209. }
  210. sub balance_control {
  211. my ($self, $key ) = @_;
  212. $key ? $self->{balance_control}->{$key} : $self->{balance_control};
  213. }
  214. sub generateSign {
  215. my ( $self, $h ) = @_;
  216. my @params;
  217. foreach (@SORTED_PARAMS) {
  218. push @params, $h->{$_} if exists $h->{$_};
  219. }
  220. md5_hex( sha1_hex (join( '', @params ) . $self->{key}) );
  221. }
  222. sub build_query {
  223. my ( $h ) = @_;
  224. my @params;
  225. foreach (@SORTED_PARAMS) {
  226. push @params, "$_=".uri_escape($h->{$_})
  227. if exists $h->{$_}
  228. }
  229. join('&', @params);
  230. }
  231. 1;