【问题标题】:Laravel Livewire and Cashier double form submit issueLaravel Livewire 和 Cashier 双表单提交问题
【发布时间】:2020-11-09 06:26:02
【问题描述】:

我正在尝试让 Cashier 使用 Livewire,但我遇到了一个错误,我必须按两次提交按钮才能获得 paymentmethod

在此视频中:https://www.loom.com/share/cb27ce3ae8ab46fab27e68afc7900eb4

我正在尝试dd();以下。

dd($this->paymentmethod, $this->cardHolderName, $this->plan->title, $this->plan->stripe_id);

除了$this->paymentmethod 之外的所有内容都在第一次提交时返回 我必须第二次提交表单,$this->paymentmethod 才能在dd(); 中返回

请注意,我在第二次提交表单时不会刷新页面。


以下是相关代码:

Livewire 视图:

<div>

<h3 class="text-lg leading-6 font-medium text-gray-200">
  Plan {{ $plan->title }} Checkout | ${{ $plan->priceFormat }}
</h3>
          
<form wire:submit.prevent="submitSubscription">
                    @if(Session::has('success'))
                        It submitted!
                    @endif
                    <div id="error-wrapper"></div>
             
<label for="cardHolderName">Name on the card</label>

<input wire:model.lazy="cardHolderName" type="text" id="card-holder-name"/>
       
                        @if(!$cardHolderName)
                            @error('cardHolderName')
                            <p>{{ $message}}</p>
                            @enderror
                        @endif

<label for="card" class="block text-sm font-medium leading-5 text-gray-200">Card Details</label>
                  
  <div wire:ignore id="card-element"/></div>
                  
       
<button id="card-button" type="submit" wire:target="submitSubscription" data-secret="{{ $intent->client_secret }}">Submit</button>

</div>


@push('stripe')
        <script src="https://js.stripe.com/v3/"></script>
    @endpush
    @section('in-page-scripts')
        <script>
            const stripe = Stripe('{{ config('cashier.key') }}');
            const elements = stripe.elements();
            const cardElement = elements.create('card');
          
            cardElement.mount('#card-element');
          
            const cardHolderName = document.getElementById('card-holder-name');
            const cardButton = document.getElementById('card-button');
            const clientSecret = cardButton.dataset.secret;
          
            cardButton.addEventListener('click', async (e) => {
                const { setupIntent, error } = await stripe.confirmCardSetup(
                    clientSecret, {
                        payment_method: {
                            card: cardElement,
                            billing_details: { name: cardHolderName.value }
                        }
                    }
                );
                if (error) {
                    let errorWrapper = document.getElementById('error-wrapper')
                    errorWrapper.textContent = error.error
                    console.info(error)
                } else {
                    //   console.info(setupIntent.payment_method)
           @this.set('paymentmethod', setupIntent.payment_method)
                }
            });
        </script>
    @endsection

Livewire 控制器:

<?php

namespace App\Http\Livewire\Subscription;

use App\Plan;
use Livewire\Component;

class PlansCheckout extends Component {

    public $plan;
    public $error;
    public $cardHolderName;
    public $paymentmethod;

    public function mount(Plan $plan) {
        $this->plan = $plan;
    }

    public function render() {
        return view('livewire.subscription.plans-checkout', [
            'intent' => auth()->user()->createSetupIntent(),
        ]);
    }

    public function submitSubscription() {
        $data = $this->validate([
            'cardHolderName' => 'required',
        ]);

        dd($this->paymentmethod, $this->cardHolderName, $this->plan->title, $this->plan->stripe_id);

        $this->reset();
    }
}

任何有关如何解决此问题的帮助将不胜感激。

【问题讨论】:

  • 试试电汇:target.prevent="submitSubscription"

标签: javascript laravel stripe-payments laravel-cashier laravel-livewire


【解决方案1】:

我认为你的流程是错误的。 $this-&gt;paymentmethod 将不会显示在您的 dd() 中,因为在调用 submitSubscription 时,条带制作的 ajax 仍未完成(因此 @this.set 不要更改公共变量 paymentmethod,这仅在您第二次单击时才会发生)。

从按钮中删除 wire:target="submitSubscription" 并添加以下脚本而不是您的 @this.set()

@this.call('setPayment', setupIntent.payment_method)
                }
            });

所以在你的 livewire 组件中:

public function setPayment($paymentmethod){
    $this->paymentmethod = $paymentmethod;
    $this->submitSubscription();
}

此代码等待 stripe ajax 完成,在您的 livewire 组件中设置支付数据,然后提交订阅。

【讨论】:

    【解决方案2】:

    成功返回令牌后,在最后使用@this.call('add_or_update_payment_method')函数。

    <div>
    
    <h3 class="text-lg leading-6 font-medium text-gray-200">
      Plan {{ $plan->title }} Checkout | ${{ $plan->priceFormat }}
    </h3>
              
    <form wire:submit.prevent="submitSubscription">
                        @if(Session::has('success'))
                            It submitted!
                        @endif
                        <div id="error-wrapper"></div>
                 
    <label for="cardHolderName">Name on the card</label>
    
    <input wire:model.lazy="cardHolderName" type="text" id="card-holder-name"/>
           
                            @if(!$cardHolderName)
                                @error('cardHolderName')
                                <p>{{ $message}}</p>
                                @enderror
                            @endif
    
    <label for="card" class="block text-sm font-medium leading-5 text-gray-200">Card Details</label>
                      
      <div wire:ignore id="card-element"/></div>
                      
           
    <button id="card-button" type="submit" wire:target="submitSubscription" data-secret="{{ $intent->client_secret }}">Submit</button>
    
    </div>
    
    
    @push('stripe')
            <script src="https://js.stripe.com/v3/"></script>
        @endpush
        @section('in-page-scripts')
            <script>
                const stripe = Stripe('{{ config('cashier.key') }}');
                const elements = stripe.elements();
                const cardElement = elements.create('card');
              
                cardElement.mount('#card-element');
              
                const cardHolderName = document.getElementById('card-holder-name');
                const cardButton = document.getElementById('card-button');
                const clientSecret = cardButton.dataset.secret;
              
                cardButton.addEventListener('click', async (e) => {
                    const { setupIntent, error } = await stripe.confirmCardSetup(
                        clientSecret, {
                            payment_method: {
                                card: cardElement,
                                billing_details: { name: cardHolderName.value }
                            }
                        }
                    );
                    if (error) {
                        let errorWrapper = document.getElementById('error-wrapper')
                        errorWrapper.textContent = error.error
                        console.info(error)
                    } else {
                        //   console.info(setupIntent.payment_method)
                        @this.set('paymentmethod', setupIntent.payment_method)
                        @this.call('add_or_update_payment_method')
                    }
                });
            </script>
        @endsection
    
    public $paymentmethod;
    public function updatedPaymentmethod()
        {
            if (filled(auth()->user()->stripe_id)) {
                $this->add_or_update_payment_method();
            } else {
                // notify user error
            }
        }
       
        public function add_or_update_payment_method()
        {
            try {
                if (!auth()->user()->hasPaymentMethod()) {
                    auth()->user()->createOrGetStripeCustomer();
                    auth()->user()->addPaymentMethod($this->paymentmethod);
                    auth()->user()->updateDefaultPaymentMethod($this->paymentmethod);
                } else {
                    auth()->user()->updateDefaultPaymentMethod($this->paymentmethod);
                }
                return true;
            } catch (\Exception $e) {
                return false;
                // error handling
            }
        }```
    

    【讨论】:

      猜你喜欢
      • 2011-11-26
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-14
      • 2021-06-18
      • 2020-08-31
      相关资源
      最近更新 更多