Coder Social home page Coder Social logo

omnipay-stripe's Introduction

Omnipay: Stripe

Stripe driver for the Omnipay PHP payment processing library

Build Status Latest Stable Version Total Downloads

Omnipay is a framework agnostic, multi-gateway payment processing library for PHP. This package implements Stripe support for Omnipay.

Installation

Omnipay is installed via Composer. To install, simply require league/omnipay and omnipay/stripe with Composer:

composer require league/omnipay omnipay/stripe

Basic Usage

The following gateways are provided by this package:

For general usage instructions, please see the main Omnipay repository.

Stripe.js

The Stripe integration is fairly straight forward. Essentially you just pass a token field through to Stripe instead of the regular credit card data.

Start by following the standard Stripe JS guide here: https://stripe.com/docs/tutorials/forms

After that you will have a stripeToken field which will be submitted to your server. Simply pass this through to the gateway as token, instead of the usual card array:

        $token = $_POST['stripeToken'];

        $response = $gateway->purchase([
            'amount' => '10.00',
            'currency' => 'USD',
            'token' => $token,
        ])->send();

Stripe Payment Intents

Stripe Payment Intents is the Stripe's new foundational payment API. As opposed to Charges API, Payment Intents supports Strong Customer Authentication. It means that during the payment process, the user might be redirected to an off-site page hosted by the customer's bank for authentication purposes.

This plugin's implementation uses the manual Payment Intent confirmation flow, which is pretty similar to the one the Charges API uses. It shouldn't be too hard to modify your current payment flow.

  1. Start by collecting the payment method details from the customer. Alternatively, if the customer has provided this earlier and has saved a payment method in your system, you can re-use that.

  2. Proceed to authorize or purchase as when using the Charges API.

$paymentMethod = $_POST['paymentMethodId'];

$response = $gateway->authorize([
     'amount'                   => '10.00',
     'currency'                 => 'USD',
     'description'              => 'This is a test purchase transaction.',
     'paymentMethod'            => $paymentMethod,
     'returnUrl'                => $completePaymentUrl,
     'confirm'                  => true,
 ])->send();
  • If you have a token, instead of a payment method, you can use that by setting the token parameter, instead of setting the paymentMethod parameter.
  • The returnUrl must point to where you would redirect every off-site gateway. This parameter is mandatory, if confirm is set to true.
  • If you don't set the confirm parameter to true, you will have to manually confirm the payment intent as shown below.
$paymentIntentReference = $response->getPaymentIntentReference();

$response = $gateway->confirm([
    'paymentIntentReference' => $paymentIntentReference,
    'returnUrl' => $completePaymentUrl,
])->send();

At this point, you'll need to save a reference to the payment intent. $_SESSION can be used for this purpose, but a more common pattern is to have a reference to the current order encoded in the $completePaymentUrl URL. In this case, now would be an excellent time to save the relationship between the order and the payment intent somewhere so that you can retrieve the payment intent reference at a later point.

  1. Check if the payment is successful. If it is, that means the 3DS authentication was not required. This decision is up to Stripe (taking into account any custom Radar rules you have set) and the issuing bank.
if ($response->isSuccessful()) {
    // Pop open that champagne bottle, because the payment is complete.
} else if($response->isRedirect()) {
    $response->redirect();
} else {
    // The payment has failed. Use $response->getMessage() to figure out why and return to step (1).
}
  1. The customer is redirected to the 3DS authentication page. Once they authenticate (or fail to do so), the customer is redirected to the URL specified earlier with completePaymentUrl.

  2. Retrieve the $paymentIntentReference mentioned at the end of step (2).

  3. Now we have to confirm the payment intent, to signal Stripe that everything is under control.

$response = $gateway->confirm([
    'paymentIntentReference' => $paymentIntentReference,
    'returnUrl' => $completePaymentUrl,
])->send();

if ($response->isSuccessful()) {
    // All done!! Big bucks!
} else {
    // The response will not be successful if the 3DS authentication process failed or the card has been declined. Either way, it's back to step (1)!
}

Stripe Connect

Stripe connect applications can charge an additional fee on top of Stripe's fees for charges they make on behalf of their users. To do this you need to specify an additional transactionFee parameter as part of an authorize or purchase request.

When a charge is refunded the transaction fee is refunded with an amount proportional to the amount of the charge refunded and by default this will come from your connected user's Stripe account effectively leaving them out of pocket. To refund from your (the applications) Stripe account instead you can pass a refundApplicationFee parameter with a boolean value of true as part of a refund request.

Note: making requests with Stripe Connect specific parameters can only be made using the OAuth access token you received as part of the authorization process. Read more on Stripe Connect here.

Test Mode

Stripe accounts have test-mode API keys as well as live-mode API keys. These keys can be active at the same time. Data created with test-mode credentials will never hit the credit card networks and will never cost anyone money.

Unlike some gateways, there is no test mode endpoint separate to the live mode endpoint, the Stripe API endpoint is the same for test and for live.

Support

If you are having general issues with Omnipay, we suggest posting on Stack Overflow. Be sure to add the omnipay tag so it can be easily found.

If you want to keep up to date with release announcements, discuss ideas for the project, or ask more detailed questions, there is also a mailing list which you can subscribe to.

If you believe you have found a bug, please report it using the GitHub issue tracker, or better yet, fork the library and submit a pull request.

omnipay-stripe's People

Contributors

aimeoscom avatar amacneil avatar andris-sevcenko avatar antoinelemaire avatar anush avatar aperdomo avatar barryvdh avatar cfreear avatar delatbabel avatar dizda avatar gabsfm avatar greydnls avatar jsampedro77 avatar markincube8 avatar mikealmond avatar mvestil avatar nathanjosiah avatar nicolassing avatar pedro-stanaka avatar phpguru avatar pilot avatar rendom avatar ruudk avatar sfarkas1988 avatar sharald avatar sudiptpa avatar w3guy avatar wellingguzman avatar yepzy avatar zchlm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

omnipay-stripe's Issues

I can't getCustomerReference on a charge object

In your test on lines 109-115 of Message\Response, you're forcing that test to run only on customer and card objects, but it's also there on charge objects.

The method currently returns null on charge objects, even though they have a $data['customer'].

@see #105

Support for payouts?

Is there going to be, or could there be support for "payouts" added in sometime soon?

https://stripe.com/docs/api#create_payout

Im going to doing a job where I need to act as a "market place" and vendors get money paid to them where we middle man the transaction. The vendors will register their bank account information with us and then when purchases are made from their products the money will be transferred to their bank account.

This used to be part of the transfers object:
https://stripe.com/docs/transfer-payout-split

On April 6, 2017, Stripe is splitting the /v1/transfers resource into /v1/transfers and /v1/payouts. This is a versioned change -- your existing integrations don't need to change.
Since Stripe was launched, we've used the word transfer to mean moving money out of Stripe and into your bank account or debit card. But when Connect was launched years later, we co-opted that term to also mean moving money between a platform and its connected accounts.
This ultimately turned out to be confusing. These are conceptually different flows of funds as they apply to a business. This made it difficult to document transfers, and also bloated the /v1/transfers API because the fields needed to support each flow of funds were different.
With the new version of 2017-04-06:
Payouts will mean moving money from Stripe to your bank account or debit card and will be represented by /v1/payouts.
Transfers will mean moving money between Stripe accounts as part of Connect and will be represented by /v1/transfers.
Relative to the legacy /v1/transfers resource, the new /v1/transfers resource won't have these fields:
method - this only applies to payouts.
status - this only applies to payouts.
type - this only applies to payouts.
bank_account - this only applies to payouts.
card - this only applies to payouts.
failure_message - this only applies to payouts.
failure_code - this only applies to payouts.
description - description was confusing because it applied to the transfer but not the resultant payment on the connected account. Use metadata to attach additional information to a transfer.
application_fee - application_fee is no longer necessary. See Connect destination charges.
Relative to the legacy /v1/transfers, the new /v1/payouts resource won't have these fields:
reversals - payouts can now be simply canceled.
reversed - refer to the payout status.
application_fee - this only applies to legacy transfers.
destination_payment - this only applies to transfers.
source_transaction - this only applies to legacy transfers.
description - description was removed because it didn't provide enough value. Use metadata to attach additional information to a payout.
On the /v1/payouts resource, the date field was renamed to arrival_date.
To send a payout to your default bank account or debit card, instead of including the parameter destination=default_for_currency, simply omit the destination entirely.
Canceling a payout is now done via POST /v1/payouts/:id/cancel. The balance transaction resulting from a cancellation is available via the cancellation_balance_transaction field on the payout. The status of a canceled payout is canceled.
When creating a transfer, you can now only use a charge as the source_transaction. Previously, it was possible to use any transaction (such as an application fee, or an adjustment) as a source_transaction. This did not mesh well with the intended use case of tagging outgoing transfers with the incoming source of funds, so this is no longer supported on the new API version.
Payouts now generate these events: payout.created, payout.failed, payout.reversed, payout.paid, payout.updated, which are the equivalent of the legacy transfer.* events.
Transfers no longer generate these events: transfer.paid and transfer.failed.
Balance transactions can have these types as they relate to payouts: type ∈ {payout, payout_failure, payout_cancel}
Balance transactions can have these types as they relate to transfers: type ∈ {transfer, transfer_refund}
Fields on the Account API were renamed:
transfers_enabled -> payouts_enabled
transfer_schedule -> payout_schedule
transfer_statement_descriptor -> payout_statement_descriptor
Transfers to deprecated Recipients API (link) are no longer represented on this version of the API. Use a legacy API version to access any transfers to recipients that you may have.

Issue with amount parameter.

Hey guys,

I'm issuing a payment with the following options array:

$options = [
    'amount'            => '10.00',
    'cardReference'     => 'cus_REAL_REFERENCE',
    'currency'          => 'GBP'
];

$gateway->purchase($options)->send();

and here's the request as shown in the Stripe back-end.

{
    "amount": 1000,
    "currency": "gbp",
    "description": "",
    "capture:" true,
    "customer": "cus_REAL_REFERENCE"
}

As you can see, the 10.00 is being interpreted as 1000 GBP. Am I doing something wrong? I've tried strings and floats as the amount parameter.

Wrong behavior for incorrect data

The Stripe provider throws an exception if the the server returns that one of the card details was invalid.

According to the docs, isSuccessful() should return false and $response->getMessage() should return the string that should be displayed to the user.

how to refund?

Maybe the best choice is official SDK. Omnipay's document is so bad,many function can not find.

CreatePlanRequest

Hi, I use this library. I think that you have some mistakes. For example, file CreatePlanRequest.php, function getData(). Code:

$data = array(
   'id' => $this->getId(),
   'amount' => $this->getAmount(),
   'currency' => $this->getCurrency(),
   'interval' => $this->getInterval(),
   'name' => $this->getName() );

need change at:

$data = array(
  'id' => $this->getId(),
  'amount' => $this->getAmount(),
  'currency' => $this->getCurrency(),
  'interval' => $this->getInterval(),
  'product' => [
     'name' => $this->getName()
 ]);

UpdateSubscriptionRequest::getPlanId() should be getPlan()

Also true for setPlanId().

Right now the 'plan' parameter is not set when passing the 'plan' key to
->updateSubscription(['plan' => '...'])
but it does work when passing the key as 'planId'.

Also CreateSubscriptionRequest has getPlan(0 and setPlan().

Is this expected behaviour?

Support updateCard for expiry only

It would be nice to be able to update just the card expiry date rather than only supporting full credit card details. Stripe supports this:

https://stripe.com/docs/api#update_card

I'd be happy to send a pull request but would like to clarify the best way to implement it. Should it be a new message request type (eg. UpdateCardExpiryRequest) and switch the request used in updateCard() based on the presence of the card id parameter (eg. card_id)?

Using Source instead of Token

The current examples for Omnipay-Stripe uses either a Credit Card object or a token to handle the processing, but Stripe advises the use of sources instead of tokens. Is there an official method of using a source object from Stripe's JS library to do processing in Omnipay?

Cannot perform transaction based upon Stripe customer ID

It is possible to create cards (which then creates a Stripe customer) but after the customer is created, a transaction using the customer ID as the token isn't successful. Passing in the parameter 'customer' instead of token results in a card error being thrown stating that card details need to be passed.

Ideally, you should be able to pass a customer id and perform the transaction according to Stripe's payment API using the customer data instead of a token.

Add shipping to customer

I had a dive into the CreateCustomerRequest class and it doesn't look as though it is currently possible to add the optional shipping parameter into your request. Is this possible or are there plans to make this possible?

Logic for customer and source have changed

From the Stripe API reference:

... If you also pass a customer ID, the source must be the ID of a source belonging to the customer. Otherwise, if you do not pass a customer ID, the source you provide must either be a token, like the ones returned by Stripe.js, or a dictionary containing a user's credit card details, with the options described below.

(Inference: you cannot pass a customer ID and the customer's credit card details, you must either pass a customer ID and a card token, or a customer ID without a card token, or card data without a customer ID).

PHP notice error: undefined index `code` on Message/Response.php#L308

Hi there,

I'm getting this error in the context of the Craft Commerce Plugin, on the last step of checkout.

The data I feed to the form is correct (a valid Stripe token), and it works fine with the Test API Keys. So the error only happens when working with the Live Keys.

https://github.com/thephpleague/omnipay-stripe/blob/master/src/Message/Response.php#L308

Here's an example of the data I get using Stripe.js (I'm "blurring" the token because real card)

{
  id: "tok_19J5meHOW6ChjHQ7djwPxxxx",
  object: "token",
  card: Object,
  client_ip: "83.32.118.217",
  created: 1479926872,
  livemode: true,
  type: "card",
  used: false
}

Any ideas?

Please let me know If I should be asking somewhere else.

Thank you!

Replacing guzzle package.

Hi there.

Just got few "warnings" while installing your package, basically saying:

Package guzzle/common is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/stream is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/parser is abandoned, you should avoid using it. Use guzzle/guzzle instead.
Package guzzle/http is abandoned, you should avoid using it. Use guzzle/guzzle instead.

As you're requiring: guzzle/http https://packagist.org/packages/guzzle/http

Probably not a big issue just yet, but it may be worth considering a switch ;)

Thanks.

FR: Method for passing receipt_email

It's really important for our accounts dept to be able to easily identify transactions in Stripe by customer email but the Omnipay Stripe implementation doesn't appear to support passing on receipt_email or even customer email (if we're using a token and not passing card details directly).

I notice there some discussion pertaining to this previously but it didn't appear to go anyway... any thoughts?

CreateCustomer doesn't return proper card token

Hi there,
I've tried both createCustomer and createCard with no customer attached to try and retrieve a customer ID and card ID. The code seems to only return the customer ID for both fields.

    $sendData = [
            'card' => new OmniPayCreditCard( $cardData->all() ), // OmniPayCreditCard is just a renamed instance of the Omnipay CreditCard object.
        ];
        \Log::debug([ __METHOD__ => $sendData]);
        $response = $this->gateway->createCustomer($sendData)->send();

        if ($response->isSuccessful()) {

            $customer_id = $response->getCustomerReference();
            \Log::debug([ __METHOD__ => $customer_id]);

            $card_id     = $response->getCardReference();
            \Log::debug([ __METHOD__ => $card_id]);

            return [
                'card_id'     => $card_id,
                'customer_id' => $customer_id,
            ];

        } 

When the code returns, the $customer_id and $card_id variables are identical, and appear to contain the customer ID.

getTransactionReference() on a failed payment

I only use Omnipay for Stripe at the moment but I've noticed that when a transaction has failed $response->getTransactionReference() returns null, obviously you'd expect it to always return the transaction id regardless.

The transaction id is available in the response from Stripe. I'm currently getting it by doing the following:

$transData = $response->getData();

if (isset($transData['error']['charge'])) {

    return $transData['error']['charge'];

 }

Is this is expected behaviour? If it is then should it be changed? What are your thoughts?

Create subscription with coupon

Hello,

We can't create a subscription with a coupon in the parameters. Settings the coupon as a parameter in the request allow you to set a discount on a newly created subscription as it is stated in the documentation.

We should update the CreateSubscriptionRequest and add getter and setter for the coupon as follow :

`/**
* Set the coupon
*
* @param $value
* @return \Omnipay\Common\Message\AbstractRequest|CreateSubscriptionRequest
*/
public function setCoupon($value)
{
return $this->setParameter('coupon', $value);
}

/**
 * Set the plan
 *
 * @param $value
 * @return \Omnipay\Common\Message\AbstractRequest|CreateSubscriptionRequest
 */
public function setPlan($value)
{
    return $this->setParameter('plan', $value);
}

`
And also add a condition the getData() method to add the coupon in the request data like this :

if($this->parameters->has('coupon')) { $data['coupon'] = $this->getCoupon(); }

I will try to make a proper pull request

Thank you

I'd like to be able to get outcome details

I don't know exactly where this fits in with the various other omni-pay drivers, but it would be nice to be able to print, on the customer receipt / thank you page, for example, the bank reply; something like

Message: Payment Complete.  // $charge['data']['outcome']['seller_message']
Status: approved_by_network  // $charge['data']['outcome']['network_status']
Type: authorized  // $charge['data']['outcome']['type']

I was thinking of adding a getOutcome method for this purpose, which would be used on charge objects. Any reason why the outcome sub-node of $data has no corresponding getter method?

Add description in transfer group.

I'm new to omnipay.
Are we able to add description while using transfer group?
I actually added the description but no luck. Please help.

    $data = array(
        'amount' => $this->getAmountInteger(),
        'currency' => strtolower($this->getCurrency()),
        'destination' => $this->getDestination(),
    );

CreatePlanRequest not converting floats to integer

This is taken care of in purchase() but neglected in CreatePlanRequest

array(1) { ["error"]=> array(3) { ["type"]=> string(21) "invalid_request_error" ["message"]=> string(23) "Invalid integer: 552.82" ["param"]=> string(6) "amount" } }

Cannot install via Composer (404 Not Found)

I'm getting this error anytime I try installing via composer. This is the error I get:

[Composer\Downloader\TransportException]                                     
The "https://api.github.com/repos/omnipay/stripe/zipball/e56ad2d1a7a50bacca  
727e1363aca44e35cf2573" file could not be downloaded (HTTP/1.1 404 Not Found)

This also happens for TargetPay, but that's a lesser priority.

TVA on subscription

Currently Stripe accept a TVA amount (ex: 20%) but the library doesn't provide a way to send the value.

Create Direct Charge

Hello, I'm using this library and so far it has been great. But I could not find a way to make a direct charge. The format of a direct charge asks for the Stripe-Account header like:

curl https://api.stripe.com/v1/charges \
   -u sk_test_hhCDjLJSkdUWHAMeYWT29HZg: \
   -d amount=1000 \
   -d currency=gbp \
   -d source=tok_visa \
   -d application_fee=123 \
   -H "Stripe-Account: {CONNECTED_STRIPE_ACCOUNT_ID}"

Am I missing something here or this is something that have to be done yet?

Move header auth setting to sendData

Should the setting of the auth header in AbstractRequest::send():

https://github.com/thephpleague/omnipay-stripe/blob/master/src/Message/AbstractRequest.php#L194-L197

Be moved into the top of sendData(), as to remove the additional param for headers?

The additional header param doesn't meet the request interface: https://github.com/thephpleague/omnipay-common/blob/master/src/Common/Message/RequestInterface.php#L51

It also looks like the original intent of splitting send() and sendData() was to allow the full modification of the request body, and not the request authentication:
thephpleague/omnipay#162

Right now this gateway implementation is breaking the interface with that additional $headers param in sendData().

Thoughts? Can we move the setting of the auth header into the top of the sendData()? Will make PR after feedback.

CreateSubscriptionRequest MetaData missing

$response = $gateway->createSubscription(
                    array(
                        'customerReference' => $customerReference,
                        'plan'              => $planID,
                        'metadata'          => array(
                            'exhibitor_id' => $exhibitor->ID // confirmed this ID is of type integer and value of 1073
                        )
                    )
                )->send();

Issue: Not sent to Stripe
Proof:

screen shot 2016-11-08 at 1 34 58 pm

createCustomer support for source

I've tried passing the extra parameter 'source' to the function createCustomer and setting it to the token returned by Stripe 'Checkout', as shown here, but it's not sent. Then I've read here that omnipay-stripe doesn't support extra parameters.

Can this work around method be used instead:
$response = $gateway->createCustomer(array( 'description' => 'Test Customer', 'email' => '[email protected]', )); $data = $request->getData(); $data['source'] = 'tok_1234oVJjPoOHXFyktY79rGyk'; $response = $request->sendData($data);
It seems to work.

Would be great if this function could be extended to support the 'source' parameter.

Once the customer has been created the token can't be re-used for the purchase so I want to use the customer_id instead of the token in the purchase request, however I run into the issue explained here. The solution described seems to involve creating a card, but I don't want to handle any card data for PCI compliance reasons.

It works if I only use the token in the purchase request and not when creating the customer, but I want to create a susbscription and to do that I believe the customer first requires a source/card.

The currency parameter is required

I'm setting the currency parameter, however I'm still receiving this error
The currency parameter is required

$pw = new PaymentWrapper( 'Stripe' );

...

$pw->initialize($processorParams);

$pw->setCreditCard([
      ...
]);

// Determine total order cost
$amount = 4000.00;
$currency = 'CAD';
$pw->purchase( $amount, $currency );
$pw->processResponse();

Creat Customer and to associate new card

I know how to create customer, but i am not find way to after creating customer create new card and associate with the customer.
Someone can help me? thank you

Create customer:

      $tra = $gateway->createCustomer(array('description' => '14', 'metadata' => ['foo' => 'bar']));
        $response = $tra->send();

        if ($response->isSuccessful()) {
            // payment was successful: update database
            echo $response->getCustomerReference();
        } elseif ($response->isRedirect()) {
            // redirect to offsite payment gateway
            $response->redirect();
        } else {
            // payment failed: display message to customer
            echo $response->getMessage();
        }

create card

        $formData = array('number' => '4242424242424242', 'expiryMonth' => '6', 'expiryYear' => '2016', 'cvv' => '123');
        $tra = $gateway->createCard(array('card' => $formData));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.