Passing sever side zip/postcode to Stripe checkout - stripe-payments

I am trying set up Stripe checkout so I can pass my server side customer zip/postcode to the Stripe checkout. It seems like it should be very simple but I cannot get it to work!
At it's simplest, the code I am using is:
<form action="charge.php" method="POST">
<script
src="https://checkout.stripe.com/v2/checkout.js" class="stripe-button"
data-key="pk_test_redacted"
data-amount="2000"
data-name="Demo Site"
data-description="2 widgets (£20.00)"
data-currency="gbp"
data-address_zip="NG15 6UR">
</script>
</form>
the transaction works fine but it does not pass the zip/postcode so that it can be AVS checked.
What am I doing wrong?
Edit:
So apparently you cannot pass address information using checkout.js - you can only get the form to require the address from the customer when they put their card details in using
data-address="true2"
As far as I can tell, this means I can either hassle the customer by getting them to add their address details when I already have them!
or I have to use stripe.js which means I have build my own form, make it look pretty, validate it etc. Not a massive thing but, when there is a form there that does everything I need but accept address form fields passed at form creation, it is a little annoying :-(
If anyone knows otherwise I would love to hear it but this info came from the #stripe irc channel so I think it is probably correct.

As said in the Edit, I did have to use stripe.js and make my own form. Shame this small omission means quite a bit of extra work - but still much better than Paypal's mess of APIs and documentation! Cheaper too.

Untested but there may be a solution as you can update a card before the charge , you are able to update the customers card from the $token that you pass to your backend processor in php for example:
$cu = Stripe_Customer::retrieve($customer->id);
$card = $cu->cards->retrieve($token);
$card->address_city = $form['city'];
$card->address_line1 = $form['address_line_1'];
$card->address_line2 = $form['address_line_2'];
$card->address_state = $form['county'];
$card->address_country = "United Kingdom";
$card->address_zip = $form['postcode'];
Then take the charge
$charge = Stripe_Charge::create(array(
'customer' => $customer->id, etc...

Related

How does a Gmail message Id or ThreadId map to the new Gmail UI?

Edit: addressing the first comment below and for clarity, this isn't a code question. The question is simply:
What do I put into the URI querystring of the new Gmail UI to view a draft message created by the Gmail API?
Despite this not really being a code question, I'm asking on Stack Overflow as it's Google's preferred platform for Gmail API questions.
--
If I view a draft message in the new Gmail UI, the URI is something like this:
https://mail.google.com/mail/u/1/?zx=iij9apqgzdf4#drafts?compose=jrjtXSqXwlFGnSGCQgDCdnHGVFdlpFMgzsCNgpQstQLxdLCMkjKstBmWZkCmjhWTQnpsZCJF
I can't see any way to create such a link from the Id or ThreadId of a message created via the Gmail API.
Previously, one could do this:
https://mail.google.com/mail/u/1/?zx=ov61dxfbrcga#drafts?compose=1631caae9dbb074d
where the value of "compose" is the Id.
How can the same thing be accomplished in the new UI?
I've been encountering the same problem and have had some success in this problem, as well as some issues I still can't get past.
Good news: The new compose parameter format is some kind of "base40" encoding. I searched the Gmail source for a restricted alphabet string, and found and deobfuscated the bit of code doing this encoding/decoding: https://gist.github.com/danrouse/52212f0de2fbfe33cfc56583f20ccb74
This code includes an encode and decode function which should work for Gmail-format query parameters.
Bad news: The values that it is encoding to open draft emails do not appear to be available using the Gmail API. Specifically, they look like this:
thread-f:NEW_THREAD_ID+msg-a:DRAFT_ID -- while the draft ID is the same as it was before, the Thread ID does not appear to match any of the IDs that the Gmail API returns.
Interestingly, if you inspect the subject row in the Gmail UI, it has dataset attributes including all of both the old format and new format IDs - but it's still unclear how to get the new ones programatically.
Thanks to #frank-szilinski - he pointed out that the old format is now translated. I.e. this now works again:
https://mail.google.com/mail/ca/u/1/#drafts/1661237c4db71ace
It doesn't seem to work when the Gmail tab isn't already open, however.
Building on #kremonte gist, and #chris-wood comments, I made a rails gem that correctly creates the open-the-draft-inside-gmail URL.
It's here - https://github.com/GoodMeasuresLLC/gmail_compose_encoder
It's for the use case of "my code created a draft (prepopulated with some text, of course) and now I want to open the draft in compose mode so that my user can review it before hitting "send".
How to get the URL for a draft
If, for example you use a list request from which you get your draft objects:
{
"id": string,
"message": {
object (Message)
}
}
You can take this id and put it into a URL in this format:
mail.google.com/mail/#inbox?compose=[id]
Eg.
mail.google.com/mail/#inbox?compose=3doinm3d08932d
This will open up GMail with the relevant draft open.
I was struggling because I wanted it to work with multiple accounts. However the authuser parameter did not help.
Inserting the email address instead of the integer after the u/ component solved the problem.
https://mail.google.com/mail/u/{email_address}/#drafts?compose={message_id}
The message id is the one provided by the API.

RichResponse VS basicCard order

I'm facing a quite annoying issue with the Actions On Google SDK.
I want to send to the user these things in this order :
A basic card
A text
A suggestion chip
I simply did this :
let richResponse = assistant.buildRichResponse();
richResponse.addBasicCard( ... );
richResponse.addSimpleResponse( ... );
richResponse.addSuggestions( ... );
Problem is, no matter the order set in my code, google will always send the simple response before the card.
If i log the JSON before sending it, the card is indeed AFTER the message.
I tried to simply switch them in the JSON before sending it but then the assistant simply crashes.
All in all, i see no option to achieve what i want :/
If i could send a 1 item carousel i wouldn't need all that, but it's apparently impossible to send such carousel because the assistant also crashes.
If i could add buttons with JSON payload instead of external URL in BasicCard i could also workaround all these issues, but that's not possible either... I feel quite stuck.
Anyone has a workaround ?
Regards
The RichResponse object requires that the first item in the response be a SimpleResponse object, so you need some text first.
However, you are allowed to have two SimpleResponse objects, so you can try adding a SimpleResponse, the card, another SimpleResponse, and then the suggestions.
It isn't clear how being able to have just one option would let you work around this (although I agree). You would still need a SimpleResponse that appears before the option.
It isn't clear what you mean by "buttons with JSON". In this sense, suggestion chips work exactly the same way options do - they send something back to your webhook (options send the tag, while the suggestion chips send their contents).

How can I prevent duplicate charge using Stripe?

I'm using Stripe to allow my customer to save a credit card and pay invoices (that have a unique id). On payment, I use a form to send a POST request with the card id (provided by stripe) to my server, and the controller charges it. Then I marked the invoiced as payed on my side.
Turns out that if I double click my form's submit button quick enough, I send two POST request and the cards ends up being charged twice, because when the second POST request arrives on my server, the POST request from my server to Stripe API (from the first click) isn't finished, thus the invoice has not been marked as payed yet.
I'm considering disabling the form submit button after first click, but I feel there may be a cleaner way.
Is there on Stripe's side to prevent duplicating charges (maybe using my invoice id)? If not what would the best back-end method to do this on my side?
Disabling the form submission after the first click is definitely the easiest way to implement this.
Another approach is to use idempotent requests as documented here. The idea is that you pass a unique identifier when making a request to Stripe's API that ensures you can only run this transaction once. If you re-run the query with the exact same idempotency key you will get the original response from the first call which ensures you never have 2 charges created for the same "transaction" on your website.
yes idempotent request is correct way to implement this.
you can refer this here
https://stripe.com/docs/api#idempotent_requests
another simple solution which you can implement is use of state machine by keeping track of stripe api call.
As mentioned by other answers, you can use Idempotent Requests to prevent duplicate charges. Here's how I've implement it:
On checkout.php:
<?php
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return substr(str_shuffle($chars),0,$length);
}
$idempotency = rand_string(8);
?>
...
<form method="post" action="payment.php">
<input type="hidden" name="idempotency" id="idempotency" value="<?=$idempotency?>">
...
</form>
...
On payment.php:
<?php
$idempotency = preg_replace('/[^a-z\d]/im', '', $_POST['idempotency']);
...
try {
$charge = \Stripe\Charge::create(
["amount" => $price,
"currency" => $currency,
"description" => $invoiceid,
"customer" => $customer->id ],
["idempotency_key" => $idempotency,]);
}catch(Exception $e) {
$api_error = $e->getMessage();
}

Instagram API: Can i check if user is verified?

I would like to know if there is any way to check if the user verification badge with the Instagram API?
I have saw that https://api.instagram.com/v1/users/{user-id} doesn't returns if the user is verified, but if you view the source code of a users page, you can see that it has a boolean that called isVerified key and it's value inside a json struct of the user.
Thanks!
Ok, this is not a great answer but here is how I accomplished this same task. Once I have a username from the API I do the following regex on the source of their profile page:
$response = file_get_contents('https://instagram.com/'.$username);
if (preg_match('/"user":\{"username":"'.$username.'",.*?"isVerified":true\},"__path":".*?'.$username.'.*?"/s', $response) || preg_match('/<meta content=".*?official.*?account.*?" name="description" \/>/is', $response)) {
print "VERIFIED USER!";
}
As I said before this is super hacky but the API currently doesn't provide an isVerified value. Until they do I am using this regular expression. It looks for "isVerified":true part of the JSON struct you referenced. (example: https://instagram.com/taylorswift)
We also added an additional check where if the meta content tag has "official account" in it then we assume it's official. (example: https://instagram.com/3doorsdown) We added this check because Instagram started doing verified accounts in 2014 and there are quite a few celebrities that haven't gotten a verified badge yet. It should pick up some of the pieces but could very well bring in false positives too.
NOTE: This solution will break if Instagram ever changes the JSON struct or meta tags on their pages so use at your own risk. We only needed a script to check a small amount of usernames for verified badges and I came up with this real quick. The best solution will be whenever they update their API.

Exp:resso Store passing credit card name

We were using the EWAY merchant plugin for Exp:resso Store and noticed that it was passing the incorrect credit card name to EWAY - instead it's reporting the billing_name for some reason, and not the name from the <input name="payment[name]"/> field.
I understand the store doesn't record any credit card info, but is there a setting I'm missing or something? Bug?
The billing_name is simply a fallback when no name is specified. Your card name input field should actually look like this:
<input name="payment[card_name]" />
I just looked at the example templates and realize this is incorrect, so will get that fixed up.
Also note there is now a dedicated ExpressionEngine Q&A site which is a better place for questions like this :)

Resources