18 Replies Latest reply on Oct 20, 2008 10:14 AM by Steve Sommers

    LOOP Credit Card Transactions

    cwmcguire
      I am needing to know how to CFLOOP multiple transactions with Authorize.net.

      When sending a order request to authorize.net, it returns a response - that response is recorded with the order.

      I can loop multiple transactions - what I cant figure out, is how to loop multiple transactions and still capture the response and record it to the db then go to the next transaction. When I just do a CFLOOP around the transaction code - it processes each order one after the other, but will not record the response.

      Here is the order of events:

      1. Db with customer info and order
      2. Send customer/order to authorize.net
      3. Receive response from authorize.net
      4. Record response to customer/order data in Db
      5. Next record repeat 2-4

      This would be great for re-occurring billing as well!

      I hope someone has some insight on this.
        • 1. Re: LOOP Credit Card Transactions
          cwmcguire Level 1
          Anyone have any suggestions...
          • 2. Re: LOOP Credit Card Transactions
            pijoogle
            When you run this, does it update any records at all?
            • 3. Re: LOOP Credit Card Transactions
              fober1 Level 1
              Where does the variable api_response come from?
              <CFSET code = ListGetAt(api_response,1)>

              Should you not use cfhttp.fileContent instead?
              <CFSET code = ListGetAt(cfhttp.fileContent,1)>

              cheers,
              fober
              • 4. Re: LOOP Credit Card Transactions
                cwmcguire Level 1
                It does not update any record, it continues on to the next record and proceeds to charge account thru authorize.net until it has gone thru all records.

                Because authorize.net is posting a server response back to that same page, that page is not capturing the response before it goes to the next record.

                Is there some way to pause the loop to catch the response from authorize.net, record the response, then move to the next record?

                The api_response is coming from this line of code:

                <cfset api_response=cfhttp.fileContent>

                That was omitted by accident when I posted this thread. Sorry.
                • 5. Re: LOOP Credit Card Transactions
                  fober1 Level 1
                  Hi,

                  to see the server response just output the "cfhttp.fileContent" variable, and cfabort at the end of the loop to keep the display on the screen.

                  cheers,
                  fober


                  <CFQUERY NAME=order>
                  </CFQUERY>
                  <CFOUTPUT>
                  <CFLOOP QUERY=order>
                  <cfhttp method="POST" url="authorize.net">
                  <cfhttpparam type="formfield" name="x_last_name" value="#lastname#">
                  <cfhttpparam type="formfield" name="x_card_num" value="#cardnumber#">
                  <cfhttpparam type="formfield" name="x_amount" value="#amount#">
                  <cfhttpparam type="formfield" name="x_card_code" value="#cvv#">
                  <cfhttpparam type="formfield" name="x_exp_date" value="#exp#">
                  <cfhttpparam type="formfield" name="x_method" value="CC">
                  <cfhttpparam type="formfield" value="AUTH_CAPTURE" name="x_type">
                  </cfhttp>

                  <hr>
                  [#cfhttp.fileContent#]

                  <CFSET code = ListGetAt(api_response,1)>
                  <CFIF code EQ 1>
                  <CFSET trans = "approved">
                  <CFSET transid = ListGetAt(api_response,7)>
                  <CFSET errortext = ListGetAt(api_response,4)>
                  </CFIF>
                  <CFIF code EQ 2>
                  <CFSET trans = "declined">
                  <CFSET transid = 0>
                  <CFSET errortext = ListGetAt(api_response,4)>
                  </CFIF>
                  <CFIF code EQ 3>
                  <CFSET trans = "error">
                  <CFSET transid = 0>
                  <CFSET errortext = ListGetAt(api_response,4)>
                  </CFIF>

                  <CFQUERY NAME=recordresponse>
                  UPDATE table
                  SET transid=#transid#,trans='#trans#',errortext='#errortext#',processdate='#processdate#'
                  WHERE id=#id#
                  </CFQUERY>

                  </CFLOOP>
                  <cfabort>
                  </CFOUTPUT>
                  • 6. Re: LOOP Credit Card Transactions
                    cwmcguire Level 1
                    That is not what I am trying to accomplish...CFABORT is CF 101...

                    I am wanting to record responses to the table for each transaction ran - it is not doing that. It is running each transaction without pausing to record the response with the CFLOOP. I i do each transaction individually, it works fine.

                    Any solution to this issue?
                    • 7. Re: LOOP Credit Card Transactions
                      Level 7
                      >
                      > Is there some way to pause the loop to catch the response from authorize.net,
                      > record the response, then move to the next record?
                      >

                      Yes, but there is a bit of a question on how to time the pause.

                      The most brute force method would be to simple put the thread to sleep
                      for a hard coded amount of time. Either with the <cfseep...> tag if you
                      are on a newer version or the older java.thread.sleep() object
                      otherwise. If you are pre-mx then a loop is the best idea I can provide.

                      A better idea would be some type of pause that waits for the response
                      from the request, but I am not sure how to do that.
                      • 8. Re: LOOP Credit Card Transactions
                        cwmcguire Level 1
                        Im using CF8

                        Will a CFSLEEP tag allow the server response to come back, write to a table, and move on to the next record automatically?

                        Never heard of CFSLEEP or know how it works...
                        • 9. Re: LOOP Credit Card Transactions
                          Level 7
                          cwmcguire wrote:
                          > Im using CF8
                          >
                          > Will a CFSLEEP tag allow the server response to come back, write to a table, and move on to the next record automatically?
                          >
                          > Never heard of CFSLEEP or know how it works...

                          Sorry, added in CF 8 is a sleep() function, not <cfsleep...> tag.

                          Sleep

                          Description

                          Causes the current thread to stop processing for a specified period of time.

                          Returns

                          Does not return a value.

                          Anyways, yes this will cause the current thread to pause for a certain
                          amount of time before it continues to process. Putting this after your
                          <cfhttp...> tag should give that task time to finish before the
                          execution continues.

                          You may also want to try adding a timeout parameter to the <cfhttp...>
                          tag itself. I don't know if that would change the behavior or not.


                          • 10. LOOP Credit Card Transactions
                            -==cfSearching==- Level 4
                            cwmcguire wrote:
                            > When I just do a CFLOOP around the transaction code - it processes
                            > each order one after the other, but will not record the response.

                            Perhaps I am misunderstanding, but it sounds a bit odd that the cfhttp calls themselves are succeeding but nothing happens with the database .. at all. Not even an error?

                            A) Did you try supplying a timeout. According to the documentation, CF can be made to wait indefinitely with the correct settings

                            http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_g-h_09.html

                            B) Did you log the cfhttp results within the loop to see what is actually happening.

                            • 11. Re: LOOP Credit Card Transactions
                              cwmcguire Level 1
                              The timout is not the problem with the CFHTTP - everyone is overlooking the problem.

                              The problem is, the server is sending a response back to the same page that is suppose to be looping thru multiple records making multiple transactions.

                              How could I run a transaction, receive a response, post the response to the table, then go to the next record needed to be processed, and run that transactions, receive a response...etc..etc...

                              This is the problem....
                              • 12. LOOP Credit Card Transactions
                                -==cfSearching==- Level 4
                                cwmcguire wrote:
                                > The timout is not the problem with the CFHTTP -
                                > everyone is overlooking the problem.

                                Did you try it?

                                > It does not update any record, ...
                                > Because authorize.net is posting a server response back to that same page, that
                                > page is not capturing the response before it goes to the next record.

                                There are other reasons an update might not occur. Some of which have nothing to do with cfhttp. For example if the #id# is invalid, the query might execute but nothing would be updated because no matching records were found.

                                You have dismissed some of the suggestions, without saying what other tests you have performed and what results led you to this conclusion. Beyond the fact that you say no updates are occurring, how else have you confirmed that the response is not being captured correctly?
                                • 13. Re: LOOP Credit Card Transactions
                                  cwmcguire Level 1
                                  >>You have dismissed some of the suggestions, without saying what other tests you have performed and what results led you to this conclusion. Beyond the fact that you say no updates are occurring, how else have you confirmed that the response is not being captured correctly?
                                  <<

                                  Because the code works when you take the CFLOOP out of the equation. You put the CFLOOP in place, and no longer does the page take back the server response, it keeps looping thru all the records til its done.
                                  • 14. LOOP Credit Card Transactions
                                    -==cfSearching==- Level 4
                                    > Because the code works when you take the CFLOOP out of the equation. You put
                                    > the CFLOOP in place, and no longer does the page take back the server response,
                                    > it keeps looping thru all the records til its done.

                                    If you take the loop out of the equation, you are likely using different values for both the cfhttp call and the query. So that still does not rule out something as simple as a different or wrong #id#.

                                    1. When you say the transactions are "processed", what does that mean? Are you dumping the cfhttp results within the loop to confirm this, or are you assuming it was successful because no error is thrown?

                                    2. How have you debugged the query - by dumping or logging the "results" within the loop? Does the result structure even exist after the cfquery? If it does check the recordCount, sql, etcetera.

                                    While I cannot prove the response is _not_ the problem, I do not think removing the loop alone is enough to conclusively prove that it _is_ the problem. There are other variables. You can certainly add a simple thread.sleep() call to the page, and see what happens. However, if the response handling is not the problem thread.sleep() will not fix anything.
                                    • 15. Re: LOOP Credit Card Transactions
                                      cwmcguire Level 1
                                      I am not using different variables. If I take the CFLOOP out of the code above, it works perfect. I use that code close to 50 times a day. I know it works perfect. When I put a CFLOOP around the code, the transactions are still being charged, that part is working fine, but the server response is not being recorded to the table BEFORE the next record is submitted to the CFHTTP.

                                      >> when you say the transactions are processed.... <<

                                      This means the credit card from a record in the table was submitted to authorize.net for authorization, a response comes back from authorize.net thru CFHTTP, I capture the response with the filecontent of CFHTTP, and record it to the table.

                                      The problem is not CFHTTP not having enough time to process the request, that is working fine. The problem is the fileconent coming back to the same page looping records is not being captured and recorded in the table, it just runs straight thru the records queried.
                                      • 16. LOOP Credit Card Transactions
                                        -==cfSearching==- Level 4
                                        > but the server response is not being recorded to the table BEFORE the next record is submitted to the CFHTTP.

                                        I understand that is what _appears_ to be happening, but from what you have described it does not sound like you have actually debugged / logged the timing and chain of events to substantiate this.

                                        1. Log time cfhttp call starts
                                        2. Log time and response from cfhttp call
                                        3. Log time before cfquery starts
                                        4. Log time and cfquery "results" after cfquery tag

                                        While it may still be related to cfhttp, what you are describing sounds very "off". So I would be looking at a simpler causes first.

                                        As I understand it, cfhttp calls are synchronous. So my expectation would be that if the cfhttp did not have time to finish processing, the cffhtp.fileContent would indicate a timeout error. The database query would still execute within each loop. But the variables used (trans, transid, etcetera) might not be set with the correct values. So while the UPDATE would still occur, the column values might be set to empty strings. That is different than saying the response is not being recorded in the database after each call. Something is being recorded, it is just not the correct information. Again, that would be my _expectation_. It would need to proven or disproven with some basic debugging and logging.

                                        (BTW, I am assuming you did not post the full CFIF code above and actually have other conditions to handle cases where an invalid or missing reponse #code# was detected. Otherwise, CF would probably throw an exception anytime something unexpected happened with cfhttp call or response)

                                        But as mentioned before, you can always add a simple thread.sleep() call to your code and see what happens..
                                        http://www.anujgakhar.com/2008/01/23/different-ways-of-making-a-thread-sleep/
                                        • 17. Re: LOOP Credit Card Transactions
                                          fober1 Level 1
                                          Hi,

                                          You already explained that without the loop it works, but with the loop it doesn't. To resolve the issue we cannot always come back to this point.

                                          There are two tasks within your loop:
                                          - the http request
                                          - the DB update.
                                          To find out which one of these is the problem, run the code with the dump of the cfhttp.fileContent variable and the cfabort.
                                          If the displayed results are fine then we know the http request is not the problem, and we need to look into the DB part.

                                          If the http request is the problem then you may want to have a look at the timeout attribute.
                                          Since you are using CF8, you can also look into opening a new tread for each autorize.net transaction.

                                          If the application allows it then you may also be able to work asyncronous, that means you have one script that dumps all autorize transactions into the DB, but you have a separate script that is scheduled, and processes these transactions one by one.

                                          "CFABORT is CF 101" is certainly correct, but for "Finding Problems 101" we need some basic information from you.

                                          cheers,
                                          fober
                                          • 18. LOOP Credit Card Transactions
                                            Steve Sommers Level 4
                                            Based on your last findings, to me the problem appears to be a scoping issue. This is a problem with embedded loops in ColdFusion and if CFHTTP internally uses a loop, the problem may be propagating in this example. There are several ways to solve the issue, the simpliest being to specify the scope: orders.xxx or cfhttp.xxx. Another way to fix it would be to remove the CFHTTP call from your loop and put it in a CFC or external CF tag.

                                            Hope this helps.