I am using WordPress, but I am using an “out of the box” solution because my client requested it specifically. I have this Javascript which creates a form and when the form is submitted it creates a cookie with the token in it, so I can retrieve it from PHP, it looks like this:
<form action="/wp-content/themes/betheme/includes/add_payment_method.php" method="post" id="add-card-form"> <div class="form-row"> <label for="card-element"> Credit or debit card </label> <div id="card-element"></div> <!-- Used to display Element errors. --> <div id="card-errors" role="alert"></div> </div> <button>Add payment method</button> </form> <script src="https://js.stripe.com/v3/"></script> <script> var style = { base: { color: '#ffffff', fontSize: '14px', fontSmoothing: 'antialiased', '::placeholder': { color: '#ccc', }, iconColor: "#fff" }, invalid: { color: '#e5424d', ':focus': { color: '#303238', }, }, }; var stripe = Stripe('xxxxxxxxxxxxxxxxxxxxxxx'); var elements = stripe.elements(); var cardElement = elements.create('card', {style: style, hidePostalCode: true}); window.mobilecheck = function() { var check = false; (function(a){if(/(android|bbd+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); return check; }; if(mobilecheck()) { cardElement.mount('#Content > div > div > div > div.section.mcb-section.hide-desktop > div > div > div > div > div > div > div > form > div.form-row >div#card-element'); } else { cardElement.mount('#Content > div > div > div > div.section.mcb-section.hide-tablet.hide-mobile > div > div > div > div > div > div > div > form > div.form-row > div#card-element'); } cardElement.addEventListener('change', function(event) { var displayError = document.getElementById('card-errors'); if (event.error) { displayError.textContent = event.error.message; } else { displayError.textContent = ''; } }); // Create a token or display an error when the form is submitted. var form = document.getElementById('add-card-form'); form.addEventListener('submit', function(event) { event.preventDefault(); stripe.createToken(cardElement).then(function(result) { if (result.error) { // Inform the customer that there was an error. var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { // Send the token to your server. stripeTokenHandler(result.token); } }); }); function createCookie(name, value, days) { var expires; if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toGMTString(); } else { expires = ""; } document.cookie = escape(name) + "=" + escape(value) + expires + "; path=/"; } function stripeTokenHandler(token) { createCookie("stripe_token", token, 1); var form = document.getElementById('add-card-form'); form.submit(); } </script>
When the form is submitted, it executes this PHP in add_payment_method.php
:
<?php require_once("../../../../wp-load.php"); submit_stripe_payment_method($_COOKIE['stripe_token']); ?>
In my functions.php
file for my theme, I have:
require_once('stripe-php/init.php'); .... function submit_stripe_payment_method($token) { print_r($token); $current_user_id = get_current_user_id(); echo 'Your User ID is: ' .$current_user_id; $customer_id = get_user_meta( $current_user_id, '_stripe_customer_id', true ); echo "CUSTOMER_ID: ".(string)$customer_id; StripeStripe::setApiKey("xxxxxxxxxxxxxxxxxxxxxxx"); echo "MADE IT HERE"; $customer = StripeCustomer::retrieve((string)$customer_id); echo "CUSTOMER: ".$customer; $customer_card = $customer->sources->create(["source" => $token]); echo "<pre>"; var_dump($customer_card); echo "</pre>"; }
The output of the above is:
[object Object]Your User ID is: 1CUSTOMER_ID: cus_DsoF18uw1dR0ujMADE IT HERE
As you can see it only gets as far as “MADE IT HERE” echo
.
I have verified in the Stripe web console that the $customer_id
I am using is correct, and I don’t have any errors, PHP or otherwise. The only thing I can think of is I am using the token wrong but it seems pretty straight forward. As you can see, the $token
prints as [Object object], and it does this no matter how I try to log it, so I can’t see exactly what it is, but this makes sense because it contains sensitive information used to validate the credit card…also maybe it never gets to that point because I never see the echo "CUSTOMER: ".$customer;
statement, so maybe it gets hung up on:
$customer = StripeCustomer::retrieve((string)$customer_id);
Also, I tried the above without (string)
first but got the same result.
So after all of this, I check the Stripe console, and no card has been added.
UPDATE
Apparently the API version I am using is not the latest version, I can upgrade, I just want to know if anyone thinks this is a possible solution before I do it. As it might change how stripe works throughout the site (with the plugin). I am using 2018-02-28
and I can upgrade to 2018-09-24
. I am also testing on localhost
environment so I am not https
, but I don’t think this matters for testing.
UPDATE
I realized I hadn’t added the endpoint for my localhost
setup to the stripe
console admin area. To do this I had to use ngrok
(as suggested by Stripe if you are using localhost
). I am using localhost
on port 8888
, so I did ./ngrok http 8888
and then tried again and it didn’t work. It does say in WordPress that the endpoint will enable you to receive notifications on the charge statuses.
So maybe it isn’t relevant for adding a payment method. I used the http
url for ngrok
not the https
url.
UPDATE
I manually installed stripe-php
so I tried with composer
but it didn’t help, same result.
UPDATE
I changed my key to the secret key
and that allowed me to retrieve the $customer
but I don’t see any output for $customer_card
and when I look in the dashboard no card has been created.
UPDATE
I checked the Stripe
dashboard and I am receiving an error when I try to create the source:
{ "error": { "code": "resource_missing", "doc_url": "https://stripe.com/docs/error-codes/resource-missing", "message": "No such token: [object Object]", "param": "source", "type": "invalid_request_error" } }
What am I doing wrong with the token?
UPDATE
Solution to token problem: in test mode, the token is just a string that corresponds with the test credit card number you are using, I needed "tok_visa"
for 4242424242424242
. https://stripe.com/docs/testing
Advertisement
Answer
The problem might be that in line
StripeStripe::setApiKey(“xxxxxxxxxxxxxxxxxxxxxxx”);
you are using Publishable key
starts with pk_xxx
, instead you should be using Secret Key
sk_xxxx
in your account.
You could see the errors from Stripe Dashboard
after you login.
Let me know if that helps
EDIT
I also needed to use a testing token, which is just a string that corresponds to the the test credit card number you are using. https://stripe.com/docs/testing. See the Tokens
tab.