Forums

PayPal Listener

dyoungers 22 Jul, 2011
I've been able to implement a form that works with PayPal standard based on the posts here but now I'd like to add code to handle the IPN callback so I can verify that the payment was processed successfully. I've handled IPN callbacks in VirtueMart so I understand what's going on here but I just need to get a sense of if/how I can use Chronoforms to process the callback.

I see an action called PayPal Listener which seems like it might be intended for this but I'm not seeing a lot of info on using it in the forums so I'm not sure if I'm right on this. If it is the right approach, if someone could point me to a simple explanation of how the PayPal Listener works I'd appreciate it.

Again, if it is intended to use with IPN, is it intended to be in a new form? or can I put it in the form used to submit the paypal transaction, i.e. does the listener detect it's being called by PayPal?

In either case, if I put fields on the form that match the IPN variables will they get populated? and can I use the DB functions to work on this fields?

Thanks!
Dave

PS. I'm using CF V4
GreyHead 23 Jul, 2011
Hi Dave,

I haven't tried this myself but this is how I think you get it to work.

On your existing form use the + Add Event icon to add a new event and give it a name like 'ppipn'. You will need to apply the fix from this post to avoid some potential problems.

In the PayPal url configuration add event=ppipn

Drag the PayPal Listener action into your new ppipn event.

The PayPal Listener doesn't seem very sophisticated at all. It just echos back the results to PayPal and sets the event status depending on what is received. Any other code you will need to add either using CF actions or Custom Code with hand-coded porcess.

You can see the listener code in administrator/components/com_chronoforms/form_actions/paypal_listener/paypal_listener.php

Bob
dyoungers 23 Jul, 2011
thanks ... I'll dig into it and see what I learn🙂
dyoungers 26 Jul, 2011
After trying things, the paypal listener kept giving me an "invalid" action then after looking at the code I see what appears to be a bug in the PayPal Listener function set_events (line 106) currently the function looks like

	
	function set_events($valid = false, $form){
		if($valid){
			if($form->data['payment_status'] == 'Completed'){
				//$this->events['verified'] = 1;
			}
--->			$this->events['invalid'] = 1;
		}else{
			$this->events['invalid'] = 1;
		}
	}


I changed it to be:
$this->events['[b]verified[/b]'] = 1;

Now on to the next step🙂

Dave
dyoungers 26 Jul, 2011
For some reason I can't seem to get my form called back by paypal (I've verified the form works from using PayPal's IPN Simulator)

I'm using the cURL ReDirect URL and I have verified that a simple PHP file will be called with the following code:

notify_url=http://mysite.com/administrator/ipnnotify.php


but this doesn't work:

notify_url=http://mysite.com/index.php?option=com_chronoforms&chronoform=MakePayment&event=ipn


I'm not familiar with cURL but is there something in the cURL processing that is tripping up on either the ? or the &

Thanks!
Dave
GreyHead 27 Jul, 2011
Hi Dave,

Good catch on the bug - I'll add it to the bugs list for Max.

CURL should be OK with a URL in the parameter value - all the values are URL encoded before they are sent (and I've used similar URLs OK with PayPal and CFv3)

What error do you get?

Have you tried the SandBox IPN simulator? I've also found the Belahost IPN tester to be very useful as it will show you what is being sent from your site.

Bob
dyoungers 27 Jul, 2011
Yes, I've verified the form is called correctly from the IPN Simulator. To make sure I'm not mistyping the URL I cut and pasted it to the redirect code but when I go through the PayPal checkout the form never gets called at all, i.e. custom logging code at the beginning of the "On IPN" action never happens. Again, if I put a custom PHP (that I wrote) in the notify_url, that code gets called back as I would expect so I know the checkout code is right.

I'm completely stumped (and not sure where to start) so any help would be appreciated.

Thanks!
Dave
GreyHead 27 Jul, 2011
Hi Dave,

By all means email or PM me the site URL and a SuperAdmin login and I'll take a quick look.

Bob
GreyHead 28 Jul, 2011
Hi Dave,

So far I've established that the immedaite problem is that the three urls need to URLencoded before they are added to the PayPal URL. The CURL plug-in handles this OK, the ReDirect one doesn't.

I've tried setting the urlencoded values in the Custom Code box before the ReDirect URL action but for some so far mysterious reason that doesn't work :-(

I've taken a a backup copy and will test a bit more on my local server where I can add debug code into the action files and see if I can work out what is happening.

Bob
dyoungers 28 Jul, 2011
Bob,

Thanks ... keep me posted🙂

Dave
GreyHead 28 Jul, 2011
Hi Dave,

I've fixed a bug in the action that was getting data from the $_POST array instead of the $form->data array (a carry over from CFv3 I think) and I've added code to force the values to be URLencoded. This seems to give a usable URL. Please will you check with the SandBox when you have a moment.

Bob

PS I installed exTplorer on your site to let me update the PHP files.

PPS The URL looks odd because the browser displays the ¬ part of ¬ify_url as ¬ - but it's just cosmetic (I hope).
dyoungers 28 Jul, 2011
Bob,

a quick test shows the IPN listener getting called now

as far as eXtplorer, thought I had it installed but either way, no problem there

Thanks!
Dave
GreyHead 28 Jul, 2011
Hi Dave,

Good news :-)

It's quite possible that you did have exTplorer installed already. I may have overlooked it, or it may not have been working in 1.7 (I had to bug-fix my version to get it to work and re-installed that on yours.) But it's been the kind of day where I can no longer remember which site is which :-(

Bob
cr33 03 Aug, 2011

Hi Dave,

I've fixed a bug in the action that was getting data from the $_POST array instead of the $form->data array (a carry over from CFv3 I think)[...]



Hi there - can you elaborate a bit more on this bug? I'm having issues with the listener myself (I'm consistently getting 'invalid' responses, but $form-> looks a bit dodgy as well). I'm on RC 1.9.

Pseudo-code:

On Load: Show HTML
On Submit: Some Validations
           Joomla User Registration
              On Fail: Debug/ShowStopper
           DB Save
           Paypal Redirect (to sandbox - IPN URL has '&event=Verify')
On Verify: PayPal Listener


Paypal listener always returns 'on invalid', even after correcting the bug in the listener PHP file. Been going around in circles for a while now - any pointers are greatly appreciated.

Thanks,
Chris
cr33 03 Aug, 2011
OK - so I missed one of the calls to paypal vs paypal sandbox. The relevant portions of the code now look like this:

class CfactionPaypalListener{

	[...]

	// Set to True if using sandbox
	var $sandbox = True;
	
	function run($form, $actiondata){

		[...]

		$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
		if ($this->sandbox){
			$header .= "Host: www.sandbox.paypal.com:443\r\n";
		} else {
			$header .= "Host: www.paypal.com:443\r\n";
		}
		
		[...]

		if ($this->sandbox){
			$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
		} else {
			$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
		}


Now where I'm stumped is setting a value in the DB based on the 'verified' response. $_POST is full of stuff that I don't really need (aside from 'payment_status' of course😉. $form is practically empty. How does one tie the IPN notification to a row in the DB?

Thanks!
Chris
dyoungers 04 Aug, 2011
yes, a bunch of references to change in order to activate/deactivate the sandbox ... I did the same thing by setting the URL based on the sandbox flag and finally ended up adding a parameter to the plugin so I could activate/deactivate the sandbox based on the form (so I wouldn't mess up my active paypal forms when testing new forms.)

as far as figuring out which record in the database to update on the IPN callback, you'll need to tie the payment back to the record in your database. PayPal uses the invoice parameter as a pass through variable and you can use that to identify the transaction.

In my case I didn't have an actual invoice id so I just used the record id from the database and added the following custom code which I placed after saving the form data (so the cf_id is set) and before redirecting to paypal.

<?php
$form->data['invoice'] =  $form->data['chronoform_data']['cf_id'];
?>


In the IPN listener you can use invoice as the key on a db record loader, i.e. load the record, set the field indicating that payment was received, and then use db save to update the database.

Hope that makes sense ...

Dave
cr33 04 Aug, 2011
Yes - thanks. I ended up doing something quite similar just now, but used the 'custom' field instead of 'invoice'.

Is adding a param as easy as editing the CTP file, or what's involved there?
dyoungers 04 Aug, 2011

Is adding a param as easy as editing the CTP file, or what's involved there?



mostly ... you also need to add code to PHP to retrieve the parameter which I figured out by looking at other plugins

No sense reinventing the wheel here, code is attached to this message
cr33 04 Aug, 2011
Thanks! I'm on a hard push to get this thing live by end of day tomorrow (why do they always wait until the 11th hour?), but as soon as I get my head above water I'll look it over.

Chris
Max_admin 15 Aug, 2011
Thank you!🙂
Max, ChronoForms developer
ChronoMyAdmin: Database administration within Joomla, no phpMyAdmin needed.
ChronoMails simplifies Joomla email: newsletters, logging, and custom templates.
mike11 30 Jun, 2012

In the IPN listener you can use invoice as the key on a db record loader, i.e. load the record, set the field indicating that payment was received, and then use db save to update the database.



Can anyone please help me with this... I have searched high and low, but I can't find anywhere that explains how I am able to grab a return value (i.e. invoice) from paypal and use a statement such as the following to update my database:

UPDATE jos_my_table_name SET Status=1 WHERE invoice={invoice_from_paypal};

I have an invoice field in my form. I just can't figure out how to get it back from Paypal, and update the row with that specific invoice number as above.

I know the IPN is working because when I use the developer sandbox ipn test tool, it sends everything, including the invoice number, back to my email.

Also, I'm not a programmer so if you could be specific, it would be greatly appreciated!

Thanks again in advance for your help...
Max_admin 30 Jun, 2012
Hi Mike,

I suggest that you check the returned values from PayPal first, you can add an email action in the success event of the listener, and configure it correctly, in the template box add this code:

<?php print_r2($form->data); ?>


This will dump all the data in the data array including those posted by PayPal, which you can use in your SQL.

Regards,
Max
Max, ChronoForms developer
ChronoMyAdmin: Database administration within Joomla, no phpMyAdmin needed.
ChronoMails simplifies Joomla email: newsletters, logging, and custom templates.
mike11 30 Jun, 2012
Hi Max! (Amazing Component by the way...)

Thanks for your reply. I did as you said and received the array of info in my email, which included the "invoice" variable.

However, I would like to be able to (either code the IPN or place a custom code or use the DB Loader) to have the chronoforms system/IPN automatically detect the "invoice" variable, find it in my DB, and update the Status column of that transaction to "Paid".

My issues are the following:
- I don't know the code I need to use to capture the invoice variable?
- I don't know the related code to update the database?
- I don't know where to place these pieces of code?

I have tried so many different configurations with the ipn listener, custom code, db loader... I just can't get the DB to update.

I know using: UPDATE jos_my_table_name SET Status=1 WHERE invoice={invoice_from_paypal};
works, because I used it in phpMyAdmin panel with real invoice numbers and it updated the associated record. Just can't get it to do it automatically from the IPN.
GreyHead 30 Jun, 2012
Hi Mike,

The invoice number (and all the other transaction data) should be returned by PayPal when the IPN listener is called and so ChronoForms will put it into the $form->data array. You can try testing $form->data['invoice_number'] in your query but it would be better to be able to dump the data and see exactly what is there. I don't think Max's suggestion will work directly because the IPN Listener action doesn't output to the browser at all but you could dump the results to a text file or use Joomla! logging capability to save it to a log file.

Below is an extract from an old PayPal IPN logfile (from a custom application that I wrote but the input names are all from PayPal).

Bob

    [ipnscript] => http://domain.com/component/option,com_ghcourse/controller,txn/task,notify/tmpl,component/
    [ipnstatus] => VERIFIED
    [rm] => 1
    [receiver_email] => pptest@example.com
    [business] => paypal@yourdomain.com
    [receiver_id] => AEFGKQRSUV678
    [paypal_address_id] => BHIMRSTWXY168
    [item_name] => Item Name
    [item_number] => 568
    [quantity] => 1
    [invoice] => 348957
    [custom] => RS2899V
    [payment_status] => Completed
    [payment_date] => 11:29:51 Mar 07, 2009 PDT
    [payment_gross] => 19.95
    [payment_fee] => 0.58
    [mc_gross] => 19.95
    [mc_fee] => 0.58
    [mc_currency] => USD
    [txn_id] => CEFIMNTYdhmuwz345
    [parent_txn_id] => AGKPRUZabehiqvz36
    [txn_type] => web_accept
    [memo] => PayPal Special Instructions/Note Field.
    [first_name] => Jayson
    [last_name] => Tester
    [address_street] => 13 Elm Street
    [address_city] => New York
    [address_state] => NY
    [address_zip] => 10185
    [address_country] => United+States
    [address_status] => confirmed
    [payer_email] => paypal@theirdomain.com
    [payer_business_name] => YourPayers AMCE Co.
    [payer_id] => HIJLNQRWYZ236
    [payer_status] => verified
    [payment_type] => instant
    [notify_version] => 2.1
    [verify_sign] => X95ktrZ86DmoOT3gaUcJH4W1GpAMVfwq2KxnsjQS7FidIuCLlPezvRYy
    [subscr_date] => 11:29:51 Mar 07, 2009 PDT
    [subscr_effective] => 11:29:51 Mar 07, 2009 PDT
    [period3] => 1 M
    [amount3] => 9.95
    [mc_amount3] => 9.95
    [retry_at] => 12:29:51 Mar 14, 2009 PDT
    [username] => xxxxxxx
    [password] => zzzzzzzz
    [subscr_id] => S-CDINQUXYejnopw256
This topic is locked and no more replies can be posted.