Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Urgent! S2member is not passing CVC checks to Stripe! #535

Closed
james282 opened this issue Apr 2, 2015 · 34 comments
Closed

Urgent! S2member is not passing CVC checks to Stripe! #535

james282 opened this issue Apr 2, 2015 · 34 comments

Comments

@james282
Copy link

james282 commented Apr 2, 2015

Hello!

Recently, we've been struggling with a TON of declines with integrating stripe with s2member. After a bunch of back and forth with Stripe, we learned that part of the issue is the prepaid cards (and I see that's being worked on - thanks!), but that there was a bigger issue at play as well.

From their support:

"I've looked into the payments on your account and it appears that you're not actually passing the CVC code from your customers through the Stripe API when creating your charges, which is likely a big reason for all the declines you've been receiving!

I'd recommend getting in contact with your developer and making sure that your card creation requests are properly passing in the CVC you collect from your customers in Stripe Checkout, as currently the value is being passed as "null"."

My website is dailyfantasysportsrankings.com. The sign-up page is /membership.

This has cost us a couple thousand dollars already, and I'd be happy to pay some amount of money to get this fix expedited, if at all possible. Or, it could just be some silly user error on my end, but I've dug around as much as I can before posting this.

Thanks!

@james282
Copy link
Author

james282 commented Apr 2, 2015

Just as a follow-up, my business partner has moved payments back to PayPal for the time being (so the page I linked won't have a stripe form on it - I can set up another page if that would be helpful). Stripe was converting way better for us, but obviously a lot of those gains were mitigated by the declines/canceled memberships. We'd still love to use Stripe, but we're putting it on hold for the time being. Thanks for your help.

@james282
Copy link
Author

james282 commented Apr 9, 2015

Hello, the declines continue on, and I was just wondering if there was any progress on this end?

Here's an example of what Stripe passes along to us, where you can see that the CVC and ZIP are coming through as "null" even though they are required fields when you actually try to check out on our site:

XXX's are for privacy.

object: "card"
last4: "XXXX"
brand: "XXXX"
funding: "debit"
exp_month: 9
exp_year: 2016
fingerprint: "XXXXXXXXXXX"
country: "US"
name: "XXXX"
address_line1: null
address_line2: null
address_city: null
address_state: null
address_zip: null
address_country: "US"
cvc_check: null
address_line1_check: null
address_zip_check: null
dynamic_last4: null
metadata:

@jaswrks
Copy link
Contributor

jaswrks commented Apr 10, 2015

@james282 Thank you for the report!


We have been investigating this over the past few days. I am going to send an email to Stripe tech. support and see if they can help us clarify this a bit further. I'll update this issue once we know more.


I'd recommend getting in contact with your developer and making sure that your card creation requests are properly passing in the CVC you collect from your customers in Stripe Checkout, as currently the value is being passed as "null"."

I believe that you may have been misinformed. Or, perhaps there was some confusion about which integration method that s2Member Pro uses.

s2Member's integration with Stripe is via "Stripe Checkout (Custom)". This opens a popup/overlay and Stripe collects the CVC. What s2Member gets back is a Card/Source Token that represents the data Stripe collects from the customer.

From my experience, and as I understand the API docs, there is no reason for s2Member to collect and/or pass a CVC to Stripe; i.e., Stripe has already collected this. We simply reference what Stripe has collected via the Source Token.

There is a cvc_check status that is exposed to s2Member, but again, if you configure your Stripe account to reject CVC failures that should automatically result in a decline when CVC checks fail, as would be expected.


Of course, Stripe will have a more informed response, so I'll wait for their confirmation before we proceed here with any changes that may or may not be necessary.

@jaswrks
Copy link
Contributor

jaswrks commented Apr 10, 2015

@james282 I see that your site is offline at the moment: dailyfantasysportsrankings.com

Can you post a screenshot of the Stripe checkout form where you are entering the credit card details please? I'd like to confirm that we are on the same page when it comes to the integration method that is being used.

@jaswrks
Copy link
Contributor

jaswrks commented Apr 10, 2015

Stripe support request opened. Awaiting response.

Hey guys :-)

I'm the lead dev for s2Member Pro, a popular eCommerce plugin for WordPress. We integrate with Stripe using Stripe Checkout (Custom).

I have a question about CVC checks.

Scenario:

- Stripe Checkout (Custom) popup/overlay.
- Stripe popup collects card, expiration date, and CVC.
- We create a card object via PHP using the token ID.

Do we need to pass and/or validate the CVC?

I'm assuming no. As I understand it, Stripe Checkout collects the CVC, so all that we need to pass in our PHP API call is the token. Right?

If the CVC check fails (and the site owner rejects invalid CVC codes), the charge is declined automatically?

Or, do we need to look at the `cvc_check` status?

@james282
Copy link
Author

Thanks so much for getting back to me.

My site is having problems with another plug-in at the moment - sorry about that.

The stripe form is located at: dailyfantasysportsrankings.com/membership.

I just received another email of my own from Stripe support saying that the CVCs are still not going through, in spite of me requiring them to accept payment on Stripe's end.

It's bizarre, because some cards give a "CVC Check: Passed" feedback, and some don't say there's any record of a CVC at all.

Thanks.

@jaswrks
Copy link
Contributor

jaswrks commented Apr 14, 2015

Reply from Stripe:

Hey there,

Thanks for writing in about this, I'm happy to help! You definitely don't have to validate CVC yourself here especially since you should never send this to your server. Stripe Checkout will collect the CVC for you and send it along the card details to our server so that we can send you a card token back.

You then use that card token on your server through the Create Customer [1] or Create Charge [2] API. When that happens you can see in the response object the field cvc_check to know if the CVC check was successful or not. If it failed and the merchant has the settings to decline those charges automatically then the charge or the customer creation would ultimately fail.

I hope this helps but please do not hesitate to get back to me if you need more details.
All the best,
Thomas


So I'm not seeing that we need to change anything in the Stripe integration. I don't see a bug here at all actually.

@james282
Copy link
Author

So we're getting conflicting reports from the various employees of Stripe.
I'm at a loss. Declines rage on unabated - there's no way that big
businesses deal with this sort of thing? We'd have to have a full time
staffer just to call all of these people. Ugh. Thanks for looking into it.

On Tue, Apr 14, 2015 at 6:34 AM, JasWSInc notifications@github.com wrote:

Reply from Stripe:

Hey there,

Thanks for writing in about this, I'm happy to help! You definitely don't
have to validate CVC yourself here especially since you should never send
this to your server. Stripe Checkout will collect the CVC for you and send
it along the card details to our server so that we can send you a card
token back.

You then use that card token on your server through the Create Customer
[1] or Create Charge [2] API. When that happens you can see in the response
object the field cvc_check to know if the CVC check was successful or
not. If it failed and the merchant has the settings to decline those
charges automatically then the charge or the customer creation would
ultimately fail.

I hope this helps but please do not hesitate to get back to me if you need
more details.
All the best,
Thomas


So I'm not seeing that we need to change anything in the Stripe
integration. I don't see a bug here at all actually.


Reply to this email directly or view it on GitHub
#535 (comment).

Summer Camp Revolution
summercamprevolution.com
609-273-8408

@ghost
Copy link

ghost commented Jul 14, 2015

@jaswsinc I am developing a site or a client at http://naturalbusinesstools.com and I am also seeing certain cards return "card_declined" when submitting them via s2.

It might be a slightly separate issue but when I enter a card into the stripe overlay it accepts is with a green tick but when I submit via the s2 'submit' button it says 'card declined'. Strangely I can't determine what cards go through and just to make it even more confusing I had a card decline the other day and then work today.. so not really sure whats going on.

Obviously this is a major issue for the client.

@raamdev
Copy link
Contributor

raamdev commented Jul 14, 2015

I'm reopening this issue after @lukeallen1986's new report (#623):

I have a s2 pro installation running at http://naturalbusinesstools.com and its got the stripe plugin attached so I can handle payments. I also have a correctly installed SSL certificate and all my Stripe settings / validation / web hooks are correct.

In testing the payment gateway all worked correctly but as soon as I have swapped over to live payments are failing.

When the stripe popup appears I enter the card details and stripe accepts them with a green tick but when I 'submit' the s2 form I get a 'card declined' message. All the details are still sent to Stripe but no payment is taken. Obviously this is a major issue as the site is live now and I can't accept payments.

Can you please advise what info you need to solve this issue asap.


Also a quick update. Looking at the logs in Stripe I see that the cvc is unchecked. Not sure if this is an issue?

See below:
id: card_16OHD6fSNzOOoFfYkqY1
object: "card"
last4: "2639"
brand: "MasterCard"
funding: "credit"
exp_month: 3
exp_year: 2018
fingerprint: "apvRygYQmvNjgta9"
country: "AU"
name: "bianca.potenta@test.com.au"
address_line1: null
address_line2: null
address_city: null
address_state: null
address_zip: null
address_country: null
cvc_check: "unchecked"
address_line1_check: null
address_zip_check: null
tokenization_method: null
dynamic_last4: null
metadata:
customer: cus_6bURGrDMxekWY2


@jaswsinc Any ideas here?

@ghost
Copy link

ghost commented Jul 14, 2015

Thanks @raamdev. Yeah I am still struggling to work out whats happening i'm testing it in every browser and with different accounts but all same result.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 14, 2015

Thank you. I'm investigating this also.

@raamdev raamdev added this to the Next Release milestone Jul 14, 2015
@ghost
Copy link

ghost commented Jul 14, 2015

Not sure if this is of any help but when I attempt to process a transaction even if its declines it still records all the user information in Stripe, however in the logs it say:

"pending http://naturalbusinesstools.com/?s2member_pro_stripe_notify=1"

when referring to the web hook but I checked and both my web hook in stripe and s2 match
http://naturalbusinesstools.com/?s2member_pro_stripe_notify=1 [s2]
http://naturalbusinesstools.com/?s2member_pro_stripe_notify=1 [stripe]

@ghost
Copy link

ghost commented Jul 15, 2015

Hey @jaswsinc has there been any progress on this? I tried another card to day and received card_declined. This was with a separate bank this time.

Could it be that we are not checking cvc or address/postcode that the card fails?

@ghost
Copy link

ghost commented Jul 16, 2015

Ok @jaswsinc and @raamdev there has been a development.

I have tried 4 separate personal credit cards [friends and families] and they all worked perfectly. Then I tried a couple of business credit/debit cards and they all failed....

So it looks like s2 or stripe is failing Business card transactions... is this a known problem?

@ghost
Copy link

ghost commented Jul 16, 2015

As this seems a little off topic now I created a new issue - #629.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

I have tried 4 separate personal credit cards [friends and families] and they all worked perfectly. Then I tried a couple of business credit/debit cards and they all failed....

Interesting. In terms of the processing API, there is no distinction that I am aware of at all. I have been unable to reproduce that scenario so far. Tried two different company cards and they go through just fine.

Do you have s2Member's logging routines enabled? If so, please send those privately and I'll review them with you. Use: http://wsharks.com/1GrOWND

The log files will show us the API communication, or lack of, and perhaps that will shed light.

See: Dashboard → s2Member → Log Files (Debug)

@ghost
Copy link

ghost commented Jul 18, 2015

Thanks for getting back to me.

Wow thats even more interesting! I had logs turned off as it was live but i've switched them back to on now and i will try a few of the cards and then send you the logs.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Looking at the logs in Stripe I see that the cvc is unchecked. Not sure if this is an issue?

Someone made this comment previously and I just wanted to point out that this is to be expected. See what Stripe said to me in a conversation I had with them about this.

The CVC check and any failure that should occur because of the CVC status--all of that is handled by Stripe in the overlay before it comes to s2Member. To control this behavior, you will need to adjust the settings in your Stripe account. See: Stripe Dashboard → Account Settings → General

2015-07-17_19-18-48

@lukeallen1986 Would you mind posting a screenshot of this panel in your Stripe Dashboard for us? I'd just like to confirm that we are attempting to reproduce with the same configuration.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

When the stripe popup appears I enter the card details and stripe accepts them with a green tick but when I 'submit' the s2 form I get a 'card declined' message.

Yes, that is puzzling. I haven't been able to reproduce this yet, but I will keep looking. Hopefully the log files that @lukeallen1986 sends us will shed light on this.

@ghost
Copy link

ghost commented Jul 18, 2015

Sure here is my current setup. I had been experimenting with these options but I think its been in this current state for 2 days now.

screen shot 2015-07-18 at 13 21 33

@ghost
Copy link

ghost commented Jul 18, 2015

Ok I have emailed you the logs. I just tried one card as I didn't want to keep you waiting but can get more if you need me to.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

@lukeallen1986 Details received. Thank you. Taking a look now.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

When the stripe popup appears I enter the card details and stripe accepts them with a green tick but when I 'submit' the s2 form I get a 'card declined' message.

@lukeallen1986 So I reproduced this behavior on your site, and I traced it back to a card update that takes place within s2Member. Upon final submission, s2Member adds the customer's name, address_zip, address_state, and address_country right after the card (aka: source) is added to your Stripe customer.

The card_declined error that you're seeing is from the Stripe API, and it's returning a card_declined error whenever s2Member attempts to update the card with those basic details. I suspect this is a bug in the Stripe API, but I wanted to post the information here first, just in case any of this might give you some of idea of why this particular update might fail. Thoughts?

Armed with the knowledge of which Stripe API call resulted in a card_declined error from Stripe, I then setup a test page on your site where I ran back through the update calls and attempted to update one piece of information at a time. I was able to update the name, address_state, and address_zip without issue. However, on this particular card whenever I attempt to update address_country to a value of AU the Stripe API says, card_declined for some reason. Any idea why that might be? i.e., do you have any Stripe configuration that would prevent AU from being validated? Is that the country associated with the billing address for that card?


Short-Term Workaround

Find this line of code in your copy of s2Member Pro: https://github.com/websharks/s2member-pro/blob/000000-dev/s2member-pro/includes/classes/gateways/stripe/stripe-utilities.inc.php#L166
File: s2member-pro/includes/classes/gateways/stripe/stripe-utilities.inc.php

Change:

$source->save();

To:

// $source->save();

That will prevent the additional update from taking place. It's only there for tax reporting purposes anyway, and that should resolve the issue in the short-term until we can get to the bottom of this.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Referencing unexpected API response failure from Stripe in their PHP SDK:

                    [file] => .../wp-content/plugins/s2member-pro/includes/classes/gateways/stripe/stripe-sdk/lib/Stripe/ApiRequestor.php
                    [line] => 109
                    [function] => _interpretResponse
                    [class] => Stripe_ApiRequestor
                    [type] => ->
                    [args] => Array
                        (
                            [0] => {
  "error": {
    "message": "Your card was declined.",
    "type": "card_error",
    "param": "",
    "code": "card_declined"
  }

jaswrks pushed a commit to wpsharks/s2member-pro that referenced this issue Jul 18, 2015
@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Request for assistance sent to Stripe:

Hi there! :-) It's Jason over here with s2Member for WordPress (integrates w/ Stripe).

It came to my attention recently that some of our Stripe API calls that update the Source (Card) object by setting the customer's name, address_state, address_zip, and address_country are returning a card_declined error.

We are using Stripe Checkout so we expect that the Token we get has already been validated. However, upon updating the Source with some additional details, the card is in fact declined according to your API.

So we went through and tried to figure out which piece of information might be triggering a response from your API that a card has declined. We found that updating the address_country to AU was causing a problem.

In the test case, it was card_[REDACTED] that we tried to update on behalf of a site owner that reported this to us. If I try to update card_[REDACTED] by setting address_country to AU I get a card_declined error.

What reasons could there be for a card_declined error in a case like this? i.e., why would updating the address_country result in a decline?

Thanks in advance! :-)

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Next Release Changelog:

  • (s2Member Pro) Stripe Bug Workaround: It came to our attention that some Stripe API calls that simply update the name, address_state, address_zip, and address_country for tax reporting purposes were resulting in a card decline even after Stripe approved the transaction. We suspect this is a bug in the Stripe API. It has been reported to Stripe. For now though, we are working around this issue by failing gracefully in such a scenario. This simple update is there only for tax reporting purposes, so if it fails it does not warrant a refusal to complete the transaction. It is simply logged by s2Member for analysis. Please see this GitHub issue where a deeper investigation is underway for our next maintenance release.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Giving this a partial completion tag, but leaving this open until I hear back from Stripe and @lukeallen1986

@jaswrks
Copy link
Contributor

jaswrks commented Jul 18, 2015

Next Release Changelog:

  • (s2Member Pro) Stripe API Update: This release of s2Member takes advantage of the latest Stripe API version. Moving from v2015-02-18 to v2015-07-13. See this article at Stripe if you'd like additional details. Remember that s2Member's API calls to Stripe will always use this specific version of their API (v2015-07-13), even if your Stripe account is configured with an older default version. This is to ensure that s2Member works as intended for all site owners.

@ghost
Copy link

ghost commented Jul 18, 2015

Hi @jaswsinc I just saw all your messages. When I get a free moment tonight I will go through them all and get back to you asap.

@jaswrks jaswrks modified the milestones: Future Release, Next Release Jul 19, 2015
@ghost
Copy link

ghost commented Jul 19, 2015

Hey @jaswsinc I made the change to comment out // $source->save(); and that appears to have worked :-)

So that will definitely be an acceptable workaround for now.

Thanks so much for helping with this and I have also email Stripe so I will update you if they tell me anything about this bug.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 23, 2015

Stripe support replies...

Hey Jason,

Thanks for writing in about this, I'm happy to help! I took a look into those failed updates on our end and it looks like standard declines from the bank here. Whenever you update the card details we automatically run an authorization on the card to make sure it's still accepted by the bank. In your case, when updating the address_country field the bank ends up declining the card so we refuse to update it to avoid the card not working anymore in the future.

To help provide a bit of background on declines, I'd recommend taking a look at our declines documentation [1]. Basically, we don't receive very detailed information on declines from a card holder's institution. Since the decision is made on the bank's end we don't have any additional insight other than what we are able to provide you via the dashboard and API.

The only way to find out more detailed information about why a payment was declined is to ask your customer to get in touch with their bank to confirm the reason for each individual decline. For security and privacy purposes, banks will (correctly) not give information about this transaction to anyone other than the cardholder, but they should be able to share more information with your customer.

I hope this helps but please do not hesitate to get back to me if you need more details.
All the best,
Thomas

[1] https://stripe.com/help/declines


So this tells me that s2Member should expect to receive a decline upon updating the extended billing information, but that when/if this occurs we should only log the error, not fail entirely. That's what the latest release does now that we applied the workaround, so I think it's safe to close this issue now. We have done all we can do. I don't see this being an issue in s2Member v150722 or higher moving forward.

@jaswrks jaswrks closed this as completed Jul 23, 2015
@jaswrks
Copy link
Contributor

jaswrks commented Jul 23, 2015

Hey @jaswsinc I made the change to comment out // $source->save(); and that appears to have worked :-)

@lukeallen1986 Thanks for reporting back on this. Much appreciated.

@jaswrks
Copy link
Contributor

jaswrks commented Jul 23, 2015

The latest release of s2Member v150722+ closes this issue.

This issue will now be locked to further updates. If you have something to add related to this GitHub Issue, please open a new GitHub Issue and reference this one. Thanks! :-)

@wpsharks wpsharks locked and limited conversation to collaborators Jul 23, 2015
@raamdev raamdev modified the milestones: v150722, Next Release Aug 27, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants