Elgg + PayPal integration

I found this plugin https://github.com/arckinteractive/elgg_paypal , but i don't know how implementing their funcionalities. I am creating a advertisement area in my elgg site and users should pay for show a ad.

Have a other plugin for it?

  • Are you asking for more user friendly plugin or what? You'd need to process IPN notifications if you don't want to manually approve payments.

    It seems that it lacks the part of creating payment, so that's the part you'd need to work on. Obviously some code to handle payments and unlock advertisements is also to be written. If you're not familiar with PayPal integrations, perhaps you should hire someone to do the job or start reading developer guide of payment solution of your choice (there are several).

  • I'm the author of that paypal plugin - it's meant as a development tool for experienced developers, there's really not much in the way of end-user facing stuff there.  Give than everybody's ecommerce requirements are different it makes sense to use something like that speed up development but still do your own custom logic.  There are some convenience functions in there for getting paypal tokens and checkout urls I believe, but it's definitely not just a drop-in plugin for end users.

  • @ Marcelo de Andrade , I wrote an elgg ads plugin which integrates paypal with elgg and openx ads server. The name of the plugin is called gutwa. You can check gutwa plugin and see how paypal functions have been used. Paypal system is messy or confusing but I was able to make a check out system that worked with elgg and openx ads server. However, I am looking into stripe payment system which seems promising than paypal system. Hope this comment can be helpful as you look forward to set up an elgg ads system.

  • @Pawel

    I am studying hard the paypal docs, but too i am newbie in Elgg development and i can't pay for it for N reasons for me.


    I don't need a exactly plugin for end users, i am developing a new plugins for my elgg site and i can coding.


    Oh, Tom! i will see that plugin.

    I want a paypal integration but simplifying I need to do: 

    integrate my form ad to paypal 
    verify that the payment was made 
    display the purchased ad

    Thanks guys!

  • @Matt

    Using your plugin, i need know why use elgg_get_site_entity when not elgg_get_logged_user_entity() ?

    function paypal_process_ipn() {
         $sandbox = elgg_get_plugin_setting('sandbox', 'elgg_paypal');

        error_log('IPN triggered: ' . print_r($_POST,1));
        $txn = (object) $_POST;

        // This IPN listener reads IPN msgs sent from PayPal, verifies the msg, and processes
        // the data by posting the IPN message fields and values to the browser screen.

        // read the IPN msg from PayPal and add 'cmd' for your verification request
        $req = 'cmd=_notify-validate';

        // append the IPN msg, in NVP format, to your verification request
        foreach ($_POST as $key => $value) {
            $value = urlencode(stripslashes($value));
            $req .= "&$key=$value";

        // set up the headers for your verification request
        // POST your verification requests to PayPal (here, the Sandbox)
        $header  = "POST /cgi-bin/webscr HTTP/1.0\r\n";
        if ($sandbox) {
            $header .= "Host: www.sandbox.paypal.com:443\r\n";
            $fsock = 'ssl://www.sandbox.paypal.com';
        else {
            $header .= "Host: ipnpb.paypal.com:443\r\n";      // endpoint for Live apps
            $fsock = 'ssl://ipnpb.paypal.com';

        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

        // open the socket
        // $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
        $fp = fsockopen ($fsock, 443, $errno, $errstr, 30);

        if (!$fp) {
            // HTTP error
            error_log("Paypal IPN ERROR:: HTTP socket error! Unable to open URL");
            die('error $fp');
        else {
            // POST verification request
            fputs ($fp, $header . $req);

            while (!feof($fp)) {
                $res = fgets ($fp, 1024);

                paypal_log_ipn(elgg_get_site_entity(), $txn);

                if (strcmp ($res, "VERIFIED") == 0) {
                        // trigger plugin hook for individual plugins to have an option to save the ipn first
                        $result = elgg_trigger_plugin_hook('paypal', 'ipn_log', array('txn' => $txn), false);
                        if (!$result) {
                            // no plugins logged the transaction, log it to the site
                            paypal_log_ipn(elgg_get_site_entity(), $txn);
                else if (strcmp ($res, "INVALID") == 0) {
                    // invalid - do nothing for now
                    // IPN invalid, log for manual investigation
                    paypal_log_ipn(elgg_get_site_entity(), $txn);

            fclose ($fp);

  • You're looking at the IPN endpoint, when paypal pings that there is no logged in user.  So the default action is to save it to the site itself, and allow custom plugins the option of reassigning it to another user/entity based on their own logic.  The simple use case is to match by the paypal token, or subscription id, or whatnot.  Additionally there may be logic where a transaction should be saved to a group or some other entity and not to a user.  I tried to make it generic enough to cover any use case.

  • Note: as Pawel pointed out to me in an email the IPN here should ideally be checking for duplicates, I need to add that in.  Thought I'd mention that if you're building something based off this.

  • Ah! I understand now! Thanks for your patience and help, @Matt !

    Ok, i will check duplicates too.

  • You get ton of stuff on IPN endpoint, not only information about single transactions, but ie. about started/cancelled subscriptions and all.

    It falls on developer to take care about further processing. Quoting from IPN developer guide:

    After PayPal verifies an IPN, your listener or administrative software should make these additional checks:

    • Verify that you are the intended recipient of the IPN message.
      To do this, check the email address in the message. This check prevents another merchant from accidentally or intentionally using your listener.
    • Verify that the IPN is not a duplicate. 
      To do this, save the transaction ID and last payment status in each IPN message in a database and verify that the current IPN's values for these fields are not already in this database.

      Note You can't rely on transaction ID alone to screen out duplicates, as this scenario shows: 1) PayPal sends you an IPN notifying you of a pending payment. 2) PayPal later sends you a second IPN telling you that the payment has completed. However, both IPNs contain the same transaction ID; therefore, if you were using just transaction ID to identify IPNs, you would to treat the "completed payment" IPN as a duplicate.

    • Ensure that you receive an IPN whose payment status is "completed" before shipping merchandise or enabling download of digital goods.
      Because IPN messages can be sent at various stages in a transaction's progress, you must wait for the IPN whose status is "completed' before handing over merchandise to a customer.
    • Verify that the payment amount in an IPN matches the price you intend to charge. 
      If you do not encrypt your button code, it's possible for someone to capture a button-click message and change the price it contains. If you don't check the price in an IPN against the real price, you could accept a lower payment than you want.
  • Yeah much of that logic I need to hand off to plugins, as things like email address may not be site-wide settings (think of groups that their own membership checkout to their own paypal accounts for example).  So it's expected that much of that will be checked in the plugin hooks.