Script to create users on receive of IPN paypal subscription event

  • Hi everyone,

    I'm face now for two days of the implementation of a captive portal for a camping  >:(. The solution has to be trought paypal, so the staff do not have to check/give vouchers codes or login/pass; it all works automatically.

    My problem is to insert new users into local database at IPN return event

    My test user is apparently declared like this in config file:


    But how can I had some more users via a php page ? I can parse XML but how to compute password encryption ?

    And on the over part I have to provide the log/pass or voucher to customer which has paid, I thought the best way was to store the email backed done by paypal and code a form on the captive portal webpage that returns voucher code or log/pass if the email entered exists (entered by paypal paiement process).

    For now I succesfully add access to paypal trought the portal for non authenticated users, They can make paiement and I've got the response from paypal, I have a custom portal index page with voucher codes and log/pass functionnalities but I need to give access to the user after receiving paypal IPN return, and the eaisest way is to used locale database or radius.

    Have you ever make a project like this ? Any advice to interact the pfsense captive portal with Paypal ?

    Many thanks for reading me, Regards all !!

  • Hi there.

    Automatically inserting new users into the "Local Database" on pfSense doesn't seem a good idea to me, because of this:
    When I set an expiration date, only the date is set, not a "time".
    So, creating a "6 hours" user seems (more) difficult to me.

    Creating a user, generating the passwords etc is already in the code (see here for the pages, start with /usr/local/www/system_usermanager.php )

    This looks the more way easy to me:
    Generate vouchers.
    Export the CVS file, and write the vouchers to a file, one per line.
    Put this file on your pfSEnse box, in here /var/etc
    When called back (IPN) by the PayPal callback function, on payment (checkout), you should:

    Mark the voucher in your file as "used" or delete it from the file (lock the file when taking a voucher, mark or delete it, and release the lock - as seen elsewhere in the pfSense code)
    Print the voucher code on the screen (needed so the user can connect) and advise urgently that the client copies the vucher code somewhere. Remind him that a copy is in his mail box.
    Send a mail to the address mail that the client used  when paying with paypal

    Idea: when 90 % of your file is used (== sold), have a mail send to yourself that you should add more vouchers.

    The "PayPal callback function" is should be executed on your pfSense box.

    Btw: using the address mail that paypal uses seems a good idea to me (if it can be obtained from the Paypal callback). Do not ask the user to enter his address mail. Many do make errors, so the pay and never receive the mail …

    All this means some PHP coding and testing - this is pure fun.

    Btw: you're sure that you have to 'sell' Internet time ?
    Now a day, electricity, water, television and Internet is part of 'standard package' in tourism.
    An exception might be the fact that Internet access might be an expensive thing to give away.
    Example: I work in a hotel, and I never ask : "Did you use the channels 4, 20,21,23,24 or 25 in your room ? (Canal + in France means several hundreds of € each month for us, whether the clients use it or not- Internet costs us only 50 € a month for 18 Mbits)

    Be ready to receive several clients at your desk that say: I paid, I didn't receive the mail - I didn't saw the voucher code - my screen went dead when checking out when paying with Paypal, etc etc etc. (the list that explain why things went wrong is huge).
    So, be ready to take a voucher out "by hand" - make a second voucher role for that - and have front desk personnel access to the pfSense page so they can
    => check if the client actually paid (checking your Paypal account - your paypal transaction log, use extensive logging in pfSense to trace all transactions. This means you have to 'form' your camping personnel - and that's yet another reason NOT to SELL Internet time.
    => Check if vouchers are being consumed
    => Check if vouchers are being used entirely.
    => etc.

    Needless to say: Camping (globally: personnel in tourism business) are NOT good system analysts - things will go out of hand. Be ready to train people for every situation.

    I love to say to my clients: "Listen, it works on my iPad, iPhone, Android smartphone" (I show it to them : portal access, a user and a password and off I go, surfing, surfing …)
    I add to that: "Look here, I show you the number of clients connected right now (on the pfSense Captive portal status screen) ….. "
    And I finish with "I don't know what YOU did with your PC s that it doesn't work for you …."

    Because I do not want to create the situation that front desk personnel start to dig in all kind of systems - even the clients computure to make it work …"

    Ok, when I'm there myself I always add after that:
    With your permission, give me your device 2 minutes.
    I'll make it work, or I tell you why it won't work with your PC.
    I I can't do that in 2 minutes I pay you a drink.
    If it works, you pay me a drink.

    The deal is always accepted.
    I always had this free drink on my work and I never paid a drink for a client the last 10 years, the time I already use pfSense Captive portal software for our public Internet access ;)
    (People use VPN software, lock down non-known networks - use aggressive firewall rules - use a STATIC IP - don't have a Wifi device (yes, happens) - had there Wifi shut down - have fucked up browser software - try to surf to an initial https site (ssl connections can't be redirected with 'scarry' messages in their browser - etc etc. I guess I've seem them all last 10 years.

    So, be sure to SELL Internet time. People are gona ask what they paid for, and they are going to insist - even at 04h00 AM  ;)

  • Hi Gertjan,

    I'm very pleased to have your answer. I just can say "waouh" !! what a great answer  ;)

    To begin let me thank you for figure me out that with the "expire" filed I will not be able to give per-hours access as it is a date, it will avoid me to spend unnecessary time on this solution…

    I think your proposal is closed from wha't I've implemented.

    Here is some code:

    $row = 1;
    $client = $_POST['email'];
    if (($handle = fopen("/var/emails.txt", "r")) !== FALSE) {
      while (($data = fgetcsv($handle, 10000, ",")) !== FALSE) {
        $num = count($data);
        echo "
     $num fields in line $row: 
    	$find = false;
        for ($c=0; $c < $num; $c++) {
    	//SI on trouve l'email dans le fichier on traite
    		if ($client == $data[$c]){
    ///On cherche le numero du voucher a donner
    $countFile = "/var/count.txt";
    $handle = fopen($countFile, 'w');
    $lineNumber = fread($handle,filesize($my_file));
    //On écrite le numéro incremente pour la prochaine fois
    $newLineNumber = $lineNumber+1;
    fwrite($handle, $newLineNumber );
    //On récupère un ocde à la ligne demandée
    $voucherFile = "/var/vouchers.txt";
    $lines = file($voucherFile); 
    		///On indique que le traitement est OK si KO partout on affiche pas de code trouvé pour cet email
    		$find = true;
    		///$newLineNumber - 1 = current line (start from 0)
            echo "Here is your code for the email entered :".$lines[$lineNumber]."
    	if (!$find)
    	echo "Your email is not recognize can't give you a code - Please contact the staff";
    function read_and_delete_first_line($filename) {
      $file = file($filename);
      $output = $file[0];
      file_put_contents($filename, $file);
      return $output;

    In the code above I use these files:

    • One to get the index on the next available voucher /var/count.txt

    • One to get a voucher based on the index /var/vouchers.txt

    • One to see if the user have a voucher linked to his email  /var/emails.txt

    I do not used "read_and_delete_first_line" but it can be a solution to not use the index file to give an available vouchers…

    This solution works like you said:

    • The user pay trought Pfsense captive portal to Paypal

    • The IPN script receive from paypal an event and add the email of the customer to /var/emails.txt

    • The user after paying goes back to the portal and click on "I paid give me my code"

    • The PHP script above gives a voucher code.

    I have not implemented the whole thing but I think there is some limitations so my next idea is to externalize the apllication process so it will look at this:

    • The user pay trought Pfsense captive portal to Paypal

    • The IPN script receive from paypal an event and add the email of the customer to the application server

    • The user after paying goes back to the portal and click on "I paid give me my code"

    • The PHP script on the application server gives a voucher code.

    It is closed from the first solution but it permit me to have access to the infrastructure from everywhere, I also can use MySQL/PHP to give more functionnalities to my portal and it's redundant (I've got a backup redundant server). And i can display all history vouchers codes for a given email simply and other functionnalities…

    The bad part is that I'll have to maintain the "application part" but it's not a huge work and it's more usable, maintanable, evoluable,

    My first thought was to give the voucher by email but if you do not have internet acces to get it back that's not fair  >:( but with the solution above I'll send the voucher by email also

    Otherwise for the other sells this camping is using a simple cash register that is on another network (they have paid 10 000$ for the 6 antennas and a similar Wifi solution  >:( this is theft), but it will be perhaps a good client for OpenERP and perhaps interface it with pfsense…

    And for the paid drink I take the advice  ;)

    Anyway many thanks for your spending time on this issue (and sorry for my english spoken). A night of reflection and your answer and I know now where to go  ;)

    Regards !!

  • Hi Gertjan,

    I have a little more question; il there a secure way to generate voucher codes offline (i.e. on another system than PFsense) ? I have found that but I can't get it working and I do not know how it works.

    So have you ever done that ? And if it is can you point me to the rigth way ?


  • @exaju:

    Hi Gertjan,

    I have a little more question; il there a secure way to generate voucher codes offline (i.e. on another system than PFsense) ? I have found that but I can't get it working and I do not know how it works.

    So have you ever done that ? And if it is can you point me to the rigth way ?



    this is the software I developed, and it is not able to create the vouchers offline. In fact you need to create the vouchers in pfSense (just create a huge number of them so you don't have to do this often), export the .csv and import it into the software. There is a PDF File included which explains how to use it. After you imported vouchercodes into the software, you can generate a PDF file for easy printing and cutting. ;)

    Best regards,

  • Hi eagle2,

    Many thanks for rour reply ! And great job for your voucher tool…

    Anyway I think also that generated a great bunch of vouchers code is THE solution, the problem is that I'll need to access to the server after a specific time when the generated vouchers will all be used to not have a "production cut".

    Anyway thank you for your reply, I'll not waste my time on a solution that does not fit my needs.

    Regards, or I can say also Grüße  ;)

  • Hi,

    "offline generating" of vouchers as such is not possible, pfSense needs to now somehow which vouchers are valid and which are not…

    Maybe setting up a VPN to the pfSense-Box could help? Someone created a REST API for pfSense Vouchers (, you could build something on top of that, but you still need access to pfsense though…

    Best regards (or "Viele Grüße"  ;)),

Log in to reply