Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Datenübergabe JSON-Array an FreeSMS-Anbieter (https://www.delphipraxis.net/179794-datenuebergabe-json-array-freesms-anbieter.html)

hesch21 2. Apr 2014 14:29

Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Liebe Delphianer
ich habe da einen interessanten FreeSMS-Anbieter gefunden. Unsere Software arbeitet zwar üblicherweise mit Indy und einem Gateway für den Versand von SMS, aber unsere ganz kleinen Kunden haben kein eigenes Gateway und denen haben wir bisher ein Interface zu Skype angeboten. Nun hat aber Skype sein API ausser Betrieb genommen. Nach langer Suche sind wir jetzt auf http://www.freesmsgateway.com/api gestossen. Die bieten 100 SMS pro Monat gratis an und das reicht für unsere Bedürfnisse allemal.
Nun aber endlich zum Problem. Der Link oben verweist auf das API des Anbieters. Ich bekomme da auch schön eine Verbindung hin, habe es schon geschafft, den Text zu 'URLencoden', nur wie ich die Telefonnummer in ein JSON-Array bekommen und dieses noch als Parameter weiter geben soll, ist mir einfach zu hoch. Dass es so wie unten nicht klappen kann, ist klar, aber wie?
Code:
procedure TForm2.PostExample;
var param : TStringList;
    valid : boolean;
    url  : string;
    text : string;
    EText : string;
    jsobj : TJsonObject;
    jsa  : TJsonArray;
begin
  param := TStringList.create;
  param.Clear;
  param.Add('access_token = 43efcb76....................e3fdb6');
  EText := TIdURI.URLEncode('http://' + Edit1.Text);
  Delete(EText, 1, 7);
  param.Add('message = ' + EText);
  param.Add('send_to=post_contacts');
  jsObj := TJsonObject.Create();
  jsa  := TJsonArray.Create();
  jsa.AddElement(Edit2.Text);
  param.Add('post_contacts=' + jsobj);
  valid := true;
  url  := 'http://www.FreeSMSGateway.com/api_send';
  try
     text := http.Post(url,param);
  except
     on E : Exception do
            valid := false;
  end;
  if valid then
     showmessage(text)
  else
     showmessage( '' );
  end;

sh17 2. Apr 2014 14:34

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Sendet der Anbieter auch an Deutschland?

Sir Rufo 2. Apr 2014 14:45

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Schau doch einfach mal auf JSON.org vorbei.

Das ist ein JSON-Array mit Telefonnummern (als string)
Code:
["12345678","23456789"]

hesch21 2. Apr 2014 14:46

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Deutschland habe ich nicht versucht, aber da es in die Schweiz geht vermutlich ja.

Sir Rufo 2. Apr 2014 18:06

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Du hast da ein paar Fehler in deinem Code
  • Erzeugte Instanzen werden nicht freigegeben
  • Dem
    Delphi-Quellcode:
    TJSONObject
    wird nichts übergeben, aber das benutzt du als Parameter
  • Die reine Instanz von
    Delphi-Quellcode:
    TJSONObject
    kann nicht automatisch in einen String konvertiert werden - da meckert schon der Compiler (freundliche Menschen geben das im Post gleich an, dass der Quellcode noch nicht mal kompiliert)
  • Das abenteuerliche
    Delphi-Quellcode:
    TIdURI.UrlEncode
    wendest du nur auf die Message an, warum dann nicht auch auf das
    Delphi-Quellcode:
    TJSONArray
    mit den Nummern?
  • Das
    Delphi-Quellcode:
    UrlEncode
    kannst du dir komplett sparen, denn das macht
    Delphi-Quellcode:
    TIdHttp.Post
    von selber, somit würde also doppelt UrlEncoded
  • Eine
    Delphi-Quellcode:
    TStringList
    hat schon eine passende Key-Value-Logik eingebaut, einfach nur benutzen
  • So wie du die Exceptions behandelst ist ja grausam ... Exceptions werden entweder gefangen um da noch etwas zu retten (Wiederholung, Anpassung, etc.) oder umgewandelt (z.B. von
    Delphi-Quellcode:
    EIdException
    zu
    Delphi-Quellcode:
    ESmsGatewayException
    ) aber auf keinen Fall so unterdrückt. Wenn du da jetzt einen Zugriffsfehler hast, dann wirst du das niemals mitbekommen. Sieht alles schön bunt aus "Ist bestimmt das SMS-Gateway dran schuld"
Delphi-Quellcode:
type
  ESmsGatewayException = class(Exception);
  ESmsGatewayApiException = class( ESmsGatewayException );

procedure TForm2.PostExample;
var param : TStringList;
    url : string;
    text : string;
    jsa : TJsonArray;
begin
  param := nil;
  jsa := nil;
  try

    param := TStringList.create;
 
    param.Values['access_token'] := '43efcb76....................e3fdb6';
    param.Values['message'] := Edit1.Text;
    param.Values['send_to'] := 'post_contacts';

    jsa := TJsonArray.Create();

    jsa.AddElement(Edit2.Text);

    param.Values['post_contacts'] := jsa.ToString;
    url := 'http://www.FreeSMSGateway.com/api_send';
    try
       text := http.Post( url, param );
    except
       // Transport-Layer Fehler
       on E : EIdException do
         raise ESmsGatewayException.Create(E.Message);
    end;

    // Api-Fehler

    if text <> 'Message sent' then
      raise ESmsGatewayApiException.Create( text );

    // Wer es mag
    ShowMessage( 'Nachricht wurde gesendet' );
  finally
    param.Free;
    jsa.Free;
  end;
end;
Generell solltest du dir überlegen ob es nicht mehr Sinn macht für den SMS-Versand ein Interface zu benutzen
Delphi-Quellcode:
ISmsGateway = interface
  procedure SendMessage( const APhoneNumber, AMessage : string );
end;
und dann je nach Anwendungsfall einfach das zutreffende Gateway erzeugst. Innerhalb der Anwendung bleibt der Zugriff dann gleich:
Delphi-Quellcode:
var
  SmsGateway : ISmsGateway;

SmsGateway.SendMessage( '12345678', 'Test-Nachricht' );
egal, welches konkrete Gateway da nun im Hintergrund bedient wird. Das macht die Sache wesentlich einfacher in der Benutzung (innerhalb der Anwendung) und der Erweiterung (neue Gateways implementieren)

zeras 2. Apr 2014 18:32

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Ich habe in meinem Tarif 2000 oder 3000 freie SMS. Problem ist nur, dass ich diese vom Handy aus schicken müsste. Aus der Weboberfläche kann ich am Tag nur eine senden. Vielleicht kann man ja einen Tarif finden, wo günstig bzw. kostenlos welche im Tarit mit drin sind.
Und dann müsste man mit Delphi bzw. Android ein Protokoll vereinbaren, wo man die jeweilige SMS auf dem Rechner erzeugen lässt und dann über eine Transaktion dann aufs Handy bekommt. Es gibt hier bestimmt den einen oder anderen Spezialist, der solch eine Anbindung mit XEMobile erstellen könnte.

Sir Rufo 2. Apr 2014 18:35

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Hier mal so eine Implementierung mit einem Interface
Delphi-Quellcode:
unit Service.SmsGateway;

interface

uses
  System.SysUtils;

type
  ESmsGatewayException = class( Exception );
  ESmsGatewayApiException = class( ESmsGatewayException );
  ESmsGatewayProtocolException = class( ESmsGatewayException );

  ISmsGateway = interface
    ['{824896A1-4A78-4470-993D-5C96881C612B}']
    procedure SendMessage( const APhoneNumber, AMessage : string ); overload;
    procedure SendMessage( const APhoneNumbers : array of string; const AMessage : string ); overload;
  end;

implementation

end.
Delphi-Quellcode:
unit com.freesmsgateway.api_send;

interface

uses
  Service.SmsGateway;

type
  TSmsGateway = class( TInterfacedObject, ISmsGateway )
  // Keine Magic Numbers/Values im Code
  // sondern als Konstanten definieren
  private const
    C_APIURL = 'http://www.freesmsgateway.com/api_send';
    C_ACCESSTOKEN = 'access_token';
    C_MESSAGE = 'message';
    C_MESSAGE_MAXLENGTH = 160;
    C_SENDTO = 'send_to';
    C_CONTACTS_EXISTING = 'existing_contacts';
    C_CONTACTS_POST = 'post_contacts';
    C_RESPONSE_OK = 'Message sent';
  private
    FAccessToken : string;
  public
    constructor Create( const AAccessToken : string );
    procedure SendMessage( const APhoneNumber, AMessage : string ); overload;
    procedure SendMessage( const APhoneNumbers : array of string; const AMessage : string ); overload;
  end;

implementation

uses
  System.Classes, System.SysUtils,
  Data.DBXJSON,
  IdException, IdHTTP;

function JSONStrArray( const AStrArray : array of string ) : string;
var
  LIdx : Integer;
  LResult : TJSONArray;
begin
  LResult := TJSONArray.Create;
  try
    for LIdx := Low( AStrArray ) to High( AStrArray ) do
    begin
      LResult.Add( AStrArray[LIdx] );
    end;
    Result := LResult.ToString;
  finally
    LResult.Free;
  end;
end;

{ TSmsGateway }

constructor TSmsGateway.Create( const AAccessToken : string );
begin
  inherited Create;

  { TODO :
    Validierung AAccessToken
    sonst EArgumentException werfen }

  if ( AAccessToken = '' )
  then
    raise EArgumentException.Create( 'AccessToken muss angegeben werden' );

  FAccessToken := AAccessToken;
end;

procedure TSmsGateway.SendMessage( const APhoneNumber, AMessage : string );
begin
  SendMessage( [APhoneNumber], AMessage );
end;

procedure TSmsGateway.SendMessage( const APhoneNumbers : array of string; const AMessage : string );
var
  LParams : TStringList;
  LHttp : TIdHttp;
  LResponse : string;
begin

  { TODO :
    Validierung APhoneNumbers:
    - gültige Telefon-Nummern
    sonst EArgumentException werfen }

  if Length( APhoneNumbers ) = 0
  then
    raise EArgumentOutOfRangeException.Create( 'Telefonnummer fehlt' );

  { TODO : alternativ in mehrere Nachrichten aufteilen }

  if Length( AMessage ) > C_MESSAGE_MAXLENGTH
  then
    raise EArgumentException.CreateFmt( 'Nachrioht darf max. %d Zeichen beinhalten', [C_MESSAGE_MAXLENGTH] );

  LParams := nil;
  LHttp := nil;
  try
    LParams := TStringList.Create;

    LParams.Values[C_ACCESSTOKEN] := FAccessToken;
    LParams.Values[C_MESSAGE] := AMessage;
    LParams.Values[C_SENDTO] := C_CONTACTS_POST;
    LParams.Values[C_CONTACTS_POST] := JSONStrArray( APhoneNumbers );

    LHttp := TIdHttp.Create( nil );

    try
      LResponse := LHttp.Post( C_APIURL, LParams );
    except
      on E : EIdException do
        raise ESmsGatewayProtocolException.CreateFmt( 'FreeSMSGateway.com: (%s) %s', [E.ClassName, E.Message] );
    end;

    if not LResponse.EndsWith( C_RESPONSE_OK )
    then
      raise ESmsGatewayApiException.CreateFmt( 'FreeSMSGateway.com: %s', [LResponse] );

  finally
    LHttp.Free;
    LParams.Free;
  end;
end;

end.

Union 2. Apr 2014 22:14

AW: Datenübergabe JSON-Array an FreeSMS-Anbieter
 
Ich sehe in der API keine Möglichkeit eine Absendernummmer anzugeben. Was kommt beim Empfänger denn an? Die Amerikanische Nummer des Anbieters oder eine konstante Nummer die evtl. im Account hinterlegt werden muß?


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz