Integrate iDeal with Stripe Connect To Split Payments - stripe-payments

I'm running a marketplace website using Dokan Pro where I have integrated Stripe Connect. Now I want to integrate iDeal with it but they don't have it officially so I'm following Stripe's documentation to do some custom coding but I'm not able to achieve anything so far.
Stripe provided me this documentation:
https://stripe.com/docs/connect/direct-charges#create-a-charge
There's an official plugin on Stripe For Woocommerce that also has iDeal option but the problem is that it doesn't split payment because it doesn't work with Stripe Connect. I did try to edit it's code but it gives me an error when I send the application_fee parameter. Here's the code:
public function create_source( $order ) {
$currency = $order->get_currency();
$return_url = $this->get_stripe_return_url( $order );
$post_data = array();
$post_data['amount'] = WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency );
$post_data['currency'] = strtolower( $currency );
$post_data['type'] = 'ideal';
$post_data['application_fee_amount'] = '10';
$post_data['owner'] = $this->get_owner_details( $order );
$post_data['redirect'] = array( 'return_url' => $return_url );
if ( ! empty( $this->statement_descriptor ) ) {
$post_data['statement_descriptor'] = WC_Stripe_Helper::clean_statement_descriptor( $this->statement_descriptor );
}
WC_Stripe_Logger::log( 'Info: Begin creating iDeal source' );
return WC_Stripe_API::request( apply_filters( 'wc_stripe_ideal_source', $post_data, $order ), 'sources' );
}
Any help would be appreciated.

Assumption: I'm assuming for "split payments" you mean to handle when a customer does a single order/payment to your platform which includes goods/services from more than one provider. You need to allocate the payment and send some of it to more than one destination account.
A couple of items that I think are making things difficult for you:
Rather than Sources, I'd recommend looking at the updated Payment Intents guide for iDEAL. You should find this aligns much better with all the most recent documentation across Stripe's API.
If you're intending to split payments to multiple recipients, you will not be able to do so with direct charges. Instead, you should use "Separate Charges & Transfers" to allow you to send portions of the payment to more than one provider of goods/services.
On server:
// Create a PaymentIntent:
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => 10000,
'currency' => 'eur',
'payment_method_types' => ['ideal'],
'transfer_group' => 'YOUR_ORDER_ID_123',
]);
// Send $paymentIntent->client_secret to the client
On client:
//HTML
<div id="ideal-bank-element">
<!-- A Stripe Element will be inserted here. -->
</div>
//JS
// Create an instance of the idealBank Element
var idealBank = elements.create('idealBank', options);
// Add an instance of the idealBank Element into
// the `ideal-bank-element` <div>
idealBank.mount('#ideal-bank-element');
...
stripe.confirmIdealPayment(
'{{PAYMENT_INTENT_CLIENT_SECRET}}',
{
payment_method: {
ideal: idealBank,
billing_details: {
name: accountholderName.value,
},
},
return_url: 'https://your-website.com/checkout/complete',
}
);
On server, later:
// Create a Transfer to a connected account (later):
$transfer = \Stripe\Transfer::create([
'amount' => 7000,
'currency' => 'eur',
'destination' => 'acct_123',
'transfer_group' => 'YOUR_ORDER_ID_123',
]);
// Create a second Transfer to another connected account (later):
$transfer = \Stripe\Transfer::create([
'amount' => 2000,
'currency' => 'eur',
'destination' => 'acct_456',
'transfer_group' => 'YOUR_ORDER_ID_123',
]);

Related

How to capture funds later when using Stripe's Checkout feature?

I am using Stripe's Checkout feature. My product takes a few minutes to generate, so I want to place a hold on the funds, only charging the customer once their product is ready. Is it possible to do so without refactoring away from using this feature?
This code works for me:
<?php
$amount = 50;
$stripe = new \Stripe\StripeClient(env('STRIPE_SECRET'));
$session = $stripe->checkout->sessions->create([
'payment_method_types' => ['card'],
'success_url' => 'reservation.success'.'?id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'reservation.cancel',
'payment_intent_data' => [
'capture_method' => 'manual',
],
'line_items' => [[
'price_data' => [
'currency' => "eur",
'product_data'=> [
'name'=> "My awesome product",
],
'unit_amount'=> $amount * 100,
],
'quantity' => 1
]],
'mode' => 'payment',
]);
return redirect()->to($session->url);
This was done in laravel. You might need to adapt it a little to your needs.
Of course you need to
adapt $amount to the amount you want to collect in €.
change the currency if you need to
set the route for success_url
set the route for cancel_url
After calling this code the user is redirected to the session url, to make the payment, which is then reserved on his card.
You can then capture the payment later via:
<?php
$stripe = new \Stripe\StripeClient(env('STRIPE_SECRET'));
$session_id = 'THE_CHECKOUT_SESSION_ID';
$payment_intent = $stripe->checkout->sessions->retrieve($session_id)-payment_intent;
$intent = \Stripe\PaymentIntent::retrieve($payment_intent);
// Capture all
$intent->capture();
// Alternative: Capture only a part of the reserved amount
// $intent->capture(['amount_to_capture' => 750]);
See also https://stripe.com/docs/payments/capture-later

Stripe - Cannot charge a customer that has no active card

I have the follow block of PHP code which generates a new Stripe customer using a token, since i don't want to handle the card details on my server
$stripe_customer = \Stripe\Customer::create(array(
'source' => $token,
'description' => $displayname,
'metadata' => array('BHAA_ID'=>$bhaa_id),
'email' => $email
)
);
$stripe_customer_id=$stripe_customer->id;
I then attempt to register the card with these calls
$customer = \Stripe\Customer::retrieve($stripe_customer_id);
$card = $customer->sources->create(array("source" => $token));
The final step is to then charge the created customer like this using the customer id
// https://stripe.com/docs/api?lang=php#create_charge
$charge = \Stripe\Charge::create(array(
'amount' => $amount*100,
'currency' => 'eur',
'customer' => $stripe_customer->id,
'description' => $booking_description,
'metadata' => array("booking_id" => $booking_id, "event_name" => $booking_description),
'statement_descriptor' => "abc",
'receipt_email' => get_userdata($user_id)->user_email
));
This was working, but i recently updated to the 3.5.0 version of the stripe PHP API. I'm now getting this error
Booking could not be created:
Connection error:: "Cannot charge a customer that has no active card"
From what i can make out, it now seems that I have to register a card with the customer but I can't find any examples of this.
Any advise would be appreciated.
EDIT - Add stripe dashboard details
From the stripe dashboard, I can see that my customer is registered. This is in the response log
id: cus_7Xq5jNrrLfv73U
object: "customer"
account_balance: 0
created: 1450292050
currency: null
default_source: null
delinquent: false
description: "Web Master"
This is a screen shot of the 'Register Card' request. I can see that the 'customer id' is present in the URL, but the source parameter is not present as a Query Parameter or in the post body.

Stripe get customer email address

I'm trying to yet up a subscription using Stripe checkout.js and then using PHP to Subscribe customers. My problem is getting their email address. Can't find anything useful in the docs.
Docs here: https://stripe.com/docs/guides/subscriptions#step-2-subscribe-customers
What I have:
<script src="https://checkout.stripe.com/checkout.js"></script>
<button id="customButton">Purchase</button>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_keyhere',
image: '/square-image.png',
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id`
}
});
document.getElementById('customButton').addEventListener('click', function(e) {
// Open Checkout with further options
handler.open({
name: 'test2',
description: 'Test Des',
amount: 0001,
currency:'GBP'
});
e.preventDefault();
});
</script>
<?php
// Set your API key
Stripe::setApiKey("sk_test_keyhere");
$token = $_POST['stripeToken'];
$customer = Stripe_Customer::create(array(
"card" => $token,
"plan" => "test2",
"email" => $email
)
);
?>
Adding to David's answer, you can retrieve the email address via PHP like so:
$stripeinfo =Stripe_Token::retrieve($_POST["token"]);
echo '<pre>',print_r($stripeinfo),'</pre>'; //show stripeObject info
$email = $stripeinfo->email;
Adding a small update to this answer for people who are coming across this now.
$token = $_POST['stripeToken'];
$stripeinfo = \Stripe\Token::retrieve($token);
$email = $stripeinfo->email;
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token,
'description' => 'New Customer'
));
Just some small changes I had to make to get my code to work.
If you are using Checkout you will be passed a token, using that token you can obtain the email address through an API call: https://stripe.com/docs/api#retrieve_token
Not sure why email isn't listed under there but I do have an email attribute available to me. You can also see the email under the Stripe's logs.

Stripe charge multiple times

Using Stripe.js, I get a card token that I can then use to charge via:
Stripe::Charge.create(
:amount => 400,
:currency => "usd",
:card => "tok_103rC02eZvKYlo2C2RD5docg", # obtained with Stripe.js,
:metadata => {'order_id' => '6735'}
)
Can I use the same card token multiple times to charge the customer or is it 1 token/charge and any subsequent charge, I will have to grab a new token?
Good question! When you use the token in that manner, it's immediately consumed, so it can't be used again. However, you can instead provide that token as the card argument when creating a Customer object in Stripe. Then you can perform multiple charges against that Customer.
https://stripe.com/docs/api#create_customer
Hope that helps.
Larry
PS I work on Support at Stripe.
There are two thing. One is token and one is card id. Token can be used one time. Also it has some time limit to use. Card id we get after save the card to cloud. We can use card id multiple time.
Token gets generate through Public key. and this can not be use again.
So You can use card id for payment multiple time
require_once APPPATH . 'libraries/Stripe.php';
Stripe::setApiKey("***********************"); //Put here your secrect key
//Add card and get token id.
$tokenDetail = Stripe_Token::create(array(
"currency" => "USD",
"card" => array(
"number" => '********', //$credit_card_number,
"exp_month" => '**', //$exp_date_month,
"exp_year" => '**', //$exp_date_year,
"cvc" => '***'//$cvv_number
)
));
$token = $tokenDetail->id;
Stripe::setApiKey("*********************"); ////Put here your secrect key
// Get card id by creating a Customer.
$customer = Stripe_Customer::create(array(
"source" => $tokenDetail->id,
"description" => "For testing purpose",
)
);
$response = Stripe_Charge::create(array(
"amount" => 100,
"currency" => "usd",
"customer" => $customer->id // obtained with Stripe.js
));

Omnipay Stripe Extra Parameters

Im trying to use the Omnipay API with Stripe, but I can't pass in extra parameters such as "Name", "Metadata", or "Zip".
// The token is grabbed from stripe JS
$this->stripe_gateway = Omnipay::create('Stripe');
$response = $this->stripe_gateway->purchase([
'amount' => $amount,
'currency' => 'usd',
'name' => $name,
'description' => $product->title,
'zip_address' => $zip,
'metadata' => [
'name' => $name,
'user_id' => $this->session->get('id')
],
'token' => $stripeToken,
])->send();
I cant get anything to work, is this not built into the API?
Omnipay uses it's own parameter names, not Stripe's. That's because Omnipay tries to abstract most of the differences between the various payment gateways.
Right now, the omnipay/stripe package doesn't support sending some of those parameters (only amount, currency, description, and now metadata). You can see the supported parameters here:
https://github.com/omnipay/stripe/blob/master/src/Message/AuthorizeRequest.php
That said, you can still easily access the underlying Stripe request to add your own custom parameters:
$request = $this->stripe_gateway->purchase([
'amount' => $amount,
'token' => $stripeToken,
'metadata' => ['foo' => 'bar'],
]);
$data = $request->getData();
$data['zip_address'] = '12345';
$data['another_custom_parameter'] = 'wow';
$response = $request->sendData($data);
Note that:
$data = $request->getData();
$response = $request->sendData($data);
is exactly the same as calling:
$response = $request->send();
Alternatively, you could create a pull request to add extra parameters to the Omnipay Stripe package. I just added the metadata parameter as an example of this:
https://github.com/omnipay/stripe/commit/99c82dc42c7c0b9ec58d8c4fb917f3dc5d1c23e2

Resources