1

我正在使用 Braintree 进行付款流程。我创建了一个订阅计划,并且在我的网站中使用 PayPal 和卡付款。我能够创建一个成功的订阅,但是我想在订阅处于活动/取消以及是否完成付款时显示获取响应。我知道这可以通过 webhook 完成,但我不知道从哪里开始。我正在使用 laravel 框架。我的客户端代码:

<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>

我的服务器端代码:

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' => 'alokchaturvedi@globussoft.in',

                '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);


    }
4

2 回答 2

1

全面披露:我在布伦特里工作。如果您还有其他问题,请随时联系支持人员

要创建webhook以跟踪订阅和事务中的特定更改,请转到 Braintree 控制面板并将特定触发器分配给服务器上的端点。当一个动作发生时(比如一个交易被结算),你的端点将被调用 POST 参数bt_signaturebt_payload。下面是创建webhookNotification包含事件信息的示例: $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

有关 webhook 的更多信息,请查看此文档

于 2016-09-15T21:47:57.530 回答
1

Webhook 通常是应用程序中的路由,可以接受来自支付提供商的 API 请求以执行相应的操作。

所以为了开始,你首先需要定义路由,例如:

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

然后你创建新的WebhookController,它应该负责接受请求并做出相应的响应。

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

在您的 Braintree 设置中,您应该设置 webhook 端点,以便他们的 API 可以使用它。

希望有帮助。

于 2016-09-12T12:19:19.323 回答