ASP (VBScript)

From Facebook Developers Wiki

Jump to: navigation, search

Contents

[edit] Craig Bovis

This is a class I have written for interfacing with FaceBook from Canvas pages. Requires MD5.asp class by Chris Read (http://chris.brimson-read.com.au/?page_id=7)

v1.2 (2007/07/23)

  • Added a SendNotificationRequest method for simple calling of the facebook.notifications.sendRequest method.
  • Added a Form method. This returns the value of a posted form item by key. If the item was specified as an array in your FBML then a Variant() will be returned otherwise a string will be returned.
  • Added a IncludeCSS method. This allows you to easily embed CSS from an external file into your FBML.
  • Added a FQLQuery method for executing an FQL statement and retrieving the results.
  • Added a SetProfileFBML method for easily setting the profile FBML of a user.
  • Added a SetRefHandle method for easily setting the content of an fb:ref by handle.
  • Added a RequireInstall method which redirects the user to your install page if they have not installed the app.
  • Added a SuccessMessage method which produces a standard FBML success tag with the specified message.
  • Added a ErrorMessage method which produces a standard FBML error tag with the specified message.
  • Added a Redirect method which writes a standard FBML redirect to the response causing your page to redirect when called.
  • Moved the API version into a constant.
  • Now using the faster REST server.

v1.1 (2007/06/30)

  • Added the ability to quickly reference InCanvas, ApplicationInstalled & UserID variables passed to your canvas page by Facebook
  • Change the field lookup to check both GET & POST. Some users have reported that Facebook switches between which one is used.
  • API calls now use ServerXMLHTTP and make a POST request
  • Data is encoded properly when passed to the API. This fixes problems with passing FBML etc. as parameters.
  • The CallID is now based off of a Timestamp (plus an incremented integer since we might make multiple requests per second)

[edit] Facebook.asp

<%

    ' FaceBook ASP Class v1.2
    ' Developed by Craig Bovis
    '-----------------------------
    '
    ' This class is designed to allow you to interface with facebook applications via a Canvas page
    ' It provides simple methods for authenticating the canvas request and making calls to the Facebook API
    
    CONST REST_URI = "http://api.facebook.com/bestserver.php"
    CONST FB_PARAM_PREFIX = "fb_sig"
    CONST FB_API_VERSION = "1.0"
    
    Class FaceBook
        
        Public SecretKey
        Public ApiKey
        Public SessionKey
        
        ' Public properties for accessing information passed across to this callback from Facebook
        
        Public Property Get InCanvas
        	InCanvas = (Request(FB_PARAM_PREFIX & "_in_canvas") = "1")
        End Property
        
        Public Property Get ApplicationInstalled
        	ApplicationInstalled = (Request(FB_PARAM_PREFIX & "_added") = "1")
        End Property
        
        Public Property Get UserID
        	UserID = Request(FB_PARAM_PREFIX & "_user")
        End Property
        
        ' This allows you to call a facebook method (e.g. facebook.profile.getFBML) with the specified parameters
        ' You do not need to pass in the following parameters as they are appended automatically,
        '   - session_key
        '   - api_key
        '   - call_id
        '   - v
        Public Function CallApiMethod(strMethod, oParams)
            oParams("method") = strMethod
            Dim oXMLHTTP
            Set oXMLHTTP = Server.CreateObject("MSXML2.ServerXMLHTTP")
            oXMLHTTP.Open "GET", GenerateRequestURI(oParams), False
            oXMLHTTP.Send()
            Set CallApiMethod = oXMLHTTP.ResponseXml
        End Function
        
        Public Sub Redirect(strURI)
            %>
                <fb:redirect url="<%= strURI %>" />
            <%
        End Sub
        
        Public Function ErrorMessage(strMsg)
            ErrorMessage = "<fb:error message=""" & strMsg & """ />"
        End Function
        
        Public Function SuccessMessage(strMsg)
            SuccessMessage = "<fb:success message=""" & strMsg & """ />"
        End Function
        
        Public Function RequireInstall()
            If (Request.Form("fb_sig_added") = "0") Then
                %>
                    <fb:redirect url="http://www.facebook.com/apps/application.php?api_key=<%= ApiKey %>" />
                <%
            End If
        End Function
        
        Public Function SetRefHandle(handle, fbml)
            Dim oParams
            Set oParams = Server.CreateObject("Scripting.Dictionary")
            oParams.Add "handle", handle
            oParams.Add "fbml", fbml
            Set SetRefHandle = CallApiMethod("facebook.fbml.setRefHandle", oParams)
        End Function
        
        Public Function SetProfileFBML(uid, fbml)
            Dim oParams
            Set oParams = Server.CreateObject("Scripting.Dictionary")
            oParams.Add "markup", fbml
            If (Not IsNull(uid)) Then oParams.Add "uid", uid
            Set SetProfileFBML = CallApiMethod("facebook.profile.setFBML", oParams)
        End Function
        
        Function FQLQuery(query)
            Dim oParams
            Set oParams = Server.CreateObject("Scripting.Dictionary")
            oParams.Add "query", query
            Set FQLQuery = CallApiMethod("facebook.fql.query", oParams)
        End Function
        
        Public Sub IncludeCSS(strPath)
            Dim oFSO
            Set oFSO = Server.CreateObject("Scripting.FileSystemObject")
            If (oFSO.FileExists(Server.MapPath(strPath))) Then
                Dim oFile
                Set oFile = oFSO.OpenTextFile(Server.MapPath(strPath))
                    %>
                    <style type="text/css">
                        <%= oFile.ReadAll() %>
                    </style>
                    <%
                Call oFile.Close()
            End If
        End Sub
        
        ' This property returns whether or not the request made to your page was from FaceBook
        Public Property Get RequestIsValid
            Dim strItem, oRequestParams
            Set oRequestParams = Server.CreateObject("Scripting.Dictionary")
            For Each strItem In Request.Form
                If (Left(strItem, Len(FB_PARAM_PREFIX)) = FB_PARAM_PREFIX And Not strItem = FB_PARAM_PREFIX) Then
                    oRequestParams(Mid(strItem, Len(FB_PARAM_PREFIX & "_") + 1)) = Request.Form(strItem)
                End If
            Next
            RequestIsValid = (GenerateSig(oRequestParams) = Request.Form("fb_sig"))
        End Property
        
        Public Function Form(strKey)
            If (Len(Request.Form(strKey)) > 0) Then
                Form = Request.Form(strKey)
            Else
                If (Len(Request.Form(strKey & "[0]")) > 0) Then
                    Dim arrKey()
                    Redim arrKey(0)
                    Do While Len(Request.Form(strKey & "[" & Ubound(arrKey) & "]")) > 0
                        arrKey(Ubound(arrKey)) = Request.Form(strKey & "[" & Ubound(arrKey) & "]")
                        Redim Preserve arrKey(Ubound(arrKey) + 1)
                    Loop
                    Redim Preserve arrKey(Ubound(arrKey) - 1)
                    Form = arrKey
                End If
            End If
        End Function
        
        Public Function SendNotificationRequest(to_ids, req_type, content, image, boolInvite)
            Dim oParams
            Set oParams = Server.CreateObject("Scripting.Dictionary")
            oParams.Add "to_ids", to_ids
            oParams.Add "type", req_type
            oParams.Add "content", content
            oParams.Add "image", image
            oParams.Add "invite", LCase(boolInvite)
            Set SendNotificationRequest = CallApiMethod("facebook.notifications.sendRequest", oParams)
        End Function
                
        Private Sub Class_Initialize()
            If (Len(Request(FB_PARAM_PREFIX & "_api_key")) > 0) Then ApiKey = Request(FB_PARAM_PREFIX & "_api_key")
            If (Len(Request(FB_PARAM_PREFIX & "_session_key")) > 0) Then SessionKey = Request(FB_PARAM_PREFIX & "_session_key")
        End Sub
        
        ' This generates a facebook REST uri for the passed in parameters
        Private Function GenerateRequestURI(oParams)
            If (Len(SessionKey) > 0) Then oParams("session_key") = SessionKey
            If (Len(ApiKey) > 0) Then oParams("api_key") = ApiKey
            If (Len(GetUniqueCallID()) > 0) Then oParams("call_id") = GetUniqueCallID()
            oParams("v") = FB_API_VERSION
            GenerateRequestURI = REST_URI & "?"
            Dim strItem
            For Each strItem In oParams.Keys
                GenerateRequestURI = GenerateRequestURI & strItem & "=" & Server.UrlEncode(oParams(strItem)) & "&"
            Next
            GenerateRequestURI = GenerateRequestURI & "sig=" & GenerateSig(oParams)
        End Function
        
        ' This creates a signature of the supplied parameters
        Private Function GenerateSig(oParams)
            Set oParams = SortDictionary(oParams)
            Dim strSig, strItem
            For Each strItem In oParams
                strSig = strSig & strItem & "=" & oParams(strItem)
            Next
            strSig = strSig & SecretKey
            Dim oMD5
            Set oMD5 = New MD5
            oMD5.Text = strSig
            GenerateSig = oMD5.HexMD5
        End Function
        
        ' SortDictionary function courtesy of MSDN
        Private Function SortDictionary(objDict)
            Dim strDict()
            Dim objKey
            Dim strKey,strItem
            Dim X,Y,Z
            Z = objDict.Count
            If Z > 1 Then
                ReDim strDict(Z,2)
                X = 0
                For Each objKey In objDict
                    strDict(X,1)  = CStr(objKey)
                    strDict(X,2) = CStr(objDict(objKey))
                    X = X + 1
                Next
                For X = 0 to (Z - 2)
                    For Y = X to (Z - 1)
                        If StrComp(strDict(X,1),strDict(Y,1),vbTextCompare) > 0 Then
                            strKey  = strDict(X,1)
                            strItem = strDict(X,2)
                            strDict(X,1)  = strDict(Y,1)
                            strDict(X,2) = strDict(Y,2)
                            strDict(Y,1)  = strKey
                            strDict(Y,2) = strItem
                        End If
                    Next
                Next
                objDict.RemoveAll
                For X = 0 to (Z - 1)
                    objDict.Add strDict(X,1), strDict(X,2)
                Next
            End If
            Set SortDictionary = objDict
        End Function
        
        ' Returns a unique CallID. Uses an application incrementer & a timestamp since VBScript only allows
        ' us to generate a timestamp accurate to 1 second. We may make multiple calls per second so this would not be unique!
        Private Function GetUniqueCallID()
        	If (Len(Application("FB_CallID")) = 0) Then Application("FB_CallID") = 1
        	GetUniqueCallID = TimeStamp() & Application("FB_CallID")
        	Application("FB_CallID") = Application("FB_CallID") + 1
        End Function
        
        ' Returns a timestamp accurate within 1 second
        Private Function TimeStamp()
        	TimeStamp = Year(Now()) & Month(Now()) & Day(Now()) & Hour(Now()) & Minute(Now()) & Second(Now())
        End Function
        
    End Class
    
%>

[edit] Fahrzin Hemmati

I'm new to ASP, so I may have used inefficient objects or a workaround for something I didn't know. I'm developing this as part of a company, so I'm not allowed to post the whole thing. Instead, I'm only posting what the guy below has posted, but fixed.

Changelog:

  • Uses POST instead of GET. Useful for setFBML and other non-URL-safe functions
  • Uses a newer XMLHTTP object with fewer bugs/limitations.
  • Allows multi-application use through initialize functions (class_initialize can't take parameters??)
  • GenerateRequestURI handles auth.getSession correctly
  • Helper methods to deal with XML, errors and unix time.
  • example function auth_getSession(auth_token)

You will need a whole separate class that handles other things if you want this class to be useful at all. I basically "translated" from the official PHP client into ASP, but there will be many troubles since PHP is, in my opinion, such a better language than ASP. You will hate the lack of simple_xml in ASP.

[edit] RestClient.asp

Also requires the CMD5.asp by Chris Read (http://chris.brimson-read.com.au/?page_id=7)

<!--#include file="fb-md5.asp"-->
<%


    CONST REST_URI = "http://api.facebook.com/restserver.php"
    CONST FB_PARAM_PREFIX = "fb_sig"
    
    Class FaceBookRestClient
        

	private parser
	private use_params

	'Sample function
	public function auth_getsession(auth_token)
		response.write("auth_getsession"&auth_token)

		use_params.removeall
		use_params.add "auth_token",auth_token
		result=callapimethod("facebook.auth.getSession",use_params)

		parser.loadxml(result)

		if instr(result,"error_response")<>0 then
			handle_error parser
			response.write "<br>getsession FAILED???<br>"
			set auth_getsession=nothing
		else
			set to_ret = server.createobject("scripting.dictionary")

			sessionkey=parser.documentelement.getElementsByTagName("session_key").item(0).firstchild.nodevalue

			set docu=parser.documentelement
			
			to_ret.add "session_key",node_value(docu,"session_key")
			response.write sessionkey&":::"&node_value(docu,"uid")&"<br>"
			to_ret.add "uid",node_value(docu,"uid")
			expire=node_value(docu,"expires")
			if expire=0 then
				to_ret.add "expires","never"
			else
				to_ret.add "expires",unix2asp(expire)
			end if

			set docu=nothing

			set auth_getsession=to_ret
			set to_ret=nothing
		end if
	end function
	public function unix2asp(unix)
		unix2asp = DateAdd("s", unix, "01/01/1970 00:00:00")
	end function

	private sub handle_error(rootnode)
		response.write "Error "&node_value(rootnode,"error_code")&": "&node_value(rootnode,"error_msg")&"<br>"
	end sub

	private function node_value(rootnode,tagname)
		node_value=rootnode.getElementsByTagName(tagname).item(0).firstchild.nodevalue
	end function

        Public ApiKey
        Public SessionKey
        Public SecretKey
        
        ' This allows you to call a facebook method (e.g. facebook.auth.getSession) with the specified parameters
        ' You do not need to pass in the following parameters as they are appended automatically,
        '   - session_key
        '   - api_key
        '   - call_id
        '   - v
        Public Function CallApiMethod( strMethod, oParams )
            oParams( "method" ) = strMethod
            Dim oXMLHTTP
            Set oXMLHTTP = Server.CreateObject( "MSXML2.ServerXMLHTTP" )
            oXMLHTTP.Open "POST", REST_URI, False, "", ""
		 oXMLHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
            oXMLHTTP.Send(GenerateRequestURI( oParams))
            CallApiMethod = oXMLHTTP.ResponseText
            Set oXMLHTTP = Nothing
        End Function
        
        ' This property returns whether or not the request made to your page was from FaceBook
        Public Property Get RequestIsValid
            Dim strItem, oRequestParams
            Set oRequestParams = Server.CreateObject( "Scripting.Dictionary" )
            For Each strItem In Request.Form
                If ( Left( strItem, Len( FB_PARAM_PREFIX ) ) = FB_PARAM_PREFIX And Not strItem = FB_PARAM_PREFIX ) Then
                    oRequestParams( Mid( strItem, Len( FB_PARAM_PREFIX & "_" ) + 1 ) ) = Request.Form( strItem )
                End If
            Next
            RequestIsValid = ( GenerateSig( oRequestParams ) = Request.Form( "fb_sig" ) )
	    set oRequestParams = nothing
        End Property
        
        'Call for initializing
        Public Sub Initialize(api_key,secret_key)
		ApiKey		=	api_key
		SecretKey	=	secret_key
        End Sub

        Public Sub Initialize2(api_key,secret_key,session_key)
		ApiKey		=	api_key
		SecretKey	=	secret_key
		SessionKey	=	session_key
        End Sub

	Private Sub Class_Initialize()
		set parser  = Server.CreateObject("Microsoft.XMLDOM")
		set use_params = server.createobject("Scripting.Dictionary")
	end sub
	
	private sub Class_Terminate()
		set parser = nothing
		set use_params = nothing
	end sub
        
        ' Creates the content for a POST to the REST server
        Private Function GenerateRequestURI( oParams )
        	If ( Len( Application( "FB_CallID" ) ) = 0 ) Then Application( "FB_CallID" ) = 100005
                'For auth.getSession (only function to not use session_key?)
		if oParams("session_key")="none" then
			oParams.remove "session_key"
		else
			oParams( "session_key" ) = SessionKey
		end if
            oParams( "api_key" ) = ApiKey
            oParams( "call_id" ) = Application( "FB_CallID" )
            oParams( "v" ) = "1.0"
            'This is useless for POSTs.
'            GenerateRequestURI = REST_URI & "?"
            Dim strItem
            For Each strItem In oParams.Keys
                GenerateRequestURI = GenerateRequestURI & strItem & "=" & Server.UrlEncode(oParams(strItem)) & "&"
            Next
            GenerateRequestURI = GenerateRequestURI & "sig=" & GenerateSig( oParams )
            Application( "FB_CallID" ) = Application( "FB_CallID" ) + 205
        End Function
        
        ' This creates an signature of the supplied parameters
        Private Function GenerateSig( oParams )
            Set oParams = SortDictionary( oParams )
            Dim strSig, strItem
            For Each strItem In oParams
                strSig = strSig & strItem & "=" & oParams( strItem )
            Next
            strSig = strSig & SecretKey
            Dim oMD5
            Set oMD5 = New MD5
            oMD5.Text = strSig
            GenerateSig = oMD5.HexMD5
        End Function

	'Wrapper of generatesig for cookies
	public function generatesig_cookies(cookies)
		set dict=server.createobject("scripting.dictionary")
		for each item in cookies
			dict.add item,cookies(item)
		next
		generatesig_cookies=generatesig(dict)
		set dict=nothing
	end function
        
        ' SortDictionary function courtesy of MSDN
        Private Function SortDictionary(objDict)
            Dim strDict()
            Dim objKey
            Dim strKey,strItem
            Dim X,Y,Z
            Z = objDict.Count
            If Z > 1 Then
                ReDim strDict(Z,2)
                X = 0
                For Each objKey In objDict
                    strDict(X,1)  = CStr(objKey)
                    strDict(X,2) = CStr(objDict(objKey))
                    X = X + 1
                Next
                For X = 0 to (Z - 2)
                    For Y = X to (Z - 1)
                        If StrComp(strDict(X,1),strDict(Y,1),vbTextCompare) > 0 Then
                            strKey  = strDict(X,1)
                            strItem = strDict(X,2)
                            strDict(X,1)  = strDict(Y,1)
                            strDict(X,2) = strDict(Y,2)
                            strDict(Y,1)  = strKey
                            strDict(Y,2) = strItem
                        End If
                    Next
                Next
                objDict.RemoveAll
                For X = 0 to (Z - 1)
                    objDict.Add strDict(X,1), strDict(X,2)
                Next
            End If
            Set SortDictionary = objDict
        End Function
        
    End Class
    
%>