human growth hormone

So I’ve been meaning to allow users to donate to my site using PayPal, and I wanted to keep track of who donated and for how much. It all seemed very complicated until Doug Boude came along and wrote this blog: http://www.dougboude.com/blog/1/2009/11/PayPal-IPN-Coldfusion-CFC.cfm

(Thanks Doug!).  Doug wrote some very cool code which helps communicate with PayPal after someone pays or donates money to you.

The code works great, but it assumes that you have a record in already created in your database which then passes a unique id of the record you wish to update.  PayPal takes that id and updates the table with the information of the transaction using IPN.

My problem existed when I tried to insert a record, THEN pass the id of that record to PayPal all within the push of 1 button.

When I used cfhttp to post to PayPal, it would post to a blank page. It would never actually make it to PayPal.

I could not get cfhttp to work or a simple cflocation.  So, with the help of Julian Gautier, we came up with a Jquery solution.  Here is what we came up with:

 

First. Create a CFC to handle the insert.

A few things to note within the cfc. Notice I have access set to “remote” and I am returning the format in json. this will make more sense when you see the jquery and ajax call. Return a structure that tells us if the insert was a success or a failure.

The name of my CFC is: paypalcall.cfc

1.     <cfcomponent hint=“update paypal table”>

2.     <cffunction name=“ppCreateRecord” access=“remote” output=“false” returnFormat=“json” returntype=“struct”>

3.     <cfargument name=“userid” type=“numeric” required=“yes”>

4.     <cfargument name=“firstname” type=“string” required=“yes”>

5.     <cfargument name=“lastname” type=“string” required=“yes”>

6.     <cfset returnStruct = {}>

7.     <cfset returnStruct.success = true>

8.     <cftry>

9.     <cfquery datasource=“#application.dsn#”>

10.   INSERT INTO Paypal (UserID, FirstName, LastName)

11.   VALUES(#arguments.userid#, ‘#arguments.firstname#‘, ‘#arguments.lastname#‘)

12.   </cfquery>

13.   <cfquery name=“qryPaypal” datasource=“#application.dsn#”>

14.   SELECT MAX(ID) AS PK_ID

15.   FROM tablePaypal

16.   </cfquery>

17.   <cfset returnStruct.pk = qryPaypal.PK_ID>

18.   <cfcatch>

19.   <cfset returnStruct.success = false>

20.   </cfcatch>

21.   </cftry>

22.   <cfreturn returnStruct>

23.   </cffunction>

24.   </cfcomponent>

Next, on the page which you wish to have your donate / pay button.

At the top of the page, include your cfajaxproxy call:

(Assuming you put your cfc in the same folder as your cfm file)

Notice that we are using a jsclassname, this is so we can tie the cfajaxproxy call to jquery.

<cfajaxproxy cfc=“paypalcall” jsclassname=“cfPaypal”>

 

 

Next, make sure that Jquery is loaded. For more info on how to load jquery, go here: http://www.jquery.com/

 

1.     <cfsavecontent variable=“jquery”>

2.     <script type=“text/javascript” src=“guru_includes/jquery.js” />

3.     </cfsavecontent>

4.     <cfhtmlhead text=“#jquery#”>

 

Next, let’s write the jquery to handle the cfajax call:

The first line creates a variable which ties the cfajaxproxy call together. Now if we want to execute a method within our cfc,

We just need to write it like this:

tblPaypal.ppCreateRecord(<cfoutput>#qryInfo.userid#</cfoutput>,<cfoutput>‘#qryInfo.FirstName#’</cfoutput>,
<cfoutput>
‘#qryInfo.LastName#’</cfoutput>);

That line would call our ppCreateRecord method in our cfc and pass it the arguments that it needs to insert a record.

tblPaypal.setCallbackHandler(payPalCallBack);
And
tblPaypal.
setErrorHandler(payPallError);

These two lines are built in cfajaxproxy functions that handle what happens when the cfc returns from being called.

The tblPaypal.setErrorHandler(payPallError); line will not be called unless there is an error that happens in our cfc or within our cfajaxproxy call.

An important line of code that cannot be missed is the last line:
$
(window).load(pageInit);

This line runs the pageInit function as soon as all the elements are rendered on the page.

When it is called, it adds a click event to our PayPal submit button, that way the cfc insert call is made prior to post to paypal.

(*Something to note, in this line of code: var tblPaypal=new cfPaypal();   be sure to NOT name the variable the same name as your cfajaxproxy variable name. This creates a conflict only in IE. To avoid this, just make sure they are different names.)

1.     <cfsavecontent variable=“jquery_paypal”>

2.     <script>

3.     var tblPaypal=new cfPaypal();

4.      

5.     function pageInit()

6.     {

7.     $(“#btnPaypalSubmit”).click(btnPaypalSubmitClick);

8.     tblPaypal.setCallbackHandler(payPalCallBack);

9.     tblPaypal.setErrorHandler(payPallError);

10.   }

11.   function btnPaypalSubmitClick()

12.   {

13.   <!— qryInfo.userid, qryInfo.firstname, qryInfo.lastname are assuming you have a logged in user and you have the users id, first and last name to pass to paypal. —>

14.   tblPaypal.ppCreateRecord(<cfoutput>#qryInfo.userid#</cfoutput>,<cfoutput>‘#qryInfo.FirstName#’</cfoutput>,
<cfoutput>
‘#qryInfo.LastName#’</cfoutput>);

15.   }

16.   function payPalCallBack(json)

17.   {

18.   alert(json);

19.   if(json.SUCCESS)

20.   {

21.   $(“#custom”).val(json.PK);

22.   $(“#frmPost”).submit();

23.   }

24.   else

25.   {

26.   alert(“Error while making ajax call”);

27.   }

28.   }

29.   function payPallError()

30.   {

31.   alert(“error while making ajax call”);

32.   }

33.   $(window).load(pageInit);

34.   </script>

35.   </cfsavecontent>

36.   <cfhtmlhead text=“#jquery_paypal#”/>

Last but not least… We just need to add the form that PayPal gave us:

Let’s make sure we give the button an id=”btnPaypalSubmit” that way we can select it in jquery.

1.     <cfoutput>

2.     <form action=“https://www.paypal.com/cgi-bin/webscr” id=“frmPost” method=“post” name=“frmPost”>

3.     <input type=“hidden” name=“payment_status” value=“completed” />

4.     <input type=“hidden” name=“mc_gross” value=“.01″ />

5.     <input type=“hidden” name=“custom” id=“custom” value=“3″ />

6.     <input type=“hidden” name=“cmd” value=“_s-xclick”>

7.     <input type=“hidden” name=“hosted_button_id” value=“9337626″>

8.     <input type=“button” border=“0″ id=“btnPaypalSubmit” name=“GoPaypal” value=“submit” alt=“PayPal - The safer, easier way to pay online!”>

9.     </form>

10.   </cfoutput>

 
Again, many thanks to Julian Gautier and Doug Boude.

 

DEMO

Download Code

So once upon a time, I had an idea that it would be cool to run a little personal website that was only to be used by my friends.  This website was to have a number of NFL football games that you could pick from and then if you guessed the most right, you win.

Sounds very simple right?  WRONG! I ran into a HUGE roadblock. I first built the site so I could input the games that you could pick from manually, then after the games were over, I would have to input the scores manually. Seeing how this gets very annoying, I wanted to incorporate some live scoring.

I tried to find a free xml feed, however, this was not the case. I spent at least a month searching to find a feed that I could use for my site. I thought about html scraping, but that seemed tedious, a lot of work and if their site changed, I would have to change my code. That idea was no good.

So I decided that I would pay for it.  I mean how much could a NFL scores feed really cost right? Wow, I couldn’t have been more wrong!

I called Stats.inc and after 2 weeks of me explaining that I wanted the cheapest form of scores and that I was a non-profit website, they gave me a quote of $40,000. 

Yes… I said $40,000 to get a feed that will save me 5 minutes inputting my own scores.

So, I decided to not spend the price of a brand new Lexus on 5 minutes of score inputting and continue my search for a free feed.

After a year of occasionally looking, my buddy stumbled upon something that was actually useful.
(He gave me only the direct url, so I don’t know the site or forum where he found it. sorry)

Here is what he found: http://sports.espn.go.com/nfl/bottomline/scores

An ESPN link that has only the output of a url string, which inside of the url string are LIVE SCORES!

My first question was why the hell does ESPN have a link that just produces a url string and nothing else.

So I decided to investigate a little further.  I found that if you strip the directories, you get: http://sports.espn.go.com

Which is a desktop application used by ESPN to install a sports ticker on your computer. This application sends http requests to ESPN to update the ticker which is installed on your computer.  So if there is a nfl url link, then there must others right?

Right! 

I installed the ticker, and then used a packet sniffer to grab all the http requests being sent from my computer. It revealed all of the url strings being used by ESPN to update the ticker.

 

http://sports.espn.go.com/nfl/bottomline/scores

http://sports.espn.go.com/nba/bottomline/scores

http://sports.espn.go.com/mlb/bottomline/scores

http://sports.espn.go.com/ncf/bottomline/scores

http://sports.espn.go.com/rpm/bottomline/race

http://sports.espn.go.com/sports/golf/bottomLineGolfLeaderboard

http://sports.espn.go.com/wnba/bottomline/scores

http://sports.espn.go.com/espn/bottomline/news

 

So now I have:

1. Consistency. ESPN uses the url string to update their application, therefore there should be little if no code changes that will be needed after I initially write the code to extract the scores.

2. FREE! I get to spend $40,000 somewhere else.

3. Accurate Scores. Since the feed is coming from ESPN and not a 3rd party site that might go down or put in bad scores, I feel good about this one.

4. Easier project. Parse a url string? Wayyy better than html scraping, or any other horrible method to extract the data.

(I would like to thank Steve Weyrick CFBLOGWORM for working on this project as well)

 

So for reason 1-4, I wrote this code. ENJOY!

 

 
 

 

 

Keep in mind that if you come across this blog while the NFL is in the off season, you will not see the scores on the demo because the scores are live J

Here is a DEMO of the application if you would like to see the finished product:
Flex 3 Insert Record into a Database using Remote Object CFC ColdFusion

Here is how to setup and insert a record into a database using Flex 3 with Remote Object / Flash Remoting with ColdFusion CFC.

Here is my Remote Object:
<mx:RemoteObject id=”mycfc

                 destination=”ColdFusion

                 showBusyCursor=”true

                 source=”cfctest.thecfc

                 result=”result(event)”

                 fault=”fault(event)”>
<mx:method name=”insertrecord” result=”confirminsert(event)”/>

</mx:RemoteObject>

 I want to setup a method that will allow me to insert a record into the database.  In my CFC, I have a function called insertrecordthat simply inserts a record:

<cffunction name=“insertrecord” access=“remote” returntype=“void”>

      <cfargument name=“FirstName” type=“string” required=“Yes”>

      <cfargument name=“LastName” type=“string” required=“Yes”>

    <cfquery datasource=“mysqlcf_flexdemo”>

INSERT INTO tblTest (tstFirstName, tstLastName)

      VALUES

(<cfqueryparam value=“#arguments.FirstName#” cfsqltype=“cf_sql_varchar”>,

 <cfqueryparam value=“#arguments.LastName#” cfsqltype=“cf_sql_varchar”>)     

    </cfquery>

  <cfreturn>

 </cffunction>

 I then setup a function in ActionScript called “confirminsert” which will be my result of my method within my remote object.  Within “confirminsert”, I am going to pass the event. This function will get called after the Insert has taken place.

private function confirminsert(evt:ResultEvent):void

{

Alert.show(txtFirstName.text + ” “ + txtLastName.text + ” was inserted into the database”, “Insert Successful”);

     txtFirstName.text = “”;

     txtLastName.text = “”;

      mycfc.recordcount();

}

 

Before the confirminsert function gets ran, I like to setup a startinsert function that will do some error handling for us. This is the first function that will get called from the actual insert button. It first looks to make sure that both input boxes are not blank and if they are not blank, then initiate the insert by calling:

mycfc.insertrecord(txtFirstName.text,txtLastName.text); This line will actually insert the record, when this is called, the insert takes place and then the result is then run from our “confirminsert” function.

The errorString can be placed on any object and can give an instruction as to why the insert failed. If the insert was successful, then we need to clear the errorString by using txtFirstName.errorString = ‘ ‘; syntax.

private function startinsert(evt:Event):void

{

if (txtFirstName.text != “” && txtLastName.text != “”)

// All statements inside { } are guarded by IF.

           {

            mycfc.insertrecord(txtFirstName.text,txtLastName.text);

            txtFirstName.errorString = ;

            txtLastName.errorString = ;

            }

      else

            {

 Alert.show(“check to make sure you have entered both the first AND the last name”);

 txtFirstName.errorString = “First Name Cannot be Left Blank”;

 txtLastName.errorString = “Last Name Cannot be Left Blank”;

            }

}


Lastly, create first name and last name input boxes and a button with a click event calling the “startinsert(event)” function that we’ve already created.

 

<mx:HBox width=”100%” horizontalAlign=”center>

     <mx:Label text=”First Name:/>

     <mx:TextInput id=”txtFirstName/>

</mx:HBox>

<mx:HBox width=”100%” horizontalAlign=”center>

     <mx:Label text=”Last Name:/>

     <mx:TextInput id=”txtLastName/>

</mx:HBox>

<mx:HBox width=”100%” horizontalAlign=”center>

<mx:Button label=”Insert Name” id=”btninsert

           click=”startinsert(event)”/>

</mx:HBox>

 

 

Here is a DEMO of the application if you would like to see the finished product:
Flex 3 Insert Record into a Database using Remote Object CFC ColdFusion

DOWNLOAD files here:
CFC     - Download
Flex     - Download

On my blog on www.cftips.net, I created a simple cfc and connected it with a standard cfm form page. You can see my original blog here.  All it did was demonstrate how get data from a cfc using the standard cfinvoke. The tiny app allowed you to type a last name into an inputbox, then it returned the first name associated with it in the database. 

I’ve since then been asked the questions:

Can you give me an example of how to integrate this simple .CFC file into a Flex app?

Also, what happens with your app when there are two different people with the same last name? How do you handle that?

So here is the answer to those questions:

Here is the DEMO of the application if you would like to see the finished product.

First off, I have a cfc named: “thecfc.cfc”

<cfcomponent>
<cffunction name=”ReturnFirstName” access=”remote” returntype=”query” hint=”This will return the first name when passed a last name”>
 <cfargument name=”LastName” type=”string” required=”Yes”>
 <cfset var get_employees_first_name = “”>
    <CFQUERY name=”get_employees_first_name” datasource=”dsnTest”>
            select tstFirstName
            from tblTest
            where tstLastName = ‘#arguments.LastName#’
    </CFQUERY>
  <CFRETURN get_employees_first_name>
 </cffunction>

<cffunction name=”returnallnames” access=”remote” returntype=”query”>
      <cfset var qryReturn = “”>
      <cfquery name=”allnames” datasource=”dsnTest”>
               SELECT tstID, tstFirstName, tstLastName
                 FROM tblTest
      </cfquery>
<cfreturn allnames>
</cffunction>
</cfcomponent>

Next, I created a Flex 3 project and named my MXML file name: cfcFirstLastNameProject.mxml

I right clicked on the src folder and imported the cfc to Flex.

 

I then created an hbox so it lines up nice, an inputbox, a datagrid, and 2 buttons:

<mx:HBox width=”80%” horizontalAlign=”center>

      <mx:Label text=”Type Last Name Here/>

</mx:HBox>

<mx:HBox width=”100%” horizontalAlign=”center>

      <mx:Label text=”Last Name:/>

      <mx:TextInput id=”txtLastName/>

</mx:HBox>

<mx:DataGrid id=”mygrid” width=”487” height=”50%/>

     

<mx:Button label=”Get All Names” id=”btnAllNames/>

<mx:Button label=”Get First Name” id=”btnLastName/>

 

I created my remote object giving it an ID of mycfc with the source pointing to the cfc from the root folder with the destination equal to ColdFusion (case sensitive). Also I create the result and fault functions which I will setup next:

 

<mx:RemoteObject id=”mycfc

                  destination=”ColdFusion

                  showBusyCursor=”true

                  source=”cfctest.thecfc

                  result=”result(event)”

                  fault=”fault(event)”>

</mx:RemoteObject>

Since I set my result and fault functions in my remote object I have to create the functions that will handle what happens when the data comes back from the cfc. In the Result handler function, I set the id of my datagrid, which is “mygrid”.dataProvider Equal to the event result of the cfc, which is the return data coming back from the cfc. I also setup a fault handler function in case we have an error. That way if there is an error, we can see what the error is placed nicely in an alert box. Here is the script statements:

<mx:Script>

      <![CDATA[

            import mx.controls.Alert;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.Fault;

            import mx.rpc.events.ResultEvent;

            private function result(evt:ResultEvent):void {

                  mygrid.dataProvider = evt.result;

            }

            private function fault(evt:FaultEvent):void {

                  Alert.show(evt.fault.message);                 

            }

      ]]>

</mx:Script>

In my cfc, I have 2 functions. One that will simply return all the names in the database and I have named that function: returnallnames

The second function I created in my cfc is going to accept one argument, which is going to be a last name, and then it returns the first name associated with it. I named that function: “ReturnFirstName”

Now that I have my result and fault functions setup to handle the return data from the cfc, I can now set my buttons have click events which will send the data to the cfc. This is accomplished by calling the remote object which mine has the ID of “mycfc” then using dot notation, calling the cfc function named “returnallnames()”. That should take care of the first function and with the second button, I use the same syntax, “mycfc” dot notation then the name of the function in the cfc, “ReturnFirstName” followed by the argument that I want to pass, which is what you typed in the inputbox, “txtLastName.text”:

<mx:Button label=”Get All Names” id=”btnAllNames” click=”mycfc.returnallnames()”/>

 

<mx:Button label=”Get First Name” id=”btnLastName” click=”mycfc.ReturnFirstName(txtLastName.text)”/>

Now that I’m displaying the data in a datagrid, if there is 2 First Names associated with a last name, then both first names will show up in the datagrid.

That’s all there is to it!

I’ve added All the code for you to download and use if you’d like.

Heres what the entire Flex 3 code looks like:


<?xml version=”1.0″ encoding=”utf-8″?>

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical” verticalAlign=”top” xmlns:local=”*>

     

      <mx:Script>

      <![CDATA[

            import mx.controls.Alert;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.Fault;

            import mx.rpc.events.ResultEvent;

            private function result(evt:ResultEvent):void {

                  mygrid.dataProvider = evt.result;

            }

            private function fault(evt:FaultEvent):void {

                  Alert.show(evt.fault.message);                 

            }

      ]]>

      </mx:Script>

 

<mx:RemoteObject id=”mycfc

                         destination=”ColdFusion

                         showBusyCursor=”true

                         source=”cfctest.thecfc

                         result=”result(event)”

                         fault=”fault(event)”>

</mx:RemoteObject>

      <mx:HBox width=”80%” horizontalAlign=”center>

            <mx:Label text=”Type Last Name Here/>

      </mx:HBox>

      <mx:HBox width=”100%” horizontalAlign=”center>

            <mx:Label text=”Last Name:/>

            <mx:TextInput id=”txtLastName/>

      </mx:HBox>

      <mx:DataGrid id=”mygrid” width=”487” height=”50%/>

     

     

      <mx:Button label=”Get All Names” id=”btnAllNames” click=”mycfc.returnallnames()”/>

      <mx:Button label=”Get First Name” id=”btnLastName” click=”mycfc.ReturnFirstName(txtLastName.text)”/>

</mx:Application>

 

Download Files here:
CFC          - Download
Flex          - Download
Database - Download

Here is the DEMO of the application if you would like to see the finished product.

{literal} {/literal}