Link to home
Start Free TrialLog in
Avatar of Annu
AnnuFlag for United Kingdom of Great Britain and Northern Ireland

asked on

VB: http post and callback script

I have an Access 2000 .adp that connects to SQL Server 2000 over an office network.

I want an Access Form to send payment information to an open browser page (IE or Firefox) that is a Virtual Terminal (VT) on a Internet payment service provider.

The VT page has text boxes for:

Name
Address
Town
County
Postcode
Country
Tel
Email
Ref
Currency
Amount
Credit Card Type
Credit Card Number
Issue Number
Expires End Month
Expires End Year
Security Code
Settlement

I want the user to type all this information in the Access Form and then press a button for it to be transfered into the relevant boxes on the VT page.

Then the user will 'submit' the transaction on the VT page and receive 2 pieces of information once the transaction has successfully been processed: Auth Code and Trans Ref.

I want these 2 pieces of info to be transferred to text boxes on the Access Form.

Can you please help me to write all the VB code for this?

Thanks.
Avatar of Annu
Annu
Flag of United Kingdom of Great Britain and Northern Ireland image

ASKER

I found the following code that solved the first part of my problem (send info to the webpage):

Set IE = CreateObject("InternetExplorer.Application")
IE.Navigate "http://localhost/login.html"
IE.Visible = True
Do Until IE.ReadyState = 4
Loop
IE.Document.All.Item("txtUsername").Value = "user"
IE.Document.All.Item("txtPassword").Value = "pass"
IE.Document.All.Item("btnSubmit").Click

Now I need to retrieve the Auth Code and Trans Ref from the webpage to my Access Form.

Can you help please?

Thanks.
Hi Annu

Please read both of my posts in this Q:
https://www.experts-exchange.com/questions/21991495/Access-Data-To-Website-Thru-Forms.html

Basically,
To send data from Access Form to a Web page:

web.Document.all(34).Value = [txtage]  
OR like you said
IE.Document.All.Item("txtUsername").Value = "user"


To Retrieve data from a Web page back to Access Form:

[txtweight] = web.Document.Forms(0).txtweight.Value


jaffer
Avatar of Annu

ASKER

Thanks Jaffer.

Can I just clarify a couple of things, please, so that you know exactly what's going on.

I have now succesfully got the code working to 'send' data to the IE fields. The user then clicks on 'Submit' on the IE page and the card transaction gets processed. The IE page then changes to display the Auth Code and Trans Ref for the successful transaction.

I now need to 'transfer' those values to my Access Form.

Thanks again.
What you want to do is crisp clear :)

Here is a code from one of my own programs that does exactly that:

1. it sends Data from Access to a Web page,
2. clicks the submit button,
3. reads the url, if it is still #1 (above), then it waits 2 seconds (repeatable), until another url shows (the Auth Code and Trans Ref, in your case),
4. then it reads the data from the Web Page back to Access Form.

in your case, since you wait for the approval page to show, you can skip step #3.

jaffer
'1
    'Fill the Haj Info in the Internet page
    cmdFillInternet_Click
    
    'assign the URL to a temporary storage,
    'we'll need this to know if the browser have gone to the next page 
    'after clicking the submit button
    Me.TempURL = web.LocationURL
 
'2   
    'Click on the Submit button
    web.Document.all("b1").Click     'Click on the Register button
'3    
'    While web.Busy  'wait until the site fully loads
'        DoEvents
'    Wend
'    While web.ReadyState <> 4 'wait until the site fully loads
'        DoEvents
'    Wend
    
    'wait until the browser goes to the Approval page
StartAgain:
    If web.LocationURL = Me.TempURL Then    
        'pause 2 seconds
        PauseTime = 2    ' Set duration.
        Start = Timer    ' Set start time.
        Do While Timer < Start + PauseTime
            DoEvents    ' Yield to other processes.
        Loop
        GoTo StartAgain
    End If
'4
    'Now Retrieve the Approval Number
    [Auth Code] = web.Document.Forms(0).Authization_Code.Value
    [Trans Ref] = web.Document.Forms(0).Transaction_Reference.Value
    'please change these values to match web ^^^^^^^^^^^^

Open in new window

Avatar of Annu

ASKER

Thanks Jaffer.

I think I've got it now, but there's one slight problem.

I use an Access Form button to do #1 above, then the user manually clicks on the IE Submit button. After the page has refreshed with the Auth Code and Trans Ref, the user clicks another Access Form button with code:

Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
Me.TransRef = IE.Document.All.Item("$streference").Value

I get this error for the above code:

Run-time error '91':
Object variable or With block variable not set

Do you know what is wrong? Thanks.

($stauthcode and $streference are variables that have the values.)
> Object variable or With block variable not set
This means Access lost the Internet Reference and cannot communicate with the web page, to make sure what I say is correct, just click on #1 button again, you will get the same error again.

to avoid this, either use the steps I mentioned above,
OR try this on the Retrieving button:

On Error Resume Next
Set IE = GetObject(, "InternetExplorer.Application")
Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
Me.TransRef = IE.Document.All.Item("$streference").Value


jaffer
Avatar of Annu

ASKER

Thanks Jaffer, and apologies for the delay in getting back.

Your solution worked:

On Error Resume Next
Set IE = GetObject(, "InternetExplorer.Application")

But now I have another problem :(

When the user clicks on the IE Submit button to process the payment, IE does not refresh, but opens another window (not tab) with the Auth Code and Trans Ref. So now your code above closes the second IE window but not the first!

Sorry about this, I didn't notice this before. Please can you show me how to close BOTH IE windows.

Also, this code doesn't seem to work:

Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
Me.TransRef = IE.Document.All.Item("$streference").Value

The Auth Code and Trans Ref do not appear in my Access Form. Any ideas?

Thanks for your help.
Hi Annu
1.
I have been through your problem before, that's when I decided to embed Internet Explorer into my Access Form, this way I only deal with ONE internet explorer.
This link gives you my code which I used on my Form:
https://www.experts-exchange.com/questions/22417826/What-is-the-URL-to-automatically-enter-a-USPS-Registered-Mail-tracking-number-to-USPS-com.html#18623644

2.
>Also, this code doesn't seem to work:
>Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
>Me.TransRef = IE.Document.All.Item("$streference").Value

This isn't my code, it is yours, I just modified the prefix!!
I assumed you knew the code works for you, so you posted it!!

my code was in my 1st post:
[txtweight] = web.Document.Forms(0).txtweight.Value


if the above still creates a problem for you, and can't get yourself out of it,
you can upload part of your zipped mdb (related to this issue) to www.ee-stuff.com
I will download it and put it together for you,
please give the required url and the other required data too.

jaffer
Avatar of Annu

ASKER

Thanks Jaffer.

Sorry, you have completely lost me (I am not very good at this) so I have uploaded the Form for you to have a look at.

Here are the details:
https://filedb.experts-exchange.com/incoming/ee-stuff/6433-EE_Jaffer.ziphttps://filedb.experts-exchange.com/incoming/ee-stuff/6426-EE_Jaffer.zip
 
https://filedb.experts-exchange.com/incoming/ee-stuff/6426-EE_Jaffer.zip 

I'd be grateful if you could just put the code in to close the second window (I like to keep things simple) and also see if you can correct the code to get the Auth Code and Trans Ref.

Thanks so much for your help, Jaffer.
Hi Annu

When you open your Form, next to Process Card, you will find a new button called "Process Form",
clicking on this button opens a new Form, frmIE_VT,
this is the code for opening frmIE_VT, which you might want to change:
    stDocName = "frmIE_VT"
    stLinkCriteria = "[DonorID]= " & Me.txtDonorIDFound
    DoCmd.OpenForm stDocName, , , stLinkCriteria

frmIE_VT is a duplicate of frmTelephoneDonations.

frmIE_VT will take a while to open, so don't do anything until that happens,
the delay is due to the fact that it opens the web site for you, and of course this delay depends on your internet speed.

frmIE_VT when opened, will contain the web page in it, in other words, there are NO internet pages that open seperately, but the site opens in the Form.

Once the site is full open, click on "Process Card" which "should" send the data to the site (which is in the Form),
click the "Send Payment" button on the site,
once the authorization page comes up, click on "Get code & Ref" on the Form.

For the button "Get code & Ref", I have changed the code to what I think is correct, but I cannot tell if the code is correct as I don't have the details of that page.
IF you cannot Retreive the code and Ref from the page, I would suggest you place this code on a command button in frmIE_VT:

'output controls to excel sheet
    Open "c:\Values.csv" For Output As #2
    For i = 0 To web.Document.all.length - 1
      If web.Document.all(i).getAttribute("type") <> "" Then
Print #2, i; ","; web.Document.all(i).getAttribute("type"); ","; web.Document.all(i).getAttribute("name")
     End If
    Next i
Close #2
=========================

now open "c:\Values.csv" with Excel
it will give you 3 columns:
Number   Type    Name

so for the next part you can assign the Access Form value to the Internet page by using the name or the number of that field as shown on the Excel file.

and here is the modified mdb with the above changes:
https://filedb.experts-exchange.com/incoming/ee-stuff/6433-EE_Jaffer.zip

jaffer
Hi Annu

Well,
Did you get it to work????

jaffer
Avatar of Annu

ASKER

Thanks Jaffer.
Sorry I was diverted with other probelms, but am looking at this now.
Avatar of Annu

ASKER

Jaffer:
I have imported your Forms into my app, but can't get frmIE_VT to display the webpage.

When I click on 'Process Form', frmIE_VT opens and there is a white space where the IE page should appear. This does not load the IE page; I have waited for more than 3 mins and have tried it out 3-4 times, but the same thing happens everytime. My Internet connection is fine too, and I have checked that the URL is OK and working aswell in another IE window.

Any ideas? Thanks for your help.
it looks like you have a Reference problem,
there should be one in the Form, and the other one in VBA,
follow this link to see how to do both:
https://www.experts-exchange.com/questions/22417826/What-is-the-URL-to-automatically-enter-a-USPS-Registered-Mail-tracking-number-to-USPS-com.html#18623644

jaffer
Avatar of Annu

ASKER

Jaffer, thank you so much for your help.

Unfortunately, I have to travel abroad tonight for a week and will not have access to the Internet. I will be back next Thursday and will carry on then... I think we are nearly there though.

Thank you again, and please accept my apologies for this delay.
Wassalaam
anwar
Salam Anwar

I was not able to check my solution on your mdb, because it didn't have any data.
Can you please send me the mdb I sent you with 1 dummy Record to test.

I couldn't open the Form in normal mode, because it gave errors due to lack of data, so I worked in Design mode, but as you can see, I need to test what I did.

thanks

jaffer
Avatar of Annu

ASKER

Sorry to get back so late, fell very ill after returning from abroad.

I have been thinking about this solution, Jaffer.

It would be much easier for me (and I would prefer it) if we could just close the second IE window and take the Auth Code and Trans Ref from it into the Access Form. Everything is working now except for these 2 things.

Hope that's OK. Thanks wassalaam
anwar
Salam Anwar

What you should do is to make Access code (not the user) click the submit button, wait for the authorisation page, then read its content,
The following thread does what you want:
https://www.experts-exchange.com/questions/21551204/Insert-calculated-answer-from-a-website-into-Access.html#14832519

>Also, this code doesn't seem to work:
>Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
>Me.TransRef = IE.Document.All.Item("$streference").Value
I don't think you have the correct names for
$stauthcode and $streference.

what you can do is to copy the authorization page to your pc and findout the exact names, then use them in your code.

to summarise what I said:
Your code should
send the data to IE
click the submit button
retrieve the data
NO manual interference, ourwise Access losses the connection.
In fact this is why I made IE inside Access, it is MUCH better way to deal with the issue.

>It would be much easier for me (and I would prefer it) if we could just close the
>second IE window and take the Auth Code and Trans Ref from it into the Access
>Form. Everything is working now except for these 2 things.
as I said before, since Access did not open the 2nd IE, it doesn't have control over it, so it cannot close it directly,
this thread shows an example on how to close a program using api:
https://www.experts-exchange.com/questions/20868220/Close-an-external-program-that-is-opened-by-access.html
or get its class name then close it:
http://www.mvps.org/access/api/api0013.htm

HOWEVER, windows explorer and Internet explorer share the same name, so if you have more than 1 IE or Windows explorer open, then GOOD LUCK ;)


jaffer
Another way to post or request information over HTTP is using the module code below.  I just happened to have this project open when I came accoss this.  

jjaffer's solution might be better, I havent read it all.
Private aspivErrorDesc As String
Private aspivPort As Long
Private aspivHostname As String
Private aspivFolder As String
 
Const INTERNET_SERVICE_HTTP = 3
 
'Public DontUseCache As Boolean
 
Private Enum InfoLevelEnum
    HTTP_QUERY_CONTENT_TYPE = 1
    HTTP_QUERY_CONTENT_LENGTH = 5
    HTTP_QUERY_EXPIRES = 10
    HTTP_QUERY_LAST_MODIFIED = 11
    HTTP_QUERY_PRAGMA = 17
    HTTP_QUERY_VERSION = 18
    HTTP_QUERY_STATUS_CODE = 19
    HTTP_QUERY_STATUS_TEXT = 20
    HTTP_QUERY_RAW_HEADERS = 21
    HTTP_QUERY_RAW_HEADERS_CRLF = 22
    HTTP_QUERY_FORWARDED = 30
    HTTP_QUERY_SERVER = 37
    HTTP_QUERY_USER_AGENT = 39
    HTTP_QUERY_SET_COOKIE = 43
    HTTP_QUERY_REQUEST_METHOD = 45
    HTTP_STATUS_DENIED = 401
    HTTP_STATUS_PROXY_AUTH_REQ = 407
End Enum
 
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_OPEN_TYPE_PROXY = 3
 
'Private Const SCUSERAGENT = "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"
Private Const SCUSERAGENT = "TABUSB"
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_FLAG_ASYNC = &H10000000  ' this request is asynchronous (where supported)
 
Private Const INTERNET_FLAG_FROM_CACHE = &H1000000   ' use offline semantics
Private Const INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE
Private Const INTERNET_FLAG_EXISTING_CONNECT = &H20000000
 
Private Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" _
    (ByVal hHttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, _
    ByRef lBufferLength As Long, ByRef lIndex As Long) As Integer
 
 
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
    (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, _
    ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
 
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" _
    (ByVal hOpen As Long, ByVal sUrl As String, ByVal sHeaders As String, _
    ByVal lLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
 
Private Declare Function InternetReadFile Lib "wininet.dll" _
    (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, _
    lNumberOfBytesRead As Long) As Integer
 
Private Declare Function InternetCloseHandle Lib "wininet.dll" _
    (ByVal hInet As Long) As Integer
 
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" ( _
    ByVal hHttpRequest As Long, _
    ByVal lpszHeaders As String, _
    ByVal dwHeadersLength As Long, _
    ByVal lpOptional As String, _
    ByVal dwOptionalLength As Long) As Boolean
    
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" ( _
    ByVal hHttpSession As Long, _
    ByVal lpszVerb As String, _
    ByVal lpszObjectName As String, _
    ByVal lpszVersion As String, _
    ByVal lpszReferer As String, _
    ByVal lpszAcceptTypes As String, _
    ByVal dwFlags As Long, _
    ByVal dwContext As Long) As Long
    
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" ( _
    ByVal hInternetSession As Long, _
    ByVal lpszServerName As String, _
    ByVal nServerPort As Integer, _
    ByVal lpszUsername As String, _
    ByVal lpszPassword As String, _
    ByVal dwService As Long, _
    ByVal dwFlags As Long, _
    ByVal dwContext As Long) As Long
    
Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" _
    (lpdwError As Long, ByVal lpszBuffer As String, ByVal lpdwBufferLength As Long) As Integer
    
' Adds one or more HTTP request headers to the HTTP request handle.
Private Declare Function HttpAddRequestHeaders Lib "wininet.dll" Alias "HttpAddRequestHeadersA" _
(ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, _
ByVal lModifiers As Long) As Integer
' Flags to modify the semantics of this function. Can be a combination of these values:
' Adds the header only if it does not already exist; otherwise, an error is returned.
Const HTTP_ADDREQ_FLAG_ADD_IF_NEW = &H10000000
' Adds the header if it does not exist. Used with REPLACE.
Const HTTP_ADDREQ_FLAG_ADD = &H20000000
' Replaces or removes a header. If the header value is empty and the header is found,
' it is removed. If not empty, the header value is replaced
Const HTTP_ADDREQ_FLAG_REPLACE = &H80000000
 
 
    
Public Function PostUrl(ByVal sUrl As String, ByVal strPostData As String) As String
  Dim bRes As Boolean
  Dim hrequest As Long
  Dim strbuffer As String * 1
  Dim returnData As String
  Dim hConnect As Long
  Dim hInternet As Long
  Dim lBytesRead As Long
  Dim sHost As String
  Dim oStrB As clsStringBuilder
  Set oStrB = New clsStringBuilder
 
  While InStr(sUrl, "://")
    sUrl = Mid(sUrl, InStr(sUrl, "://") + 3)
  Wend
  
  sHost = sUrl
  
  While InStr(sHost, "/")
    sHost = Left(sHost, InStr(sHost, "/") - 1)
  Wend
  
  sUrl = Mid(sUrl, Len(sHost) + 1)
  
  While InStr(sHost, ":")
    sHost = Left(sHost, InStr(sHost, ":") - 1)
  Wend
  'Stop
  
  hInternet = InternetOpen(App.Title, INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)
  hConnect = InternetConnect(hInternet, sHost, aspivPort, "", "", INTERNET_SERVICE_HTTP, 0, 0)
 
 
  If strPostData = "" Then
    hrequest = HttpOpenRequest(hConnect, "GET", sUrl, "HTTP/1.0", vbNullString, vbNullString, 0, 0)
  Else
    hrequest = HttpOpenRequest(hConnect, "POST", sUrl, "HTTP/1.0", vbNullString, vbNullString, 0, 0)
  End If
  Call HttpAddRequestHeaders(hrequest, "Content-Type: application/x-www-form-urlencoded", Len("Content-Type: application/x-www-form-urlencoded"), HTTP_ADDREQ_FLAG_REPLACE Or HTTP_ADDREQ_FLAG_ADD)
  Call HttpAddRequestHeaders(hrequest, "BrowserHost: " & SCUSERAGENT, Len("BrowserHost: " & SCUSERAGENT), HTTP_ADDREQ_FLAG_REPLACE Or HTTP_ADDREQ_FLAG_ADD)
 
  bRes = HttpSendRequest(hrequest, vbNullString, 0, strPostData, Len(strPostData))
  'returnData = ""
  oStrB.Clear
  Do
    bRes = InternetReadFile(hrequest, strbuffer, Len(strbuffer), lBytesRead)
    If lBytesRead > 0 Then
      oStrB.addDataFast strbuffer
      '  returnData = returnData + strbuffer
    End If
  Loop While lBytesRead > 0
  PostUrl = oStrB.StringStored
  Set oStrB = Nothing
  DoEvents
End Function

Open in new window

Avatar of Annu

ASKER

Hi guys, and thank you for your patience.

I have finally got things to work, except retrieving the Auth Code and Trans Ref values from IE to the Access form.

This is the code I am trying to use:

Me.txtAuthCode = IE.Document.All.Item("$stauthcode").Value
Me.TransRef = IE.Document.All.Item("$streference").Value

but it seems that $stauthcode and $streference is not correct (although this is what the technical guys told me).

Below is the Source code of the web page I am trying to copy from. Can you tell me what value names I have to use? Thanks.



<HTML>
<HEAD><TITLE>Success Page</TITLE></HEAD>
<BODY BACKGROUND="/images/back.jpg">
<img src="/images/securesite.gif" align=left border=0>
<font face="Arial, Helvetica, sans-serif">
<H2 align="center">Authorisation Success Page</H2>
<CENTER>
<H4>The credit card authorisation was successful for merchant : merchant1234</H4><BR>
</CENTER><BR><BR>
 
Amount          : <B>£5.00</B> (GBP)<BR>
Orderinfo       : <BR>
<BR>
Name            : Mr Anwar Saleem<BR>
Email           : <BR>
Company         : <BR>
Address         : 1 Any Road, Anyplace, , Zip, UK<BR>
Telephone		: 123456789<BR>
<BR>
Auth Code		: <B>AUTH CODE:665263</B><BR>
Trans Ref		: <B>20-3-693635</B><BR>
<BR>
</font>
</BODY>
</HTML>

Open in new window

I dont see how it would work that way, unless the tag with the values in were given an ID like
<Span ID="authcode">AUTHCODE:665263</span>

Then you could request the innerHTML value of the authcode element.

Using the module I posted would mean doing it differently, I could write the parsing function if you wanted to do it that way.
I agree with dentab,
the only way to get the Auth Code and Trans Ref values, is through parsing the innerHTML of that page,

Although that could be done,
BUT,
How will Access "see" this page?
I go back to my last post:
https://www.experts-exchange.com/questions/23045378/VB-http-post-and-callback-script.html?anchorAnswerId=20752898#a20752898
"to summarise what I said:
Your code should
send the data to IE
click the submit button
retrieve the data
NO manual interference, ourwise Access losses the connection."

So to pars the HTML page, you have to save the Authorization page to disk with a certain name, then press another button in your mdb to get the Auth Code and Trans Ref values. Which is too much of a hassel,
unless dentab knows something that I don't know.

To avoid all of this,
Please post here the HML or the url to the page where you enter the data/information, I will get the button name, then pars this auth HTML page.

jaffer
Jaffer,

My method was alternative, which would be calling IE API to download the page into a string.  No file would need saving.  Your method may well be simpler for Annu.
Well, if Annu provides the url, this will make our life easier.
Avatar of Annu

ASKER

Sorry guys, you have completely lost me here. I don't know ANYTHING about integrating with IE.

Anyway, below is the code I use to open the IE page and post the data.

Jaffer, I can't do the automatic way that you have suggested quite a few times because my Access form stores the postal address of the donor, and sometimes this is not the card registered address. So the user has to be able to adjust the address on the card page if the postal address and card address are different. Our system does not need to keep the card registered address, but we need to keep the correct postal address. I hope that explains things :)

Also, I only need to close one IE window now (the original that was opened by Access) once the Failure or Success page has been displayed, so that's another headache over...
Set IE = CreateObject("InternetExplorer.Application")
        IE.Navigate "https://securetrading.net/authorize/form.cgi?merchant=muslimaid5831&formref=2"
        IE.Visible = True
        IE.Left = 20
        IE.Top = 20
        IE.Height = 800
        IE.Width = 700
        
        Do Until IE.ReadyState = 4
        Loop
        
        IE.Document.all.Item("telephone").Value = Me.txtContactNumber
        
        
        If IsNull(Me.txtNameOrgNameChange) Or Me.txtNameOrgNameChange = "" Then
            IE.Document.all.Item("name").Value = Me.txtName
        Else
            IE.Document.all.Item("name").Value = Me.txtNameOrgNameChange
        End If
        
        
        If IsNull(Me.txtAddrLine1Change) Or Me.txtAddrLine1Change = "" Then
            IE.Document.all.Item("address").Value = Me.txtAddrLine1
        Else
            IE.Document.all.Item("address").Value = Me.txtDoorNoChange & " " & Me.txtAddrLine1Change
        End If
        
        
        If IsNull(Me.txtTownCityChange) Or Me.txtTownCityChange = "" Then
            IE.Document.all.Item("town").Value = Me.txtTown
        Else
            IE.Document.all.Item("town").Value = Me.txtTownCityChange
        End If
        
        
        IE.Document.all.Item("county").Value = ""
        
        
        If IsNull(Me.txtPostcodeChange) Or Me.txtPostcodeChange = "" Then
            IE.Document.all.Item("postcode").Value = Me.txtPostcode
        Else
            IE.Document.all.Item("postcode").Value = Me.txtPostcodeChange
        End If
        
    
        If IsNull(Me.txtDonorIDFound) Or Me.txtDonorIDFound = "" Then
            IE.Document.all.Item("country").Value = Me.txtCountryChange
        ElseIf IsNull(Me.txtCountry) Or Me.txtCountry = "" Then
            IE.Document.all.Item("country").Value = "UK"
        ElseIf Not IsNull(Me.txtCountry) Or Me.txtCountry <> "" Then
            IE.Document.all.Item("country").Value = Me.txtCountry
        End If
        
        
        IE.Document.all.Item("email").Value = ""
        
        
        If cmbCurrency = "£" Then
            IE.Document.all.Item("currency").Value = "GBP"
        ElseIf cmbCurrency = "$" Then
            IE.Document.all.Item("currency").Value = "USD"
        ElseIf cmbCurrency = "¬" Then
            IE.Document.all.Item("currency").Value = "EUR"
        End If
        
       
        IE.Document.all.Item("inputamount").Value = Me.txtTotalAmount
        IE.Document.all.Item("cctype").Value = Me.cmbCardType
        IE.Document.all.Item("ccnumber").Value = Me.txtCardNumber
        
        If IsNull(Me.txtCardIssueNo) Or Me.txtCardIssueNo = "" Then
            IE.Document.all.Item("ccissue").Value = ""
        Else
            IE.Document.all.Item("ccissue").Value = Me.txtCardIssueNo
        End If
        
        IE.Document.all.Item("month").Value = Me.cmbCardExpireMonth
        IE.Document.all.Item("year").Value = Me.cmbCardExpireYear
        IE.Document.all.Item("securitycode").Value = Me.txtCardSecurityCode
        IE.Document.all.Item("settlementday").Value = "1"

Open in new window

then try my method, if the final page does not require a referer - then it might be possible to use a form to take all the information.  The code I suggested would allow you to POST (HTTP POST) the data - I expect it could then be done with a single HTTP call.
Thanks for the additional info Annu,
let me see what I can do, now that we have more info.

jaffer
Avatar of Annu

ASKER

Thanks.

dentab: If I understand correctly, your solution will not allow my user to amend card address details on the IE page before submitting? See my comment above:

"Jaffer, I can't do the automatic way that you have suggested quite a few times because my Access form stores the postal address of the donor, and sometimes this is not the card registered address. So the user has to be able to adjust the address on the card page if the postal address and card address are different. Our system does not need to keep the card registered address, but we need to keep the correct postal address. I hope that explains things :)"

Thanks.
Annu one more Q

When you enter the data and click on the submit button, does the page change to the Authorisation page, or does it open a new page?
Hi Annu,

Like I said beffore jjaffers answer might be easier for you to use, because it is closer to what you already have.  My solution would never show the user a web-page.  You would have a second access form to ammend details.  The final action by the form would be a HTTP post, as if from the second web-page.  The information returned could be shorn as a web-page, but could also be shown in a form or message-box.

My Sulotion however is relying on a session not being required from the server from the first page before proceeding.  This solution has less dependancies and possibly more control of the information flow, but is lengthier to write and I am relying on my assumptions about the transaction server.
I would wait until jjafferr has finished his parsing routine (I think thats what he is doing).  If jjafferrs solution is not usable (I dont see why it wont work though), then I will try to help with this alternative.

Best of luck
Avatar of Annu

ASKER

OK, thanks dentab.
Annu

Pls reply to my last post,
thanks

jaffer
Avatar of Annu

ASKER

Sorry, Jaffer, I missed that.

It changes to the Authorisation page. No new page/window.

Thanks.
Avatar of Annu

ASKER

Any progress, Jaffer? Sorry to push you and I know that I have been very lapse about this.

Just want to go live and need this last thing to work.

Thank you for your help.

Wassalaam
anwar
Hi Anwar,

Sorry, I was too busy,
but I am working on it now.

jaffer
ASKER CERTIFIED SOLUTION
Avatar of jjafferr
jjafferr
Flag of Oman image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Anwar,

I posted my solution 4 days ago, yet I didn't hear from you!!
you said it was urgent!!
... guess not.

Hey Den where are you located?
I see you posting in our day time!!

I am from Oman, in the Persian Gulf.

jaffer
lol, not the same then... I'm in Essex in the UK.
It's a small world with this Internet thing,
and EE made it even smaller :)
I know, its funny - especially as everybody seems to write in English so well (aprart from us in the UK).  I don't know if I am talking with my next door neighbour or with somebody 1/2 way around the world.

What was really mad is during the war on Iraq, speaking to both people in Iraq and people in the US at the same time!  Thats something that will change war in the future, governments wont be able to disguise so easily that the "enemy" are people too.
Avatar of Annu

ASKER

Hi guys! Nice to know that you two are getting on well :) I'm in London, by the way, and was surprised that Jaffer is in Oman. I thought he was round the corner too!

Anyway, I'm really sorry for this delay. Unfortunately I am at the beck and call of my client, and as I was just about to get dug in with Jaffer's solution, they changed all my priorities for something more urgent. I've done that now, so will try and finish this off now...

Jaffer: I get this error when compiling the VBA for the code 'Private IE As WebBrowser':

Compile error: User-defined type not defined.

I am sure this is to do with your comment:

Please make sure you give the proper Reference in VBA:
'Make Reference to Microsoft Internet Controls

but I cannot find 'Microsoft Internet Controls' in my available Reference list in VBA.

Can you help please? Thanks again.
Oh well looks like this is going to be all wrapped up very soon.

It was nice to meet both of you, Annu you are not looking for VB coders at your place by any chance? lol
Avatar of Annu

ASKER

Jaffer:

Great! It works! Thanks so much Jaffer, you have been a really helpful. I dd choose Microsoft Browser Help and it changed to Microsoft Internet Controls too!

One last little thing: I already declare Public IE As Object because I close the IE window using another form. Can I just change the this line in your code and use another name for IE:

vBody = IE.Document.body.innerHTML

dentab: how can I contact you?

Thanks.
Nice one Jaffer!

My email alias is denzil.newman on the domain tab.ac.uk :)
Avatar of Annu

ASKER

Jaffer:

I got this last problem solved by removing your line: Private IE As WebBrowser

because I already had:  Public IE As Object

but did not rename anything (so IE is still IE).

Everything seems to work fine now. Can you just confirm that this will be OK - to use Object instead of Browser?

Thanks!

dentab: I'll be in touch :)
LOL
Wow, what a nice end, makes me want to cry ;)

Den,
Like wise, nice meeting you :)

Anwar,
Man, you have the program on you, why would you ask me, just give it a try and test it for your self, and let me know ;)

Ok, Ok, I won't spoil the moment,
I have tried it and IT WORKS.

jaffer
lol

Anwar, yes it will be ok - its just that if you use Object you wont get intellisence helping you.
Avatar of Annu

ASKER

:)

Jaffer: I did test it ofcourse, and it did work. What I meant was that I did not know about other IMPLICATIONS of using Object instead of Browser...

Sorry should have been more specific :)

Anyway, alls well that ends well.

dentab: I'll probably give all the points to Jaffer as it was his code that did it for me. Is that OK with you?
absolutely, it was all Jaffer.
Den
Please explaine what you code does, I want to learn,
then we can share the points :)

Ok Annu?
lol, sure jjafferr but the points are all yours.

Mind if we do this by email instead though?

My email alias is denzil.newman on the domain tab.ac.uk :)
Hmmmm,
Can I request for it to be posted here, so that others can benifit from it too.
I still want to share the points with your code, if you don't mind.

thanks

jaffer
ok...

I will try to post an explanation tomorrow
Avatar of Annu

ASKER

I think since I have decided to give all points to Jaffer, I'll leave it to Jaffer to tell me what to do with the points.
Annu, you're still at work?
Thanks Anwar,
I would like to share the points with Den's explanation of his code, it is an added value to my answer, and I would like to learn from it, as well as any one else who reads this Q.

So once Den places his eplanation tomorrow, you can split the points between us.

Thanks once again to both of you.

jaffer
Jaffer, I'll explain it - but you earnt these points.

I wont be doing anymore EE tonight, so I'll catch up with you tomorrow.
Hey tehy are my points and I can do whatever I like to do with them, ask Annu :)
lol, sorry I have been meaning to post the answer...

I forgot to post the StringBuilder Class the first time too... I shall get onto this tomorrow... really I will.
Right finally, here we go.

Firstly I have attached the stringbuilder class below... put this in a new class module and call it clsStringBuilder

Unlike the other code module, the StringBuilder is entirely my own creation.  Quite simply its to concatenate strings, You may well already know this, but in VB when you concatenate two strings (e.g. strA = strA & strB) it creates a new string and copies both strings into it rather than just extending the first string... in other words the work done for
strA = strA & strB
is actually the same as
strC = strA & strB

This means that the bigger the recieving string is, the exponentially longer the process takes.  The string builder class breaks the recieved strings into an array and minimizes the number of times the strings have to be joined.  The array is copied together using a Join statement.
Const INTERNET_SERVICE_HTTP = 3
 
'Public DontUseCache As Boolean
 
Private Enum InfoLevelEnum
    HTTP_QUERY_CONTENT_TYPE = 1
    HTTP_QUERY_CONTENT_LENGTH = 5
    HTTP_QUERY_EXPIRES = 10
    HTTP_QUERY_LAST_MODIFIED = 11
    HTTP_QUERY_PRAGMA = 17
    HTTP_QUERY_VERSION = 18
    HTTP_QUERY_STATUS_CODE = 19
    HTTP_QUERY_STATUS_TEXT = 20
    HTTP_QUERY_RAW_HEADERS = 21
    HTTP_QUERY_RAW_HEADERS_CRLF = 22
    HTTP_QUERY_FORWARDED = 30
    HTTP_QUERY_SERVER = 37
    HTTP_QUERY_USER_AGENT = 39
    HTTP_QUERY_SET_COOKIE = 43
    HTTP_QUERY_REQUEST_METHOD = 45
    HTTP_STATUS_DENIED = 401
    HTTP_STATUS_PROXY_AUTH_REQ = 407
End Enum
 
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_OPEN_TYPE_PROXY = 3
 
'Private Const SCUSERAGENT = "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"
Private Const SCUSERAGENT = "TABUSB"
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_FLAG_ASYNC = &H10000000  ' this request is asynchronous (where supported)
 
Private Const INTERNET_FLAG_FROM_CACHE = &H1000000   ' use offline semantics
Private Const INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE
Private Const INTERNET_FLAG_EXISTING_CONNECT = &H20000000
 
Private Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" _
    (ByVal hHttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, _
    ByRef lBufferLength As Long, ByRef lIndex As Long) As Integer
 
 
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
    (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, _
    ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
 
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" _
    (ByVal hOpen As Long, ByVal sUrl As String, ByVal sHeaders As String, _
    ByVal lLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
 
Private Declare Function InternetReadFile Lib "wininet.dll" _
    (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumBytesToRead As Long, _
    lNumberOfBytesRead As Long) As Integer
 
Private Declare Function InternetCloseHandle Lib "wininet.dll" _
    (ByVal hInet As Long) As Integer
 
Private Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" ( _
    ByVal hHttpRequest As Long, _
    ByVal lpszHeaders As String, _
    ByVal dwHeadersLength As Long, _
    ByVal lpOptional As String, _
    ByVal dwOptionalLength As Long) As Boolean
    
Private Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" ( _
    ByVal hHttpSession As Long, _
    ByVal lpszVerb As String, _
    ByVal lpszObjectName As String, _
    ByVal lpszVersion As String, _
    ByVal lpszReferer As String, _
    ByVal lpszAcceptTypes As String, _
    ByVal dwFlags As Long, _
    ByVal dwContext As Long) As Long
    
Private Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" ( _
    ByVal hInternetSession As Long, _
    ByVal lpszServerName As String, _
    ByVal nServerPort As Integer, _
    ByVal lpszUsername As String, _
    ByVal lpszPassword As String, _
    ByVal dwService As Long, _
    ByVal dwFlags As Long, _
    ByVal dwContext As Long) As Long
    
Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" Alias "InternetGetLastResponseInfoA" _
    (lpdwError As Long, ByVal lpszBuffer As String, ByVal lpdwBufferLength As Long) As Integer
    
' Adds one or more HTTP request headers to the HTTP request handle.
Private Declare Function HttpAddRequestHeaders Lib "wininet.dll" Alias "HttpAddRequestHeadersA" _
(ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, _
ByVal lModifiers As Long) As Integer
' Flags to modify the semantics of this function. Can be a combination of these values:
' Adds the header only if it does not already exist; otherwise, an error is returned.
Const HTTP_ADDREQ_FLAG_ADD_IF_NEW = &H10000000
' Adds the header if it does not exist. Used with REPLACE.
Const HTTP_ADDREQ_FLAG_ADD = &H20000000
' Replaces or removes a header. If the header value is empty and the header is found,
' it is removed. If not empty, the header value is replaced
Const HTTP_ADDREQ_FLAG_REPLACE = &H80000000
 
 
    
Public Function PostUrl(ByVal sUrl As String, ByVal strPostData As String) As String
  Dim bRes As Boolean
  Dim hrequest As Long
  Dim strbuffer As String * 1
  Dim returnData As String
  Dim hConnect As Long
  Dim hInternet As Long
  Dim lBytesRead As Long
  Dim sHost As String
  Dim oStrB As clsStringBuilder
  Set oStrB = New clsStringBuilder
 
  While InStr(sUrl, "://")
    sUrl = Mid(sUrl, InStr(sUrl, "://") + 3)
  Wend
  
  sHost = sUrl
  
  While InStr(sHost, "/")
    sHost = Left(sHost, InStr(sHost, "/") - 1)
  Wend
  
  sUrl = Mid(sUrl, Len(sHost) + 1)
  
  While InStr(sHost, ":")
    sHost = Left(sHost, InStr(sHost, ":") - 1)
  Wend
  'Stop
  
  hInternet = InternetOpen(App.Title, INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)
  hConnect = InternetConnect(hInternet, sHost, aspivPort, "", "", INTERNET_SERVICE_HTTP, 0, 0)
 
 
  If strPostData = "" Then
    hrequest = HttpOpenRequest(hConnect, "GET", sUrl, "HTTP/1.0", vbNullString, vbNullString, 0, 0)
  Else
    hrequest = HttpOpenRequest(hConnect, "POST", sUrl, "HTTP/1.0", vbNullString, vbNullString, 0, 0)
  End If
  Call HttpAddRequestHeaders(hrequest, "Content-Type: application/x-www-form-urlencoded", Len("Content-Type: application/x-www-form-urlencoded"), HTTP_ADDREQ_FLAG_REPLACE Or HTTP_ADDREQ_FLAG_ADD)
  Call HttpAddRequestHeaders(hrequest, "BrowserHost: " & SCUSERAGENT, Len("BrowserHost: " & SCUSERAGENT), HTTP_ADDREQ_FLAG_REPLACE Or HTTP_ADDREQ_FLAG_ADD)
 
  bRes = HttpSendRequest(hrequest, vbNullString, 0, strPostData, Len(strPostData))
  'returnData = ""
  oStrB.Clear
  Do
    bRes = InternetReadFile(hrequest, strbuffer, Len(strbuffer), lBytesRead)
    If lBytesRead > 0 Then
      oStrB.addDataFast strbuffer
      '  returnData = returnData + strbuffer
    End If
  Loop While lBytesRead > 0
  PostUrl = oStrB.StringStored
  Set oStrB = Nothing
  DoEvents
End Function

Open in new window

doh, the last post was the Internet module again - EE please, why cant you delete your own posts!!??

here is the class
Private Const maxAddSeg As Long = 250
Private Const initBlocks As Long = 3000
Private Const blockExpansionStep As Long = 1000
 
Private dataBlock() As String
Private topBlock As Long
Private curBlock As Long
 
Public Sub addDataFast(ByVal thisData As String)
  If Len(dataBlock(curBlock)) > maxAddSeg Then
    newBlock
  End If
  dataBlock(curBlock) = dataBlock(curBlock) & thisData
End Sub
 
Public Sub add(ByVal thisData As String)
  If Len(dataBlock(curBlock)) > maxAddSeg Then
    newBlock
  End If
  dataBlock(curBlock) = dataBlock(curBlock) & thisData
End Sub
 
 
Public Sub addDataLowMem(ByRef thisData As String)
  If Len(dataBlock(curBlock)) > maxAddSeg Then
    newBlock
  End If
  dataBlock(curBlock) = dataBlock(curBlock) & thisData
End Sub
 
Private Sub Class_Initialize()
  ReDim dataBlock(10)
  topBlock = 0
  curBlock = 0
End Sub
 
Private Sub newBlock()
  curBlock = curBlock + 1
  If curBlock > topBlock Then
    topBlock = topBlock + blockExpansionStep
    ReDim Preserve dataBlock(topBlock)
  End If
End Sub
 
Public Sub Clear()
  ReDim dataBlock(initBlocks)
  topBlock = 0
  curBlock = 0
End Sub
 
 
 
Public Property Get BytesStored() As Variant
  Dim aLoop As Long
  BytesStored = CDec(0)
  For aLoop = 0 To curBlock
    BytesStored = BytesStored + Len(dataBlock(aLoop))
  Next
  BytesStored = BytesStored * 2
End Property
 
Public Property Get BytesStoredText() As String
  BytesStoredText = bytesToText(BytesStored)
End Property
 
Private Sub Class_Terminate()
  ReDim dataBlock(0)
  topBlock = 0
  curBlock = 0
End Sub
 
Private Function bytesToText(ByVal noBytes As Variant) As String
  Dim ext As String
  ext = "B"
  noBytes = CDec(noBytes)
  If noBytes > 1024 Then
    noBytes = noBytes / 1024
    ext = "K"
    If noBytes > 1024 Then
      noBytes = noBytes / 1024
      ext = "MB"
      If noBytes > 1024 Then
        noBytes = noBytes / 1024
        ext = "GB"
        If noBytes > 1024 Then
          noBytes = noBytes / 1024
          ext = "TB"
          If noBytes > 1024 Then
            noBytes = noBytes / 1024
            ext = "Petabytes"
            If noBytes > 1024 Then
              noBytes = noBytes / 1024
              ext = "Exabytes"
            End If
          End If
        End If
      End If
    End If
  End If
  noBytes = Round(noBytes, 2)
  bytesToText = noBytes & ext
End Function
Public Property Get RAMdataCost() As Variant
  Dim rdc As Variant
  'How this is calculated
  'An array costs 20 bytes
  'Each index of an array costs an additional 4 bytes + the space used by
  '  the variable it is an array of
  'Variable-Length strings cost 10bytes + length of string
  'Bytes stored is the length of all the strings
  'So (14bytes*no indexes)+BytesStored+20bytes(Array initial overhead) = Ram used by array
  RAMdataCost = CDec(((UBound(dataBlock) + 1) * 14) + 20 + (BytesStored))
End Property
 
Public Property Get StringStored() As String
  Dim strJoined As String
  strJoined = Join(dataBlock, "")
  StringStored = strJoined
  Me.Clear
  topBlock = 1
  dataBlock(0) = strJoined
End Property
 
Public Property Let StringStored(ByVal vNewValue As String) 'Alternative to SUB
  If Len(dataBlock(curBlock)) > maxAddSeg Then
    newBlock
  End If
  dataBlock(curBlock) = dataBlock(curBlock) & vNewValue
End Property

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
So to download a webpage (just the page, not images etc) I have listed different examples below using a fictional web called staffweb and a webpage called telephone.asp that returnes staff phone numbers based on the requested name.

To download the page:
txtDownloadSource.Text = HttpRequest("http://staffweb/telephone.asp")

To download the page using a GET request for the name of Dentab:
txtDownloadSource.Text = HttpRequest("http://staffweb/telephone.asp?name=dentab")

To download the page using a POST request for the name of Dentab:
txtDownloadSource.Text = HttpRequest("http://staffweb/telephone.asp", "name=dentab")

To download the page using a POST request for the name of Dentab and the webserver being on port 81:
txtDownloadSource.Text = HttpRequest("http://staffweb:81/telephone.asp", "name=dentab")

I hope this makes sense, and answers what you wanted jjaffer.  Please let me know if I omitted anything or left in any errors.

Dentab
Hi Den
Thanks for the class and the module, I didn't look deep in them, but I will.

One thing I noticed though, your examples were to download/request info,
but in your 1st post you said:
>Another way to post or request information over HTTP is using the module code below.

Does the code post info too?
can you please give an example.

I appreciate your input Den,

jaffer
Yes it does, but all posts are requests.

if you see my last post I have provided an example of a post, data will be returned but you can ignore it.  For example to simulate a textbox called strTest being POSTed with the value of hello world, then you could do:

Call HttpRequest("http://staffweb/telephone.asp", "strTest=hello+world")

or if you would rather send the data via a GET then

Call HttpRequest("http://staffweb/telephone.asp?strTest=hello+world")

Does that make sense?
If you have a HTML form you would like me to emulate, then I show you how.  The values do need to be URL encoded and there are lots of examples of how to do it, I can post a URL encode function too if you like.
found one
Function URLEncode(ByVal Text As String) As String
    Dim i As Integer
    Dim acode As Integer
    Dim char As String
    
    URLEncode = Text
    
    For i = Len(URLEncode) To 1 Step -1
        acode = Asc(Mid$(URLEncode, i, 1))
        Select Case acode
            Case 48 To 57, 65 To 90, 97 To 122
                ' don't touch alphanumeric chars
            Case 32
                ' replace space with "+"
                Mid$(URLEncode, i, 1) = "+"
            Case Else
                ' replace punctuation chars with "%hex"
                URLEncode = Left$(URLEncode, i - 1) & "%" & Hex$(acode) & Mid$ _
                    (URLEncode, i + 1)
        End Select
    Next
    
End Function

Open in new window

Den

Thank you very much, I am happy with what you gave,
now that I have the code, it's a matter of playing with it.

Annu

Please go ahead and split the points :)

Thanks to both of you.

jaffer
ok, let me know if it doesnt achieve what you need.

DenTab
Avatar of Annu

ASKER

I hope everybody is happy now.

I am :)

Thanks!
:)

Well thanks for the points jjaffer/Annu

See you around,
DenTab
Thanks Anwar/Den
This is what I consider, Job well done.

jaffer