StripeInput
Greetings, I would like to create a StripeInput field for the Filament Form Builder. I would like to create a Payment Intent and then use it later to perform payments on the customer. I am currently stuck at the submission process, because the field should tackle into the form submission and after Filament validation do it's magic. Any help is appreciated, and also I would love to know more about the correct way to implement custom fields because I have a lot of ideas that I would like to share as plugins, both for standalone usage on the Filament Form and on the Filament Admin Builder.
14 Replies
essentially the
state
of the field in alpine needs to be entangled
and then the state of the field stores the payment intent ID
and that is accessible to PHP
is there a way to get the nessecary ID for payment purely on the frontend without the backend call?[edited] Still figuring details out. So far, I entangled the state of the field by using [edited] hidden input field. [edited] When changing the input value from the javascript, I had to resort to dispatchEvent an "input" event on the input field so that alpine updates the entangled data. Seems there's also some operations that need to be done on submit, I am still figuring out [edited].
It could be helpful to me to understand if it is possible to pass some object to the instance of the javascript class StripeInput (preferred) or the global instance of Livewire or alpine.js (less preferable) so I don't have to rely on the entanglement system via a proxy input field.
Sorry, I edited the message to shorten it to not tire you with unnecessary details.
Right now I am receiving the ID of the intent, but I cannot pass it back to the Filament Form during the submission, the entangling doesn't work anymore and even livewire global events don't get passed.
can you send the code where you are entangling?
as you see I am entangling input with
{{ $applyStateBindingModifiers('wire:model') }}="{{ $getStatePath() }}"
and this works, but it is not elegant.
the input is used as an hidden vessel to share information between the server and the client.
unfortunately, when you press the submitAction of the Wizard, the entangling stops
one idea I had is this. Remove the submitAction and replace it with a custom action that dispatches an event, this event is catched on the frontend that starts the card verification process. Once the card verification process is finished, an event on the frontend is dispatched that is catched by the backend on the form and the submission is performed. However this flow seems a bit fragile and I need to investigate some steps in it. The problem is also on publishing this component, it can be a difficult to understand workflow (albeit if you are incorporating credit card processing, you have to expect some minor things to change). At the moment the system retrieves the card SetupIntent ID, so it seems like the Stripe part is done!
Also, if I had just to use this on my form, that uses the credit card field in a step, I could tackle into the next step logic and work my magic from there, but again it would not make it general purpose.
I need to be sure the whole process is async, because the card verification process can show some UI depending on the card (for example, if it triggers the Strong Customer Authentication).
you can see I have those setters and getters on the javascript class so I can make
this.state = {...this.state, valid: false, error: event.error.message};
and than I can
in this screenshot a very simplified output with just one step. How über cool is that?
The checkbox on the top says "I don't have the credit card with me, I'll insert it later". It will send you an email and you can get back later to insert your credit card data for registration. As we are talking about a Filament Form, the sky is the limit and the credit card becomes a field just like any other! Unfortunately my specific use case is a bit more complicated because you don't directly pay, instead you register the card for future usage (just like you do on Amazon). But as releasing this as a plugin we can figure out the different modes. Also notice that I am using fake data and working on unsecured localhost via Sail, as I am using a test key.
ok now I feel like an hack. I managed to simply stop the propagation, then doing my magic, then clicking on the submit button again. Is this cheating? Can it be done better? I feel dirty.
the good news is that this double submit workflow also handles the SCA (3D Secure) because it makes it async by using await in the confirmCardSetup.
ah, I miss Angular so much... and I hate Angular so much!!
also I would like to point out:
seems like window.livewire.emit is not catched during submit, I would have preferred to have some extension points in place, but I may simply have made something wrong.
this.state = {...this.state,
as I said is the code that makes the entangling and also doesn't work. Reading the documentation it seems like there is a phase before submission and after validation, but I think I can only access it server side. Even if I could dispatch an event at that point, the server uses code that is sync, while the flow is async and the server would not "await" for the frontend to answer.
Sorry to bother you but I think I need to document all my mental process. It appears evident I am not using the full potential of alpine.js.when i say entangle, i mean entangle in alpine
$wire.entangle()
you dont need a hidden input then
That’s exactly the point that I am missing
I’ll look that up and report.
I also made an example input field to perform a minimal use case debug
The idea is that I can create a JavaScript class instance and pass some sort of reference to the entanglement so I can use that to communicate, but it’s obvious I need to study alpine.js more.
in this minimal use case, I am passing the state in the instance. Then I am changing the state programmatically after 5 seconds. Should that reflect on the server side? If not, what I am not understanding? (please ignore the double root in component, this is a pseudocode example)
i dont know why you are using
class ExampleInput
that is not standard Alpine and is probably breaking it
use Alpine.data()
check the alpine docsExampleInput is very simplified, and of course it would not need a separate javascript class to hold its logic. But, coming back to StripeInput, there's a lot more involved there
So I used the hidden input to bind the state of the object. Also, I've checked out alpine.js "Data Binding" chapter here https://laravel-livewire.com/docs/2.x/properties#data-binding
Livewire
Properties | Livewire
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
and it looks like it binds to any element that dispatches an input event, so it actually needs that element to perform its entangling. Am I missing out something? I am so sorry for tiring you with those questions, I wanted to learn more about Filament Form. I fear that I couldn't model the behavior I need just inlining all the javascript so I used a class.
By the way, thank you very much for pointing me out to
Alpine.data()
. I'll check that out!