質問

I'm builiding a web application that allows our users to sell tickets for music shows. In order to handle the payments between ticket buyers and show instigators, I use Stripe. Basically, the show instigator creates his show's page on my application, and the users can buy tickets for this show.

In order to create a show, the instigator fills in a form (Show's name, show's date, where the show will take place, what bands will be playing, etc.) This form also requires the show instigator to provide both his Publishable and Secret Stripe keys. My app uses both these tokens to retrieve credit cart information (on the client side) and process payments (on the server side).

The problem is, I want to make sure that show instigators provide valid and existing Stripe keys. I wouldn't want my users to stumble across payments errors because show instigators did not provide valid Stripe keys.

So, my question is: How can I verify that Publishable and Secret keys are valid and existing? What's the best strategy to achieve this? Thanks!

役に立ちましたか?

解決 3

I am not aware of any documented api call that can be made specifically to validate keys. Here is a suggestion you might try:

Require your partners to provide a valid credit card and inform them that in order to validate their Stripe keys, you will be making a $0.50 charge to their card that will be immediately refunded.

As part of your form validation, when both keys are given, submit a hidden form that contains all the data necessary to create a card token. You should be able to examine the response in your create card token response handler and determine if the publishable key is valid.

If you get a successful response back from the stripe server containing a card token, turn right around and submit a test charge for $0.50 (the minimum charge amount).

Make sure you're properly catching all the stripe exceptions. I believe with an invalid secret key, you should catch a Stripe_InvalidRequestError. If an exception is thrown you can report to the user.

If no errors are thrown, the charge will be made. Since you don't want to charge your partners, you'll want to capture the charge id from the stripe response and immediately refund the charge.

他のヒント

Validating the secret key is easy, simply calling the Stripe API with any command on the server side.

But for the public key... I found a way with Stripe.js :

let stripe = Stripe( <public key to test> );
setTimeout( ()=>{
    stripe.createToken('pii', {personal_id_number: 'test'})
        .then( result =>{
            if( result.token )
               // public key is valid :o)
            else 
              // nope !
        })
}, 300 )

Note the timeout before calling stripe.createToken(). If you don't do it, the promise returned by createToken() will never come back.

UPDATE: Just received a confirmation from Stripe; this it is a valid and acceptable method.

Got it!

To validate your publishable keys you need to ask stripe for a new token using cURL. If the given key is invalid the response will contain an error message starting with "Invalid API Key provided".

Here's an example written in PHP:

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/tokens");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "card[number]=4242424242424242&card[exp_month]=12&card[exp_year]=2017&card[cvc]=123");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, $publishableKey . ":");

$response = json_decode(curl_exec($ch),true);

if( curl_errno($ch) ){
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

if(substr($response["error"]["message"],0, 24 ) == "Invalid API Key provided"){
    echo "Invalid API Key provided";
}

Same idea for validating your secret keys.

I have been trying to figure out a good way validate provided Stripe API keys also. I figured out a way to validate the secret key without having to make a purchase by creating a test customer. I am still looking into validating the publishable key but I thought this might help someone.

Here is a PHP example:

try {
    \Stripe\Stripe::setApiKey($secret_key);

    // create a test customer to see if the provided secret key is valid
    $response = \Stripe\Customer::create(["description" => "Test Customer - Validate Secret Key"]); 

    return true;
}
// error will be thrown when provided secret key is not valid
catch (\Stripe\Error\InvalidRequest $e) {
    // Invalid parameters were supplied to Stripe's API
    $body = $e->getJsonBody();
    $err  = $body['error'];

    $messages = array();
    $messages[] = 'Status is: ' . $e->getHttpStatus();
    $messages[] = 'Type is: ' . $err['type'];
    $messages[] = 'Code is: ' . $err['code'];
    $messages[] = 'Decline Code is: ' . $err['decline_code'];
    $messages[] = 'Message: ' . $err['message'];

    return false;
}
catch (\Stripe\Error\Authentication $e) {
    // Authentication with Stripe's API failed
    // (maybe you changed API keys recently)
    $body = $e->getJsonBody();
    $err  = $body['error'];

    $messages = array();
    $messages[] = 'Status is: ' . $e->getHttpStatus();
    $messages[] = 'Type is: ' . $err['type'];
    $messages[] = 'Code is: ' . $err['code'];
    $messages[] = 'Decline Code is: ' . $err['decline_code'];
    $messages[] = 'Message: ' . $err['message'];

    return false;
}
catch (\Stripe\Error\ApiConnection $e) {
    // Network communication with Stripe failed
    $body = $e->getJsonBody();
    $err  = $body['error'];

    $messages = array();
    $messages[] = 'Status is: ' . $e->getHttpStatus();
    $messages[] = 'Type is: ' . $err['type'];
    $messages[] = 'Code is: ' . $err['code'];
    $messages[] = 'Decline Code is: ' . $err['decline_code'];
    $messages[] = 'Message: ' . $err['message'];

    return false;
}
catch (\Stripe\Error\Base $e) {
    // Display a very generic error to the user, and maybe send
    // yourself an email
    $body = $e->getJsonBody();
    $err  = $body['error'];

    $messages = array();
    $messages[] = 'Status is: ' . $e->getHttpStatus();
    $messages[] = 'Type is: ' . $err['type'];
    $messages[] = 'Code is: ' . $err['code'];
    $messages[] = 'Decline Code is: ' . $err['decline_code'];
    $messages[] = 'Message: ' . $err['message'];

    return false;
}
catch (Exception $e) {
    // Something else happened, completely unrelated to Stripe
    $body = $e->getJsonBody();
    $err  = $body['error'];

    $messages = array();
    $messages[] = 'Status is: ' . $e->getHttpStatus();
    $messages[] = 'Type is: ' . $err['type'];
    $messages[] = 'Code is: ' . $err['code'];
    $messages[] = 'Decline Code is: ' . $err['decline_code'];
    $messages[] = 'Message: ' . $err['message'];

    return false;
}       

this is working client side validation example with js

<script type="text/javascript" src="https://js.stripe.com/v2/"></script>

<script>
    Stripe.setPublishableKey('{{FILL_THIS_WITH_YOURS}}');
    Stripe.createToken({}, function(status, response) {
        if (status == 401) {
            //invalid public key
        } else {
            //valid public key
        }
    });
</script>

here is the easiest solution I found with Stripe JS v3 for validating the public key.

Then if the key is valid, you can send your form with ajax and validate the secret key server side with the same system.

$('body').on('submit', '.stripe_validate_keys', function(e){
        e.preventDefault();

        //public key submitted by your form
        var public_key = $('.stripe_validate_keys').find('input[name="ba_stripe_public"]').val();

        
        stripe = Stripe( public_key, {
            betas: ['payment_intent_beta_3']
        });

        //Trying to retrieve a customer who don't exist
        //You have to pass only the prefix
        stripe.retrieveSource({
            id: 'src_',
            client_secret: 'src_client_secret_',
        })
        .then(function(result) {
            var res = result.error.message;
            

            var test = res.search( 'Invalid API Key' );
            

            if( test === 0 ){
                //Key invalid
            } else {
                //Now you can submit your form for validate secret key server side
            }
        });
    });
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top