Hook for Payment Received

Discussion in 'aMember Pro v.4' started by betgear, Mar 23, 2012.

  1. betgear

    betgear New Member

    Joined:
    Nov 13, 2008
    Messages:
    10
    Hi,
    I'm trying to code a simple hook when a payment is received. I've looked at the documentation, and it is somewhat lacking.

    All I want to do it process the product ID and email address so that I can update a separate database.

    Can anyone point me in the right direction.

    Thanks.
  2. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    application/default/plugins/misc/betgear.php
    PHP:
    class Am_Plugin_Betgear extends Am_Plugin
    {
        function 
    onPaymentAfterInsert(Am_Event $event)
        {
             
    $payment $event->getPayment();
             
    $invoice    $payment->getInvoice();
             foreach (
    $invoice->getItems() as $item)
             {
                   
    $product_ids[] = $item->item_id;
             }
             
    $s $invoice->getEmail() . " == " implode(";"$product_ids);
             
    $this->getDi()->errorLogTable->log("BETGEAR HOOK: " $s);
        }
    }
  3. betgear

    betgear New Member

    Joined:
    Nov 13, 2008
    Messages:
    10
    Thanks Alex, much appreciated.
  4. spicyniknaks

    spicyniknaks New Member

    Joined:
    Feb 27, 2012
    Messages:
    20

    What is the best way to catch a refund event ? I am using paypal. I'm not talking about the end of subscription event but when a paypal refund or chargeback is processed by paypal.
  5. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    There is no such event currently. Do you need to perform special actions on refunds? If yes what actions?
  6. betgear

    betgear New Member

    Joined:
    Nov 13, 2008
    Messages:
    10
    Hi Alex,

    For future reference, how do I obtain quantity and price of items purchased?

    Is there a class diagram anywhere?

    Cheers
  7. spicyniknaks

    spicyniknaks New Member

    Joined:
    Feb 27, 2012
    Messages:
    20
    Hi Alexander,

    I just recently bought the software and like what you have created. I intend to use it to replace my custom license management/paypal IPN solution that I wrote for my own software.

    When a customer buys my software my IPN script generates a license and sends an email. This I have managed to do already with aMemeber through writing a custom plugin. However, if a customer cancels their payment or requests a refund then I would like to catch this IPN event and block access for support/updates. I can see in the Paypal plugin the processValidated function catches the "web_accept" and depending on the request->payment_status it will either add a payment or add a refund.

    I can probably handle what I want by modifying the core code, but I would have liked to do it through a plugin if possible so it doesn't break the update process and saves me having to manually modify the code every time I want to apply an update. I was thinking of adding a hook similar to the onPaymentAfterInsert but for refunds. I assume that refunds are important to be handled as this would affect affiliate payments so I thought there would be something in place for this already. I can't see any transactions being marked as refunds although I may be doing something wrong here, but I have been making live purchases then refunding the purchase through PayPal expecting to see the payment marked as refunded.

    When I look at the XML of the invoice I see the refund has been received from PayPal:

    Significant fields from initial invoice event:

    <event time="2012-03-24 23:18:44">
    <invoice-log-item type="incoming-request">
    <url>
    <method>POST</method>
    <scheme>http</scheme>
    <base_url>/cp</base_url>
    <path_info>/payment/paypal/ipn</path_info>
    <host>mydomain.com</host>
    <remote_addr>xx.xx.xx.xx</remote_addr>
    </url>
    <params>
    <param name="payment_status">Completed</param>
    <param name="payment_type">instant</param>
    <param name="txn_type">web_accept</param>
    ....

    Below this in the XML is another invoice event which clearly shows the refund has been received:

    <event time="2012-03-24 23:23:05">
    <invoice-log-item type="incoming-request">
    <url><method>POST</method>
    <scheme>http</scheme>
    <base_url>/cp</base_url>
    <path_info>/payment/paypal/ipn</path_info>
    <host>mydomain.com</host>
    <remote_addr>xx.xx.xx.xx</remote_addr></url>
    <params>
    <param name="payment_type">instant</param>
    <param name="payment_status">Refunded</param>

    But the invoice is showing as "Paid" and the status of the user is "Paid" which I not what I want. There needs to be a way of marking that transaction as "Not Paid" and denying the user access.
  8. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    What aMember version have you installed? There must be a second record added into user invoice : "Refunded" (displayed in red in admin cp), and customer access must be revoked (look at "Access" records at bottom.
  9. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    If only one copy of your software may belong to customer at a time, you may look to these hooks (from library/Am/Event.php ) :

    PHP:
        /**
         * Access record inserted 
         * NOTE - record may be in not-active state - check dates
         * @param Access access
         */
        
    const ACCESS_AFTER_INSERT 'accessAfterInsert';
        
    /**
         * Access record updated
         * @param Access access
         * @param Access old - record before changes
         */
        
    const ACCESS_AFTER_UPDATE 'accessAfterUpdate';
        
    /**
         * Access record deleted
         * NOTE - record may be in not-active state - check dates
         * @param Access access
         */
        
    const ACCESS_AFTER_DELETE 'accessAfterDelete';
    so you may use functions in the plugin:
    onAccessAfterInsert
    onAccessAfterUpdate
    onAccessAfterDelete

    normally, refund/chargeback must cause onAccessAfterDelete or onAccessAfterUpdate hook called.
  10. betgear

    betgear New Member

    Joined:
    Nov 13, 2008
    Messages:
    10
    Oy SpicyNikNaks, stop hijacking my thread :p

    Alex, can you please take a look at reply #6
  11. alex

    alex Administrator Staff Member

    Joined:
    Jan 24, 2004
    Messages:
    6,020
    :)
    We will prepare public API docs soon.
    You may look at the following classes:
    - application/models/Invoice.php : Invoice class. Invoice->getItems() returns list of InvoiceItem
    - application/models/InvoiceItem.php : InvoiceItem class : here you can get qty and first_price, second_price fields.
    - or inside your hook, use print_rr($event->getInvoice()->toArray()); it will dump properties of object

    - for testing, add the following code snippet into your file application/configs/site.php
    PHP:
    if (@$_GET['xx'] == 2)
    {
            
    // replace 123123 to any invoice_payment_id from your am_invoice_payment table
            
    Am_Di::getInstance()->hook->call(Am_Event::PAYMENT_AFTER_INSERT, array(
                  
    'invoice' => Am_Di::getInstance()->invoiceTable->load(123123),
            ));
    }
    then once your request http://yoursite.com/amember/?xx=2 it will run your hook for afterPaymentInsert and you can dump variables, etc to debug
  12. spicyniknaks

    spicyniknaks New Member

    Joined:
    Feb 27, 2012
    Messages:
    20
    Sorry @betgear, didn't mean to hi-jack.

    I didn't see your post prior to mine - my post took me so long to write I think you had posted during that time.

    I was looking for the answer to the question you had asked and thought the refund question was a logical follow-up.
  13. starwizard

    starwizard New Member

    Joined:
    Dec 26, 2011
    Messages:
    10
    Does the PAYMENT_AFTER_INSERT hook get called for every recurring payment? So, if it is a monthly subscription, for each automatic paypal recurring payment, the hook will be triggered?
  14. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    Yes it is called each time when new payment will be inserted into database.
  15. epaperportal

    epaperportal aMember Pro Customer

    Joined:
    Oct 4, 2011
    Messages:
    6
    hello,
    i have create new plugin for the payment
    when user is signup after successively payment is done and redirect successfully on thank you page BUT my
    payment history is not inserted on the database.
    Please give me the instruction what i can do ?
    I have already add this hook on site.php but they also not called.



    function addAccess(Am_Event_PaymentAfterInsert $event){

    $invoice = $event->getInvoice();

    $products = $invoice->getProducts();

    $product_id = $products[0]->pk();

    if($invoice->getExpectedPaymentsCount() == $invoice->getPaymentsCount() && $product_id == 1){

    // Add access;

    $access = Am_Di::getInstance()->accessRecord;

    $access->begin_date = date('Y-m-d');

    $access->expire_date = '2037-12-31';

    $access->product_id = $product_id;

    $access->user_id = $invoice->user_id;

    $access->insert();

    }

    }

    Am_Di::getInstance()->hook->add('paymentAfterInsert', 'addAccess');
  16. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    Please show your plugin code.
  17. epaperportal

    epaperportal aMember Pro Customer

    Joined:
    Oct 4, 2011
    Messages:
    6
    can i send plugin code to you ?
  18. epaperportal

    epaperportal aMember Pro Customer

    Joined:
    Oct 4, 2011
    Messages:
    6
    payment method :pesapal

    function is called successfully but does not update database status

    site.php

    --------------------------
    if (@$_GET['pesapal_merchant_reference']!="")
    {

    // replace 123123 to any invoice_payment_id from your am_invoice_payment table
    //echo Am_Event::pAYMENT_AFTER_INSERT; exit;
    Am_Di::getInstance()->hook->call(Am_Event::pAYMENT_AFTER_INSERT, array(
    'invoice' => Am_Di::getInstance()->invoiceTable->load('65'),
    ));
    }
    -------
    Please give me solution as soon as possible...
  19. epaperportal

    epaperportal aMember Pro Customer

    Joined:
    Oct 4, 2011
    Messages:
    6
    Please find attached plugin code

    Attached Files:

  20. alexander

    alexander Administrator Staff Member

    Joined:
    Jan 8, 2003
    Messages:
    6,274
    You have function createTransaction commented in your plugin file, that's why transactions are not activated.
    You have to uncomment it and change your Am_Transaction_Esapal class to meet IPN notifications structure.

Share This Page