Elsie Hamilton
Elsie Hamilton

Reputation: 155

How to use Braintree Webhooks in Laravel

I am using the Braintree for Payment Process. I have created a subscrition plan and I am using PayPal and Card Payment in My Site. I was able to create a Successful subscription, But I want to show the get the response when the subscription is active/canceled and payment done or not. I know this can be done by webhooks But I am not getting where to start. I am using the laravel Framework. My Client Side code:

<form id="cardForm">
    <div class="panel">
        <header class="panel__header">
            <h1>Card Payment</h1>
        </header>

        <div class="panel__content">
            <div class="textfield--float-label">
                <label class="hosted-field--label" for="card-number"><span class="icon">
         <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
             <path d="M0 0h24v24H0z" fill="none"/>
             <path
                     d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"/>
         </svg></span> Card Number
                </label>
                <div id="card-number" class="hosted-field"></div>
            </div>

            <div class="textfield--float-label">

                <label class="hosted-field--label" for="expiration-date">
           <span class="icon">
          <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
              <path
                      d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H5V9h14v11z"/>
          </svg>
         </span>
                    Expiration Date</label>
                <div id="expiration-date" class="hosted-field"></div>
            </div>


            <div class="textfield--float-label">
                <label class="hosted-field--label" for="cvv">
          <span class="icon">
            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
                <path
                        d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/>
            </svg>
            </span>
                    CVV</label>
                <div id="cvv" class="hosted-field"></div>
            </div>


        </div>

        <footer class="panel__footer">
            <button class="pay-button">Submit</button>
        </footer>
    </div>
</form>


<script>
    var paypalButton = document.querySelector('#paypal');
    var cardButton = document.querySelector('.pay-button');
    var CLIENT_AUTHORIZATION = $('#client').val();
    console.log(CLIENT_AUTHORIZATION);
    braintree.client.create({
        authorization: CLIENT_AUTHORIZATION
    }, function (clientErr, clientInstance) {
        if (clientErr) {
            console.error('Error creating client:', clientErr);
            return;

        }
        braintree.paypal.create({
            client: clientInstance

        }, function (paypalErr, paypalInstance) {

            if (paypalErr) {
                console.error('Error creating PayPal:', paypalErr);
                return;
            }

            paypalButton.removeAttribute('disabled');
            paypalButton.addEventListener('click', function (event) {

                paypalInstance.tokenize({
                    flow: 'vault',
                    enableShippingAddress: false,
                    shippingAddressEditable: false,
                }, function (tokenizeErr, payload) {

                    if (tokenizeErr) {
                        if (tokenizeErr.type !== 'CUSTOMER') {
                            console.error('Error tokenizing:', tokenizeErr);
                            alert(tokenizeErr.message);
                        }
                        return;
                    }

                    paypalButton.setAttribute('disabled', true);
                    console.log('Got a nonce! You should submit this to your server.');
                    console.log(payload.nonce);
                    $.ajax({
                        url: '/subscription',
                        type: 'post',

                        data: {
                            nonce: payload.nonce,
                            payload: payload


                        },
                        success: function (response) {

                            console.log(response);


                        },
                        error: function (response, status, err) {

                        }

                    });

                });

            }, false);

        });

        braintree.hostedFields.create({
            client: clientInstance,
            styles: {
                'input': {
                    'font-size': '16px',
                    'font-family': 'roboto, verdana, sans-serif',
                    'font-weight': 'lighter',
                    'color': 'black'
                },
                ':focus': {
                    'color': 'black'
                },
                '.valid': {
                    'color': 'black'
                },
                '.invalid': {
                    'color': 'red'
                }
            },
            fields: {
                number: {
                    selector: '#card-number',
                    placeholder: '1111 1111 1111 1111'
                },
                cvv: {
                    selector: '#cvv',
                    placeholder: '111'
                },
                expirationDate: {
                    selector: '#expiration-date',
                    placeholder: 'MM/YY'
                },

            }
        }, function (err, hostedFieldsInstance) {
            if (err) {
                console.error(err);
                return;
            }

            hostedFieldsInstance.on('focus', function (event) {
                var field = event.fields[event.emittedBy];

                $(field.container).next('.hosted-field--label').addClass('label-float').removeClass('filled');
            });

            hostedFieldsInstance.on('blur', function (event) {
                var field = event.fields[event.emittedBy];

                if (field.isEmpty) {
                    $(field.container).next('.hosted-field--label').removeClass('label-float');
                } else if (event.isValid) {
                    $(field.container).next('.hosted-field--label').addClass('filled');
                } else {
                    $(field.container).next('.hosted-field--label').addClass('invalid');
                }
            });

            hostedFieldsInstance.on('empty', function (event) {
                var field = event.fields[event.emittedBy];

                $(field.container).next('.hosted-field--label').removeClass('filled').removeClass('invalid');
            });

            hostedFieldsInstance.on('validityChange', function (event) {
                var field = event.fields[event.emittedBy];

                if (field.isPotentiallyValid) {
                    $(field.container).next('.hosted-field--label').removeClass('invalid');
                } else {
                    $(field.container).next('.hosted-field--label').addClass('invalid');
                }
            });

            cardButton.removeAttribute('disabled');
            $('#cardForm').submit(function (event) {
                event.preventDefault();

                hostedFieldsInstance.tokenize(function (err, payload) {
                    if (err) {

                        $('.panel__header > h1').html(err.message);
                        $('.panel__header').css("background", "#D50000 none repeat scroll 0 0");

                        return;
                    }
                    cardButton.setAttribute('disabled', true);
                    $('.pay-button').html("Please Wait ..");
                    $.ajax({
                        url: '/subscription',
                        type: 'post',

                        data: {
                            nonce: payload.nonce,
                            payload: payload


                        },
                        success: function (response) {
                            console.log(response);


                        },
                        error: function (response, status, err) {

                        }

                    });
                });
            });

        });
    });
</script>

My server side code:

public function dropin()
    {
        $clientToken = \Braintree_ClientToken::generate();

        return view('User::user.dropui')->with("client", $clientToken);
    }

    public function subscription(Request $request)
    {


        $result = Braintree_Customer::create(array(


                'email' => '[email protected]',

                'firstName' => 'Aloknotrail ',

                'lastName' => 'Kumar',


        ));

        if($result->success == 1){
            //print_r($result->customer->id);
            $resultcreate = Braintree_PaymentMethod::create([
                'customerId' => $result->customer->id,
                'paymentMethodNonce' => $request->nonce,

                'options' => [
                    'failOnDuplicatePaymentMethod' => true
                ]
            ]);
            if($resultcreate->success == 1){
                //print_r($resultcreate->paymentMethod->token);
                $resultSubscription = Braintree_Subscription::create([
                    'paymentMethodToken' => $resultcreate->paymentMethod->token,
                    'planId' => 'pro'
                ]);


            }else{
                dd($resultcreate);
            }
        }

        dd($resultSubscription);


    }

Upvotes: 1

Views: 926

Answers (2)

Mimarshall
Mimarshall

Reputation: 442

Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.

To create webhooks to track specific changes in subscriptions and transactions, go to the Braintree Control Panel and assign specific triggers to endpoints on your server. When an action occurs (like a transaction being settled), your endpoint will be called with the POST parameters of bt_signature and bt_payload. An example of creating a webhookNotification which contains information about the event, is below: $webhookNotification = Braintree_WebhookNotification::parse( $_POST["bt_signature"], $_POST["bt_payload"] );

$webhookNotification->kind;
# => "subscription_went_past_due"

$webhookNotification->timestamp;
# => Sun Jan 1 00:00:00 UTC 2016

For more information on webhooks, please check out this documentation.

Upvotes: 1

Mina Abadir
Mina Abadir

Reputation: 2981

Webhooks in general are routes in your application that can accept API requests from the payment provider to perform action accordingly.

So in order to start, you need first to define the route, for example:

Route::get('paypal/webhook', 'WebhookController@handle');

Then you create the new WebhookController, that should be responsible for accepting the requests and responds accordingly.

class WebhookController extends Controller
{
    public function handle(Request $request)
    {
         //handle request here
    }
}

In your Braintree settings you should set the webhook endpoint so their API can consume it.

Hope that helps.

Upvotes: 1

Related Questions