2016-04-09 30 views
4

只是好奇整合布伦特里,Laravel:与出纳

是否有人使用laravel/cashier-braintree成功整合布伦特里?

我被困在与开头:
$user->newSubscription('main', 'monthly')->create($creditCardToken);

继文档,我想需要类似的东西: $data = [ 'firstName' => $request->first_name, 'lastName' => $request->last_name, ]; $creditCardToken = Auth::id(); $planId = [Plan Id defined in Braintree] $user->newSubscription('main', $planId)->create($creditCardToken, $data);

offical documentation我没有指定任何信用卡信息,它已被弃用。

"Unable to create Braintree customer: Unknown payment_method_nonce.\n Expiration date is required.\n Credit card number is required.\n Credit card must include number, payment_method_nonce, or venmo_sdk_payment_method_code."

哎呦!因此,让我们添加这个反正: $data = [ 'firstName' => $request->first_name, 'lastName' => $request->last_name, 'creditCard' => [ 'number' => $request->number, 'expirationMonth' => $request->month, 'expirationYear' => $request->year, 'cvv' => $request->cvv, 'billingAddress' => [ 'firstName' => 'Jen', 'lastName' => 'Smith', 'company' => 'Braintree', 'streetAddress' => '123 Address', 'locality' => 'City', 'region' => 'State', 'postalCode' => '12345', ], ], ];

而现在,我得到的是:
"Unable to create Braintree customer: Unknown payment_method_nonce."

有官方Braintree_Customer::create()一些有用的信息。而且,实际上,您可以轻松实施Braintree,而不需要 cachier,如braintree_php_guide

那么是什么?我必须丢弃 Cachier

+0

我的坏,它的标记[不稳定(https://github.com/laravel/cashier-braintree ) –

回答

1

与braintree收银员已经工作(至少对我来说)。开始对我来说也有点困惑。

背后的想法是,用户将他的关键信用卡数据直接发送给braintree而不是你。所以你需要一个表单,它将数据发送给Braintree(通过javascript)。之后,你会收到一个令牌(payment_method_nonce)。之后您必须使用此令牌为用户开票。

所以我在Laravel 5.2中以下列方式实现它。这个实现有点复杂,因为我想使用引导格式。通过使用较旧的javascript v2 SDK,您可以更轻松地完成此操作(具有较低的灵活性)。

我的实现:

/app/Http/routes.php

Route::get  ('upgrade', '[email protected]')->name('account.upgrade'); 
Route::post  ('upgrade', '[email protected]'); 

/app/Providers/AppServiceProvider.php

class AppServiceProvider extends ServiceProvider 
{ 
    /** 
    * Bootstrap any application services. 
    * 
    * @return void 
    */ 
    public function boot() 
    { 
     \Braintree_Configuration::environment(env('BRAINTREE_ENV')); 
     \Braintree_Configuration::merchantId(env('BRAINTREE_MERCHANT_ID')); 
     \Braintree_Configuration::publicKey(env('BRAINTREE_PUBLIC_KEY')); 
     \Braintree_Configuration::privateKey(env('BRAINTREE_PRIVATE_KEY')); 

     \Laravel\Cashier\Cashier::useCurrency('eur', '€'); 

     // .... 
    } 
    // ... 
} 

/应用/ HTTP /Controllers/AccountController.php

<?php 

namespace App\Http\Controllers; 

use Illuminate\Http\Request; 
use App\Http\Controllers\Controller; 

class AccountController extends Controller 
{ 
    // .. 

    public function getUpgrade() 
    { 
     return view('account.upgrade'); 
    } 

    public function postUpgrade(Request $request) 
    { 
     $plan = 'myservice-yearly'; 

     $nonce = $request->input('payment-method-nonce'); 

     // optional user data 
     $user = $request->user(); 
     $user_data = [ 
      'id' =>  'myservice_'.$user->id, 
      'email' => $user->email, 
     ]; 

     // optional subscription data 
     $subscription_data = []; 

     $user->newSubscription('main', $plan) 
      ->create($nonce, $user_data, $subscription_data); 

     return 'thank-you'; 
    } 
} 

/resources/views/account/upgrade.blade。PHP

<h1>Upgrade</h1> 

<button class="btn btn-primary" id="paypal_button"><i class="fa fa-paypal"></i> Mit PayPal zahlen</button> 
<hr> 
{!! Form::open(['route' => 'account.upgrade', 'class'=>'panel-body', 'id'=> 'paymentform']) !!} 
    <div class="row"> 
     <div class="form-group col-xs-4"> 
      <label class="control-label">credit card number</label> 
      <!-- Hosted Fields div container --> 
      <div class="form-control" id="card-number"></div> 
      <span class="helper-text"></span> 
     </div> 
    </div> 
    <div class="row"> 
     <div class="form-group col-xs-4"> 
      <div class="row"> 
       <label class="control-label col-xs-12">expiration date</label> 
       <div class="col-xs-6"> 
        <!-- Hosted Fields div container --> 
        <div class="form-control" id="expiration-month"></div> 
       </div> 
       <div class="col-xs-6"> 
        <!-- Hosted Fields div container --> 
        <div class="form-control" id="expiration-year"></div> 
       </div> 
      </div> 
     </div> 
    </div> 

    <label class="control-label">security code (CCV)</label> 
    <div class="row"> 
     <div class="form-group col-xs-2"> 
      <!-- Hosted Fields div container --> 
      <div class="form-control" id="cvv"></div> 
     </div> 
    </div> 

    <button type="button" class="btn btn-primary">Pay with <span id="card-type">credit card</span></button> 

    <input type="hidden" name="payment-method-nonce" value=""> 
{!! Form::close() !!} 

<!-- Load the Client component. --> 
<script src="https://js.braintreegateway.com/web/3.4.0/js/client.min.js"></script> 

<!-- Load additional components if desired. --> 
<script src="https://js.braintreegateway.com/web/3.4.0/js/hosted-fields.min.js"></script> 
<script src="https://js.braintreegateway.com/web/3.4.0/js/paypal.min.js"></script> 

<script> 
    $(function(){ 
     braintree.client.create({ 
      authorization: '{{ Braintree\ClientToken::generate() }}' 
     }, function (err, clientInstance) { 
      if (err) { 
       console.error(err); 
       return; 
      } 

      braintree.paypal.create({ 
       client: clientInstance 
      }, function (err, paypalInstance) { 
       $('#paypal_button').click(function() { 
        // Tokenize here! 
        paypalInstance.tokenize({ 
         flow: 'vault', // Required 
         billingAgreementDescription: 'MyService Premium' 
        }, function (err, payload) { 
         console.log(payload); 
         $('input[name="payment-method-nonce"]').val(payload.nonce); 
         $('#paymentform').submit(); 
        }); 
       }); 
      }); 

      braintree.hostedFields.create({ 
       client: clientInstance, 
       styles: { 
        'input': { 
         'font-size': '14px', 
         'font-family': 'helvetica, tahoma, calibri, sans-serif', 
         'color': '#3a3a3a' 
        }, 
        ':focus': { 
         'color': 'black' 
        } 
       }, 
       fields: { 
        number: { 
         selector: '#card-number', 
         placeholder: '4111 1111 1111 1111' 
        }, 
        cvv: { 
         selector: '#cvv', 
         placeholder: '123' 
        }, 
        expirationMonth: { 
         selector: '#expiration-month', 
         placeholder: 'MM' 
        }, 
        expirationYear: { 
         selector: '#expiration-year', 
         placeholder: 'JJ' 
        } 
       } 
      }, function (err, hostedFieldsInstance) { 
       if (err) { 
        console.error(err); 
        return; 
       } 

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

        if (field.isValid) { 
         if (event.emittedBy === 'expirationMonth' || event.emittedBy === 'expirationYear') { 
          if (!event.fields.expirationMonth.isValid || !event.fields.expirationYear.isValid) { 
           return; 
          } 
         } else if (event.emittedBy === 'number') { 
          $('#card-number').next('span').text(''); 
         } 

         // Apply styling for a valid field 
         $(field.container).parents('.form-group').addClass('has-success'); 
        } else if (field.isPotentiallyValid) { 
         // Remove styling from potentially valid fields 
         $(field.container).parents('.form-group').removeClass('has-warning'); 
         $(field.container).parents('.form-group').removeClass('has-success'); 
         if (event.emittedBy === 'number') { 
          $('#card-number').next('span').text(''); 
         } 
        } else { 
         // Add styling to invalid fields 
         $(field.container).parents('.form-group').addClass('has-warning'); 
         // Add helper text for an invalid card number 
         if (event.emittedBy === 'number') { 
          $('#card-number').next('span').text('Looks like this card number has an error.'); 
         } 
        } 
       }); 

       hostedFieldsInstance.on('cardTypeChange', function (event) { 
        // Handle a field's change, such as a change in validity or credit card type 
        if (event.cards.length === 1) { 
         $('#card-type').text(event.cards[0].niceType); 
        } else { 
         $('#card-type').text('Card'); 
        } 
       }); 

       $('#paymentform').submit(function (event) { 
        var value = $('input[name="payment-method-nonce"]').val(); 
        console.log(event); 
        console.log('nonce=' + value); 

        if (value == '') { 
         //console.log('preventing'); 
         event.preventDefault(); 
         hostedFieldsInstance.tokenize(function (err, payload) { 
          if (err) { 
           console.error(err); 
           return; 
          } 

          // This is where you would submit payload.nonce to your server 
          $('input[name="payment-method-nonce"]').val(payload.nonce); 
          $('#paymentform').submit(); 
         }); 
        } /*else { 
         console.log('should submit'); 
        }*/ 
       }); 
      }); 
     }); 
    }); 
</script> 

参见: