I'm creating a managed account in Stripe and for some reason, when I create an account it creates two in my dashboard.
This is in Laravel. Here is my code:
$user = Auth::user();
//create them a connect account
$account = \Stripe\Account::create(
array(
"country" => "GB",
"managed" => true,
"external_account" => request('stripeToken'),
"legal_entity[type]" => $user->legal_entity_type,
"legal_entity[first_name]" => $user->name,
"legal_entity[last_name]" => $user->last_name,
"tos_acceptance[date]" => $user->tos_acceptance_date,
"tos_acceptance[ip]" => $user->tos_acceptance_ip,
"legal_entity[dob][day]" => $user->dob_day,
"legal_entity[dob][month]" => $user->dob_month,
"legal_entity[dob][year]" => $user->dob_year,
"legal_entity[address][city]" => $user->address_city,
"legal_entity[address][line1]" => $user->address_line1,
"legal_entity[address][postal_code]" => $user->address_postal_code,
)
);
//grab the stripe users ID, secret key and publishable key
$acc_id = $account->id;
$secret_key = $account->keys->secret;
$publishable = $account->keys->publishable;
//update the users table to reflect the changes
$user->stripe_id=$acc_id;
$user->stripe_secret=$secret_key;
$user->stripe_key=$publishable;
$user->save();
return redirect()->action('HomeController#index');
I create the managed account with all the required information (including bank token created from previous form and submitted) then update my users tables with the stripe id etc and save it.
However when I go to my Stripe dashboard I have two entries with different account ID's but all the same details.
Any advice where I'm going wrong would be great
When I die and dump the account ID it's always the second account ID.
Edit: The first account never receives the External Account attribute, but the second account in the dashboard does, and that's the one that ends up being attributed in the users table as the stripe_id
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script>
Stripe.setPublishableKey('{{ config('services.stripe.key') }}');
function stripeResponseHandler(status, response) {
// Grab the form:
var $form = $('#bank-account-form');
if (response.error) { // Problem!
// Show the errors on the form:
$form.find('.bank-errors').text(response.error.message);
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
}
$(document).ready(function () {
$("#bank-account-form").submit(function (event) {
// disable the submit button to prevent repeated clicks
$('.submit-button').attr("disabled", "disabled");
// bank account parameters
var bankAccountParams = {
country: $('.country').val(),
currency: $('.currency').val(),
//routing_number: $('.routing-number').val(),
account_number: $('.account-number').val(),
account_holder_name: $('.account-holder-name').val(),
account_holder_type: $('.account-holder-type').val()
}
if ($('.routing-number').val() != '') {
bankAccountParams['routing_number'] = $('.routing-number').val();
}
// createToken returns immediately - the supplied callback submits the form if there are no errors
Stripe.bankAccount.createToken(bankAccountParams, stripeResponseHandler);
});
});
</script>
Thanks,
Your backend code for creating the managed account is being called twice, once without the stripeToken POST parameter and once with it.
My guess is that you have a client-side form using Stripe.js to collect the user's bank account information, and there is an issue with the form where the browser submits it twice, once without the token and once with it.
In your form's event handler, make sure that you disable the default submission by calling preventDefault(); on the submit event and/or returning false in the handler.
The form should only be submitted by Stripe.js' own callback, when the token has been created.
Check if your browser network request see if its sending multiple requests. Any javascript error or redirection could be cause of the issue, as php code looks ok.
Related
I am hoping someone can help me here.
I am trying to process subcription payments through stripe I have code that redirects you to the checkout once a button is clicked:
<script>
var stripe = Stripe('pk_test_CJ3p2EuKzHOC0mQrx9AIDZ3R00TR4ysmyS');
document.getElementById("checkout-button").addEventListener('click', function () {
stripe.redirectToCheckout({
items: [{
// Define the product and plan in the Dashboard first, and use the plan
// ID in your client-side code.
plan: 'plan_Fd6dQD8JT0sl0C',
quantity: 1,
}],
successUrl: 'https://www.example.com/success',
cancelUrl: 'https://www.example.com/cancel'
});
});
</script>
I then have set up a webhook to do some processing once this has completed:
<?php
require_once('vendor/autoload.php');
Stripe\Stripe::setApiKey("TEST KEY");
// retrieve the request's body and parse it as JSON
$body = #file_get_contents('php://input');
$event_json = json_decode($body);
// for extra security, retrieve from the Stripe API
$event_id = $event_json->id;
$event = \Stripe\Event::retrieve($event_id);
// This will send receipts on succesful invoices
if ($event->type == 'invoice.payment_succeeded') {
include 'email_template_functions/email_function.php';
include 'email_template_functions/password_reset_email_templatetest.php';
sendemail('triggertraders.com','richard#triggertraders.com','Bluebanana1995',465,'richard#triggertraders.com', 'Richard','rglass5565#gmail.com','richard#triggertraders.com',
'Information','Reset Password Trigger Trader','This has worked!!','This is the body in plain text for non-HTML mail clients');
}
So this works fine and the payments are going through to stripe its the next step I am wondering about.
I have a entity table in my database that contains all of the 'client' data which has an entity_id. I am trying to figure out a way to link the stripe customer_id to my entity_id in my local database so I can update their account when a payment is made but I cant see how I can do this.
Is there some way I can send my own entity_id to stripe when a payment is set up so when I retrive that data from the webhook and can update my database correctly?
I found this https://stripe.com/docs/stripe-js/reference#stripe-redirect-to-checkout it makes reference to clientReferenceId which I can use to store the ID that i need.
<script>
var stripe = Stripe('pk_test_CJ3p2EuKzHOC0mQrx9AIDZ3R00TR4ysmyS');
document.getElementById("checkout-button").addEventListener('click', function () {
stripe.redirectToCheckout({
items: [{
// Define the product and plan in the Dashboard first, and use the plan
// ID in your client-side code.
plan: 'plan_Fd6dQD8JT0sl0C',
quantity: 1,
}],
clientReferenceId: '123',
successUrl: 'https://www.example.com/success',
cancelUrl: 'https://www.example.com/cancel'
});
});
</script>
I then can use this in my webhook - anybody know of any other ways to do this?
When a user tries to connect my Zapier app, I'll ask for a login. I have used custom authentication, you can see the code below.
const testAuth = (z , bundle) =>
{
var email = bundle.authData.email;
var password = bundle.authData.password;
return z.request({
method: 'POST',
url: 'http://mysite/check_login',
}).then((response) => {
if (response['status'] === 201) {
throw new Error('Your credentials is not match with our database');
}
else
{
var obj = JSON.parse( response.content );
var user_id =obj.user_id;
return user_id;
}
});
This is run successfully, now I want to use this return data user_id in
trigger page(list.js) code listed below,
const list = (z, bundle) => {
//I WANTS TO USE THAT USER_ID OVER HERE
//USER_ID=;
const promise = z.request('http://mysite/list_data/'+USER_ID,
{
params: {}
});
return promise.then((response) => response.json);
};
Please help me out how to access auth response in trigger file.
Create a dynamic dropdown field for a trigger like below screnshot
to access user_id in a perform API call.
Here is an example app that utilizing dynamic dropdown feature:
https://github.com/zapier/zapier-platform-example-app-dynamic-dropdown
More helpful articles:
https://platform.zapier.com/cli_tutorials/dynamic-dropdowns
https://platform.zapier.com/cli_docs/docs#dynamic-dropdowns
David here, from the Zapier Platform team. Great question!
Normally, computed fields would be the answer here, but it's not currently possible to use those outside of OAuth.
In your case, there are two options:
If there's an easy and obvious way for the user to manually supply their id, then add it to the auth fields use it as needed
Otherwise, you'll need to call the login endpoint before you run each trigger to fetch the user id. You've got 30 seconds of execution time, so doing a second API request should be doable.
Yes Sure, Rather than sending user_id that is returned by the auth response, in sending bundle.authData.email at the end of the URL.
const list = (z, bundle) => {
var email=encodeURIComponent(bundle.authData.email);//Like this
const promise = z.request('http://mysite/list_data/'+email,
{
params: {}
});
return promise.then((response) => response.json);
};
Scenario: A customer can refer a client to another customer.
Each referral needs to be stored in a DB table row. The customer receiving the referral should see a notification for the event.
Create a new referral and dispatch the event:
$totalRefers = [];
foreach ($array as $to) {
$refer = new ClientReferral;
$refer->user_id = $user_id;
$refer->by = $by;
$refer->to = $to;
$refer->save();
array_push($totalRefers, $refer);
ReferralSent::dispatch($refer); // Here is the Event
}
return response()->json([
'status' => 'Success',
'message' => 'Client referred successfully to selected professionals.',
'data' => $totalRefers
], 200);
The event broadcastOn() method:
public function broadcastOn() {
return new PrivateChannel('referral.' . $this->referral->id);
}
The channel:
Broadcast::channel('referral.{id}', function ($user, $id) {
// let's say it's true for the time being
return true;
});
And the request is an Ajax POST so in the success callback:
console.log('referral created');
res.data.forEach(function(entry) {
// window.custom.userId is the authenticated user ID:
if (entry.refer_to == window.custom.userId) {
window.Echo.private('referral.' + entry.id).listen('ReferralSent', ({data}) => {
console.log('You have received a new referral');
});
}
});
Now the issue with the current code is that the receiver cannot subscribe to this channel because the event is created dynamically, and I cannot make the channel name static because the referral came in at run time.
How can a receiver subscribe and listen to dynamic events?
With this logic, I want to get that specific referral and its data to show it in the notification tray in HTML.
How can I achieve this?
The event shown in the question broadcasts to a channel for that specific referral entity only. However, the receiver that subscribes to this channel should receive events for all referral entities referred to them.
Instead of creating the channel context for the referral entity itself, publish to a channel designated for the user that receives the referral. I'm guessing that $referral->to contains that user's ID:
public function broadcastOn()
{
return new PrivateChannel('referral.' . $this->referral->to);
}
Update the channel to authorize the current user based on the ID of the user that receives the referral:
Broadcast::channel('referral.{refereeId}', function ($user, $refereeId) {
return $user->id == $refereeId;
});
And, on the client-side, listen on the same channel:
window.Echo.private('referral.' + window.custom.userId)
.listen(e => console.log(e.referral));
Because we're not listening for a specific referral ID anymore, we can initialize the Echo subscriber during the page load instead of in the AJAX response callback.
Broadcast events are designed to be useful for real-time actions outside the normal request/response cycle (including AJAX requests). In the case of this question, we want to start Echo listeners for every customer when the page loads—not after a specific request—so that they can receive notifications any time another customer refers a client to them.
The flow looks like this:
Customer 1 and Customer 2 both open the app, which starts Echo on the client-side.
Customer 1 creates a referral for Customer 2.
Customer 1's browser sends an AJAX request to save the referral.
Laravel publishes the event to Customer 2's channel.
Customer 2's browser receives the event through Echo, which is listening on that channel.
The code you wrote to handle that event creates a notification in Customer 2's browser.
I've yet to find an answer to what should be a very straightforward approach to using Stripe (in my opinion). Using Stripe Checkout, how can I allow a person to pay for a product that I already have created in my "Products" section of the dashboard? All documentation that I have found shows how to retrieve product data, etc., and that's great, but it doesn't actually explain how to allow the customer to purchase the product with Checkout. I'm using PHP, but would be more than happy to see any examples in any language to follow the trajectory.
If you are attempting to do this using checkout.js or stripe elements, it is not possible. You will need to handle this server side by:
First get a token that's a representation of the card the customer submitted using Stripe Elements
subscribe
Script:
$('.btn-save-sub').click(function () {
//if your customer has chosen a plan, for example
var plan = $("#plan_id").val();
var stripe = Stripe(//your public key here );
var elements = stripe.elements();
/**create and mount cc and cc exp elements**/
var card = elements.create('card'); //complete card element, can be customized
card.mount('#card-element');
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
}else{
displayError.textContent = '';
}
});
var form = document.getElementById('subscription_add_new_source');
stripe.createToken(card).then(function(result) {
if (result.error) {
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
}else{
//post result.token.id and plan_id to your server, this token represents the card you will be using
}
});
});
Now, server side you have a token and a plan_id (if you've decided to allow customer to select a plan). Now we will subscribe the customer to the plan using stripe's PHP Bindings
//you have posted a plan_id to be used, you will create a subscription for that plan id, create a card objecting using the token you have, and attach that card as a default source to the stripe customer
$stripe_customer= //retrieve it, if you don't have one, create it
Create customer via stripe API
Once you have your customer you will first create a card object and assign that as the default source:
//create new card
$new_card = $stripe_customer->sources->create(array('sources'=>$posted_token));
//assign newly created card as customer's default source
//subscriptions can only charge default sources
$stripe_customer->default_source = $new_card->id;
//finally, create a subscription with the plan_id
$subscription = \Stripe\Subscription::create(
array(
'customer' => $stripe_customer->id,
'items' => array(
array(
'plan' => $posted_plan_id,
)
),
'trial_end' =>$end // represents the first day a customer will be charged for this plan, pass a timestamp
)
);
For some reason, some parameters such as amount, and description are not being passed on from the Form to the Controller.
The token is generated and the email is sent too, but not the other params.
In order for the Payment to work I have to enter manually the amount at the controller.
<form action="checkout" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key= "pk_test_zOi8g9ztDo1HNeC6iFFTWqwk"
data-amount="1500"
data-name="Demo Site"
data-description="2 shoes ($20.00)"
data-image="/128x128.png">
</script>
</form>
=====================================
public function PostPaymentData(){
Stripe::setApiKey('sk_test_CvCavCI3G4onNbKxZEaNzkvZ');
// get the data submitted by the CHECK OUT Form
$token = Input::get('stripeToken'); (it gets it)
$amount = Input::get('amount'); (it does not get it)
$description = Input::get('description');(it does not get it)
echo "the amount is . $amount"; //nothing
echo "the description is $description"; // nothing
print_r(input::all()); // it just prints the token and the email
// create the charge on STRIPE servers. This will charge the credit card
try {
$charge = Stripe_Charge::create(array(
"amount" => 1800, // amount in cents, again (I have to enter it manually because $amount = ' ';
"currency" => "usd",
"card" => $token,
"description" => "holycow#gmail.com")
);
}
catch(Stripe_CardError $e) {
// Since it's a decline, Stripe_CardError will be caught
dd($e);
=================================================
Route::get('payments/getpaymentpage', array(
'as'=>'getpaymentpage',
'uses'=>'StripePay#getPaymentPage'
));
Route::post('payments/checkout', array(
'as'=>'checkout',
'uses'=>'StripePay#PostPaymentData'
));
My config for Stripe:
In the providers:
'Abodeo\LaravelStripe\LaravelStripeServiceProvider'
In the composer json
"stripe/stripe-php": "1.*",
"abodeo/laravel-stripe": "dev-master"
Well, it was the support staff from Stripe (very kind people) who has given me the answer:
It's actually expected that the amount doesn't get sent with the token to your server. If it did, the user could easily tamper with it via developer tools or writing javascript snippets, etc. Usually you'll want the price of something to be in your database somewhere (a product or whatever you're selling) and look it up again once you receive the token to get the authoritative price.
But sometimes you've got a situation where the user specifies the price somehow, and that is intentional. In that case I suggest making a hidden form element:
And then populating that with JavaScript using a callback. If you're using Stripe.js you already have a response handler you can use for this, just populate the field before you POST your data. If you're using Stripe Checkout, then you can use the token callback on the handler using the custom integration.