Addon: Adding support for failed payments with paypal_r

Discussion in 'Customization & add-ons' started by amadeus, Jun 18, 2009.

  1. amadeus

    amadeus Member

    Joined:
    Jan 16, 2009
    Messages:
    42
    I wanted to have a way to let my users know that they have had a FAILED payment on their recurring paypal subscription. This was my solution.

    This addon does NOT change the functionality of how amember currently handles a failed payment. All it does is:
    1. Add a blurb in the Admin->User->Payments & Subscriptions (similar to the CANCELLED tag)
    2. Add a blurb in the member's area under payment history for the payment that actually failed.

    Along with the member's area blurb (#2 above) will be a link called "Resolve Failed Payment", which will point to an html document that you define in the code below. For me, I just make one document called FailedPayment.html and explain the situation and what the user must do to resolve it (typically either wait or cancel/fix/resubscribe.)

    Anyway, this is very unobtrusive code and really only provides a line of additional customer support more than actual script functionality. However, I think anyone that uses recurring paypal_r will find it useful.

    Amadeus

    ---------------------------------

    In /plugins/payment/paypal_r/paypal_r.inc.php:

    REPLACE:
    Code:
                case 'subscr_eot':
                case 'subscr_failed':
                    $payment_id = $this->find_last_payment_id($vars['subscr_id'], $vars['invoice']);
                    if (!$payment_id)
                        $this->postback_error(_PLUG_PAY_PAYPALR_ERROR11);
                    $p = $db->get_payment($payment_id);
                    $new_expire = date('Y-m-d', time() - 3600 * 24 ); //yesterday date
                    if ($p['expire_date'] && ($new_expire < $p['expire_date']))
                        $p['expire_date'] = $new_expire;
                    $p['data'][] = $vars;
                    $db->update_payment($payment_id, $p);
                    break;
    
    With:
    Code:
    	    case 'subscr_failed':
                    $failed = 1;
                case 'subscr_eot':
                    $payment_id = $this->find_last_payment_id($vars['subscr_id'], $vars['invoice']);
                    if (!$payment_id)
                        $this->postback_error(_PLUG_PAY_PAYPALR_ERROR11);
                    $p = $db->get_payment($payment_id);
                    $new_expire = date('Y-m-d', time() - 3600 * 24 ); //yesterday date
                    if ($p['expire_date'] && ($new_expire < $p['expire_date']))
                        $p['expire_date'] = $new_expire;
                    $p['data'][] = $vars;
                    if ($failed)						
                    {
                        $p['data']['FAILED'] = 1;
                        $p['data']['FAILED_AT'] = strftime($config['time_format'], time());               
                        $p['data']['failed_url'] = "http://www.yourdomain.com/FailedPayment.html";
                    }		
                    $db->update_payment($payment_id, $p);
                    break;
    
    NOTE: Replace ""http://www.yourdomain.com/FailedPayment.html" (in the code above) with the URL to the document you wish people to be directed to in order to resolve failed payments.



    In /templates/admin/user_payment.html:

    AFTER:
    Code:
    {if $p.data.CANCELLED}
    <table style='font-size: 8pt;' bgcolor=#e0e0e0>
        <tr><th align=right><b>CANCELLED</b>&nbsp;</th><td>&nbsp;{$p.data.CANCELLED_AT|escape}</td></tr>
    </table>
    <br /><br />
    {/if}
    
    ADD:
    Code:
    {if $p.data.FAILED}
    <table style='font-size: 8pt;' bgcolor=#e0e0e0>
        <tr><th align=right><b>FAILED</b>&nbsp;</th><td>&nbsp;{$p.data.FAILED_AT|escape}</td></tr>
    </table>
    <br /><br />
    {/if}
    


    In /templates/admin/payments.html:

    AFTER:
    Code:
    {if $p.data.CANCELLED}<br /><font color=red>CANCELLED</font>{/if}
    
    ADD:
    Code:
    {if $p.data.FAILED}<br /><font color=red>FAILED PAYMENT</font>{/if}
    


    In /templates/admin/user_payments.html:

    AFTER:
    Code:
    {if $p.data.CANCELLED}<br /><font color=red>CANCELLED</font>{/if}
    
    ADD:
    Code:
    {if $p.data.FAILED}<br /><font color=red>FAILED PAYMENT</font>{/if}
    


    In /templates/member.html
    AFTER:
    Code:
        {if $p.data.CANCELLED}<br /><div class="small" style="font-color: red; font-weight: bold;">#_TPL_MEMBER_CANCELLED#</div>
        {elseif $p.cancel_url}<br /><a href="{$p.cancel_url}" target=top onclick="return confirm('#_TPL_MEMBER_CANCEL_SUBSCR#')">#_TPL_MEMBER_CANCEL#</a>
        {/if}
    
    ADD:
    Code:
        {if $p.data.FAILED}<br /><div class="small" style="font-color: red; font-weight: bold;"><font color=red>PAYMENT FAILED</font></div>
        <br /><a href="{$p.data.failed_url}" target=top">Resolve Failed Payment</a>
        {/if}	
    
  2. amadeus

    amadeus Member

    Joined:
    Jan 16, 2009
    Messages:
    42
    Hmmm...I hope that it is ok to post code here on the forums. I thought I saw someone else posting another addon; however, I got to thinking after I posted it that perhaps it might not be allowed. I think the templates are fair game; however, perhaps the one php snippet might not be acceptable.

    Administrators feel free to delete if this is out-of-line with my apologies. I only thought I'd give a little something back after asking so many questions the past few days ..heh.
  3. miso

    miso aMember Pro Customer

    Joined:
    Aug 22, 2006
    Messages:
    543
    Awesome!

    Thanks for the contribution.

    And I don't think Alex will mind some random code being posted up here, as the aMember itself is so big that it really doesn't make a difference if you "share" some of the code here for free...
  4. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,279
    amadeus, this is ok, no problem at all.
  5. amadeus

    amadeus Member

    Joined:
    Jan 16, 2009
    Messages:
    42
    Here is a little more tweaking for those that are interested:

    In the code above that I had you add in paypal_r.inc.php, replace this line:
    Code:
    $p['data']['failed_url'] = "http://www.yourdomain.com/FailedPayment.html";
    
    With this line:
    Code:
    $p['data']['failed_url'] = "http://www.yourdomain.com/FailedPayment.php?cancel_url=https://www.paypal.com/cgi-bin/webscr?cmd=_subscr-find&alias=USER%40DOMAIN.COM";
    
    (USER%40DOMAIN.COM is the email address that people are paying to on paypal. ..an example might be uberness%40amember.com)







    Once you've done that ..then you can put something like this in your FailedPayment.php file...

    Code:
    <p> 1.  First, you must cancel your current subscription.  
              <a href=	
              <?php
                     if (isset($_GET['cancel_url']))     $cancel_url = $_GET['cancel_url'];
                     else                                $cancel_url = "http://www.paypal.com";
                     print "\"$cancel_url\"";
              ?>			
              target="_blank">Click here</a> to visit paypal and cancel you current subscription.  After you have cancelled that subscription, you can close the additional browser window and come back to this page in order to continue on to step 2.</p>
    
    After that, I tell the user to FIX the problem that causes the failure, then I give them a link to the member page to create a new subscription. I'm thinking it's really the only sane way to deal with a failed recurring payment on paypal without forcing the user to wait 3 days for the automatic rebill.
  6. makelemonade

    makelemonade New Member

    Joined:
    Jul 5, 2009
    Messages:
    7
    This is awesome, any chance it can be rolled into the main amember distribution? There are a bunch of changes to the files, and I'd rather not have to deal with checking the changes each upgrade.
  7. makelemonade

    makelemonade New Member

    Joined:
    Jul 5, 2009
    Messages:
    7
    Am revisiting this as I use Paypal a lot. This is good code, I'm really interested in having it integrated in amember. How should I go about requesting this?
  8. amadeus

    amadeus Member

    Joined:
    Jan 16, 2009
    Messages:
    42
    I just wanted to be clear that I relinquish all copyrights on my code in this thread (in hopes that Alex will add it, or something similar, to the standard aMember distribution.) :)

Share This Page