Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 18 total
Thread Power
Thu, Mar 20 2014 12:56 PMPermanent Link

Matthew Jones

I'd just like to say, while I'm feeling happy, that writing web systems in Elevate
WebBuilder is really good fun. I've just done my first complete "3D-Secure"
(Verified by Visa) transaction on my new web shop. The WebBuilder part is sort of
easy, but it sends the order details to my Delphi backend, which is using
RemObjects SDK as the communication mechanism. The Delphi back-end does all sorts
of things like generate install codes for the software, create PDF invoices, and
sends emails. These are done in threads, which watch DBISAM tables for things to do,
which means that the EWB application in the browser sends the request and then asks
for the status to show the customer and it keeps it responsive. The actual card
payment is done using another service dedicated to talking to the card processing
company. The link is again via RemObjects, but with an interface DLL to make it
easy for a desktop app. In the case of the 3D Secure requirement, the card service
returns data which is returned to the EWB application to trigger the TPage to show
the authentication page. They authenticate, and that causes a POST to the
RemObjects server which I customised to take the data and pass it to the database
and then kick the order processing thread along which then passes the data back to
the card service, which then completes the payment. Then the order is completed and
the user gets to see the final cart.

I wrote the whole product selection and cart thing in about 2.5 weeks. The 3D
secure part was about 2 weeks I think. I did start with my existing service
framework and card system, but I have implemented a new provider. All been really
good fun and little hassle.

I shall soon ask for feedback on it...

/Matthew Jones/
Fri, Mar 21 2014 5:22 AMPermanent Link

Mark Brooks

Slikware

Avatar

Would like to see this Matthew
Fri, Mar 21 2014 9:35 AMPermanent Link

Matthew Jones

There's an early version at dev .ban xia. com  (eliminate the spaces to access!
I'll be updating it with the much better version sometime next week. Feel free to
create an account. I shall work out a way to hide the test card numbers sometime
but in that version any 16 digit number "works" I think.

/Matthew Jones/
Fri, Mar 21 2014 10:46 AMPermanent Link

Matthew Jones

I've set up "demo@ ban
xia . com" with the password elevate. I've also set the card payment to test mode
so it isn't doing anything real (it never will, but this doesn't even talk to
anyone either).

/Matthew Jones/
Tue, Mar 25 2014 12:36 PMPermanent Link

Matthew Jones

I'd be interested in any feedback on this. I've not yet got it polished, and the
shipping and tax is "todo" but it is now up to date and working. Details of a test
card number are at the bottom of the application, and it does the full "verified by
VISA" operation, except it is with the test card of my payment provider so it looks
all technical - just hit "submit" to complete. The invoice download works, the
software install codes are not complete and you can't download, but I'm quite
pleased with it so far. (Most of the last week has been fighting the payment
provider - integrating it into EWB has been easy).

Account details in the previous posting, and it may change in the future.

/Matthew Jones/
Thu, Mar 27 2014 6:53 AMPermanent Link

Mark Brooks

Slikware

Avatar

>> I'd be interested in any feedback on this.

It's nice Mathew. Only slight concern for me would be lack of distinct "view URLs" and therefore ability to navigate with browser back and forward. Great job though.
Thu, Mar 27 2014 9:35 AMPermanent Link

Matthew Jones

Browser navigation is an interesting one - it doesn't look too possible. But it
does make me think that it needs to have a few "jump to product" facilities so that
we can link directly to a specific product. Hmm, slight issue in that the products
come from a database, but I'll work on that too!

It's not finished, but it is getting there.

/Matthew Jones/
Thu, Mar 27 2014 4:24 PMPermanent Link

Mark Brooks

Slikware

Avatar

>> Browser navigation is an interesting one - it doesn't look too possible

It's pretty straightforward if you:

1) Define a number of views in your app e.g. Login
2) Define a URL hash string for each e.g. #View=Login
3) Have your code set the URL has string in order to display a particular view
4) Trap the hash change and show the view accordingly

Sounds a lot, but actually not too much code

Cheers
Fri, Mar 28 2014 6:29 AMPermanent Link

Matthew Jones

Do you have code for EWB to do it? I'll give it a go if you have.

/Matthew Jones/
Wed, Apr 2 2014 6:25 AMPermanent Link

Mark Brooks

Slikware

Avatar

>>Do you have code for EWB to do it? I'll give it a go if you have.

SO SORRY for the delay, but hope this makes sense

// Call this in order to trap changes to the "hash" part of the URL

SetWindowEventHandler('hashchange',TrapWindowHashChange);

// Code a bit like this will form the trap

function TfrmHeader.TrapWindowHashChange(event: TEvent): boolean;
begin
 Result := True;

 fWindowHash.ReadFromBrowser;

 if fWindowHash.Names[0] = 'View' then
   begin
     if fWindowHash.Values[0] = 'Home' then
       DoShowForm(frmHome)

     else if fWindowHash.Values[0] = 'Welcome' then
       DoShowForm(frmWelcome)

     else if fWindowHash.Values[0] = 'Item' then
       DoShowForm(frmItem)

     else if fWindowHash.Values[0] = 'Preview' then
       DoShowForm(frmPreview)

     else if fWindowHash.Values[0] = 'Folder' then
       DoShowForm(frmFolder)

     else if fWindowHash.Values[0] = 'Notifications' then
       DoShowForm(frmNotifications)

     else if fWindowHash.Values[0] = 'Discussions' then
       DoShowForm(frmDiscussions)

     else if fWindowHash.Values[0] = 'Subscribed' then
       DoShowForm(frmSubscribed)

     else if fWindowHash.Values[0] = 'Upload' then
       DoShowForm(frmUpload)

     else if fWindowHash.Values[0] = 'Settings' then
       DoShowForm(frmSettings)

     else if fWindowHash.Values[0] = 'Search' then
       DoShowForm(frmSearch)

     else if fWindowHash.Values[0] = 'Discussion' then
       DoShowForm(frmDiscussion)
   end
end;

// And I have a class to read and write the "hash" element of the URL (fWindowHash in the above code) including breaking out name:value pairs


 TWindowHash = class
 private
   fList: TStringList;
   function GetText: string;
   function GetCount: integer;
   function GetName(I: integer): string;
   function GetValue(I: integer): string;
 public
   constructor Create; override;
   destructor Destroy; override;
   procedure Clear;
   procedure SendToBrowser(const ANewTab: boolean = False);
   procedure ReadFromBrowser;
   procedure AddPair(const AName: string; const AValue: string);
   property Count: integer read GetCount;
   property Names[I: integer]: string read GetName;
   property Values[I: integer]: string read GetValue;   
   property Text: string read GetText;
 end;

implementation

uses
 WebDOM;

constructor TWindowHash.Create;
begin
 inherited Create;
 fList := TStringList.Create;
 fList.LineSeparator := '&';
end;

destructor TWindowhash.Destroy;
begin
 fList.Free;
 inherited Destroy;
end;

procedure TWindowHash.SendToBrowser(const ANewTab: boolean = False);
var
 S: string;
 I: integer;
begin

 if fList.Count = 0 then
   S := ''
 else
   begin
     S := '#';
     for I := 0 to fList.Count - 1 do
       begin
         S := S + Names[I];
         S := S + '=';
         S := S + Values[I];
         if I < fList.Count - 1 then
           S := S + '&';
       end;
   end;

 if ANewTab then
   Window.Open(StrReplace(Window.Location.HRef,Window.Location.Hash,S),'_blank','',False)
 else
   Window.Location.Hash := S;                          {+ '&_dc=' + IntToStr(MSecondOf(Now) + (SecondOf(Now) * 1000) + (MinuteOf(Now) * 60 * 1000))}
end;

procedure TWindowHash.ReadFromBrowser;
var
 S: string;
 I: integer;
begin
 fList.Clear;
 S := Window.Location.Hash;
 if S[1] <> '#' then
   exit;
 S := Copy(S,2,Length(S) - 1);
 if S = '' then
   raise EError.Create('TWindowHash.ReadFromBrowser: Empty hash encountered');
 fList.Text := S;
 for I := 0 to fList.Count - 1 do
   if Pos('=',fList[I]) = 0 then
     raise EError.Create('TWindowHash.ReadFromBrowser: Pair format is invalid');
 {if Pos('_dc=',fList[fList.Count - 1]) <> 0 then
   fList.Remove(fList.Count - 1);}
end;

procedure TWindowHash.Clear;
begin
 fList.Clear;
end;

procedure TWindowHash.AddPair(const AName: string; const AValue: string);
begin
 if Trim(AName) = '' then
   raise EError.Create('TWindowHash.AddPair: Empty name');
 if Trim(AValue) = '' then
   raise EError.Create('TWindowHash.AddPair: Empty value');
 fList.Add(Trim(AName) + '=' + Trim(AValue));
end;

function TWindowHash.GetText: string;
begin
 Result := fList.Text;
end;

function TWindowHash.GetCount: integer;
begin
 Result := fList.Count;
end;

function TWindowHash.GetName(I: integer): string;
var
 S: string;
 P: integer;
begin
 if (I < 0) or (I > fList.Count - 1) then
   raise EError.Create('TWindowHash.GetName: Invalid index');
 S := fList[I];
 P := Pos('=',S);
 if P = 0 then
   raise EError.Create('TWindowHash.GetName: Pair format is invalid');
 Result := Copy(S,1,P - 1);
 if Result = '' then
   raise EError.Create('TWindowHash.GetName: Empty name');
end;

function TWindowHash.GetValue(I: integer): string;
var
 S: string;
 P: integer;
begin
 if (I < 0) or (I > fList.Count - 1) then
   raise EError.Create('TWindowHash.GetValue: Invalid index');
 S := fList[I];
 P := Pos('=',S);
 if P = 0 then
   raise EError.Create('TWindowHash.GetValue: Pair format is invalid');
 Result := Copy(S,P + 1,Length(S) - P);
 if Result = '' then
   raise EError.Create('TWindowHash.GetValue: Empty value');
end;
Page 1 of 2Next Page
Jump to Page:  1 2
Image