Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Stripe app: custom charge handler and webhooks handler

edited October 2014 in Apps

In the stripe app, what does the custom charge handler do, and how does it differ from what the webhooks handler does?


  • The custom charge handler gets notified by the Stripe app when a charge has been made, so you can act on the charge itself (e.g., deliver the goods). It receives a Stripe_Charge object with this info, as well as a stripe\Payment object which is an Elefant model.

    The webhooks handler gets passed event notifications that Stripe sends for any account activity, which can include other actions like refunds, new account creations, subscription payment failures, etc. This receives a more general Stripe_Event object instead.

  • Thanks. Do you have suggestions for how to test the charge handler? We can test the webhooks handler from the stripe control panel, which sends a sample event. Is there a way to do the same for the charge handler?

    Also, in the readme file there is this code for a sample subscription form:

    echo $this->run ('stripe/payment', array (
        'plan' => 'basic',
        'callback' => function ($customer, $payment) {
            info ($customer);
            info ($payment);

    What would you do in the callback function as opposed to what you would do in the charge handler?

  • You should be able to pass any callable as the callback parameter, so you could define it as a class method elsewhere then refer to that, e.g.:

    class MyApp {
        public static function payment_handler ($customer, $payment) {
            info ($customer);
            info ($payment);
    echo $this->run ('stripe/payment', array (
        'amount' => 1000,
        'description' => 'Description here',
        'callback' => 'MyApp::payment_handler'

    Technically, you could implement some of the same logic in the webhooks handler, since it receives events for all of these too, except that it happens outside of the current request. So things like sending a confirmation email will work fine, but responding to the current user will not be possible there.

    The charge handler is actually just tied to the stripe/button handler, so it doesn't get called when you implement your own handler with stripe/payment. The embeddable button is okay for simple tasks, but generally I find I use stripe/payment and a custom callback for anything more complex.

    Hope that helps sort out the differences!

  • Thanks. Another question: is there a flag in either the $customer or $payment object that indicates success or failure?

    Or more broadly, what's the best way to implement error handling? For instance, if I put in an expiration year of, say, 2013, the app handles it nicely by reloading the form with the message that "Your card's expiration year is invalid" However, if I use the credit card number that stripe has designated for testing "card declined" responses, the form doesn't reload and just gives the message "Unable to save customer info at this time. Please try again later. " The error log does report "Error calling Stripe_Customer::create(): Your card was declined" but the form doesn't reload or give a helpful message to the customer.

  • It looks like error handling could be improved, to be honest. Right now it just returns the error you see. A better approach would probably be to pass an 'error' parameter as an additional callback, and only fall back on the default handling that's there now if no 'error' parameter is set.

  • I like the way the form displays the error messages for, e.g., invalid expiration year. How would I go about getting it to display the other messages (like "credit card declined"). I'm looking through handlers/payment.php but I don't see where they're handled differently.

  • Those messages are returned from Stripe.createToken in js/payment.js. For the handler to display an error message like that, you would have to set an error parameter and re-render the form. On line 180 you could try this:

    $form->data['charge_failed'] = true;
    $form->data['error'] = 'Error message here';
    return false;

    Then in views/payment.html check for it and display:

    <p class="payment-errors">{% if error %}{{error}}{% end %}</p>

    I didn't have a chance to test it, but let me know if that works.

  • I'm trying it first as an existing customer and found I needed to add the code at line 104. I used $form->data['error'] = $e->getMessage ();, hoping that I can trust Stripe's error messages.

    I also found I needed to toggle display in the view; I'm doing that like so at the moment:

    <p class="payment-errors"{% if error %} style="display: block;"{% end %}>{% if error %}{{ error }}{% end %}</p>

    When the form reloads with a createToken error the fields remain filled in. Would it be a security risk (or are there other reasons not) to add, e.g., name="cc_number" value="{{ cc_number }}" to the input fields in the view?

  • Alternatively, is there a way to send more errors to Stripe.createToken in js/payment.js?

  • I'm working on some other improvements to the Stripe app as well, so I'll be testing this out soon and let you know what I can figure out.

  • Awesome!

Sign In or Register to comment.