EDIT: There's a chance I may have been a complete bonehead and mistook USER:UID for the member's ID when in fact it may be referring to the account admin ID. I have changed it to simply include the member's email address as the last URI segment. Is that an acceptable approach?
I'm setting up an EDM in MailChimp that includes a link to a website form. The URL is structured like so:
http://domain.com/foo/*|LIST:UID|*/*|USER:UID|*
The idea is that some PHP on that page gets the member info using the list ID and the user ID in the API (3.0) endpoint for use in a cURL operation:
$url = 'https://us4.api.mailchimp.com/3.0/lists/' . $listid . '/members/' . $userid;
The retrieved data would then pre-populate the form so that the user could edit the information and submit to 1) store the record of the submission locally in the CMS, and 2) send a PATCH command to the API.
This worked fine in my testing with a different MailChimp account, but when switching over to the production account, the *|USER:UID|* merge tag started sending incorrect hashes. I even changed the list but the ID stayed the same, and neither IDs were valid MD5 hashes.
To be clear, this is not an issue with authorization, I correctly changed the credentials (API key and username) and data center in the URL. If I manually enter a valid user ID into the URL the information is retrieved successfully. I simply can't get the correct user IDs to be embedded in the email.
Additionally, my initial testing using PUT instead of PATCH failed if the entered email address was not found in the list, sending back a message to use PUT (which I was).
Yeah, passing the email address back to your page is likely the best option for you here.
I know this question is old, but perhaps you were looking for *|UNIQID|* instead of *|USER:UID|*? According to MailChimp's documentation:
*|UNIQID|* Pulls in the $member->email->unique_id; (API function).
If used in an email campaign, this tag will pull in your subscriber's
unique ID. It can also be used to create unique links for subscribers.
The merge tag you were using, *|USER:UID|*, simply says:
*|USER:UID|* Displays the "u" parameter from your hosted Mailchimp audience forms.
While their documentation does not specify what the "u" parameter is, this other stack overflow answer to a related question mentions that it is an identifier for your account, which is exactly the same conclusion you came to in your question's edit :)
Personally, I prefer to pass unique IDs as opposed to email addresses for the sake of privacy. Some of my clients put a high value on privacy and security so we do not pass any personally identifiable information (PII) where it could be intercepted.
Related
I'm doing a soap request to an external API using Laravel & Guzzle. All other calls have succeeded to get the actual response but for the redirecting user to the external page has failed because the external API web service only allows my server IP to access that page.
I have tried:
windows.location (javascript)
location header (PHP)
return redirect URL (PHP)
This is their documentation on how to redirect in VB language :
redirection code in VB
All of these methods only use the browser redirection which is using user IP not the server IP.
Any method that I can use to redirect user using my server IP that you guys can recommend?
Thanks in advance.
Extra context/information:
Example screenshot for the fourth call which include get the quotation number and generate the url parameter
That is the code for VB that they provided in API documentation. So why I want to bring the user to the page? It is because when the GetQuotation (fourth call) is already submitted to their database and it will return QuoNo that will be used in the URL parameter. When the user gets redirected to the external page with parameter QuoNo=12412194149124, their backend will query for the quotation details that the user fills in my side (mydomain.com/form) and auto filled it on their side (otherdomain.com/form).
If you see from the screenshot, the System.Diagnostics.Process.Start will execute the url once the Quotation number (QuoNo) is generated. So once the user click on the 'buy now' button on our end (mydomain.com/form), it will call the fourth call (GetQuotation guzzle function) and generate a Quotation Number (QuoNo) then it will be populated in http://otherdomain.com/main.a5w?tokenid=wm-9Kj-14e-Fa4-I1adlXrQ00weqwe3S&QuoNo=QUO022348921312301623. Based on what my understanding on VB code, System.Diagnostics.Process.Start will force the url to be opened.
I'm sorry if it's still lacked of info given. Feel free to ask more. Thank you
What you want can not be achieved sadly. The only thing you can do with the redirect is tell the browser where to go, you have no control over the IP here since this would pose all kinds of issues regarding security and identification. The only way to achieve what you want is to wrap the html of the resulting webpage in your website or remove the restriction of the ip addresses. Another solution could be to build a simple page which is accessible to everyone and limit the API routes to specific IP addresses. For example:
Let's assume the payment gateway is at: example.com/checkout, this one would be accessible to everyone and would contain a form to which you can perform the redirect and fill this form with the passed data.
This form would then post the information to example.com/api/v1/checkout which will process your form data and return if the transaction was succesful. Based on this return the user will be redirected to another page. This is assuming you have control over the other domain since only with your server IP you can access this site.
If this is not the case there is no other way than to post the data to an endpoint via guzzle and use these return values to provide feedback to the user.
I hope this answers your question, if anything is unclear please let me know.
I'm trying to retrieve some information about the user via Linkedin API, such as name, location, email address, phone number(s). The first three ones are returned perfectly, but the phone number is not returned for some reason (the field isn't even included in the return set). I have added it later, so I guess in might be some caching on the Linkedin's side.
All the permissions are included both in request and in the app's settings, the scope is: r_basicprofile r_emailaddress r_fullprofile r_contactinfo w_share
The query URL is: https://api.linkedin.com/v1/people/~:(id,first-name,last-name,phone-numbers,location:(name),email-address)?format=json
What might me the reason?
Thanks in advance!
An additional investigation has shown that to obtain any field from the full profile (including phone) it is necessary to request an ability to use this permission for your application via Apply with LinkedIn program.
I am working on drupal6 to develop a web application for office automation. I have an Employee content type. Each time I create an employee content, an account should be created with user name, and email id taken from fields of employee content. I've searched for the same on net, and found few solutions written completely in php, but i couldn't find how this can be done through rules-> triggered rules option in drupal(shown in figure). What entries should be provided in these username,email fields? I should get these from the content that I just created before triggering this. I tried exploring "Replacement patterns for saved content" option provided like [node:field_name], but no luck. Can someone help me with this?
None of the following (which are listed in "Token replacement patterns -> Replacement patterns for saved content") are working
[node:field_emp_name-formatted] Formatted and filtered text
[node:field_emp_name-raw] Raw, unfiltered text Warning: Token value contains raw user input.
[node:field_emp_mail-formatted] Formatted email address
[node:field_emp_mail-raw] Raw email address Warning: Token value contains raw user input.
Thanks in advance.
It suddenly started working for the following field values
User name: [node:field_emp_name-formatted]
User's E-mail: [node:field_emp_mail-raw]
I think it does not take "formatted" field for E-mail, since it has anchor tags, etc.,
I'm creating a PHP API for a website and I'd want to restrict the API access to domains that are registered on our server (in order to prevent abusing of API usage). So, this is my approach right now, and well, it should look pretty good on paper.
The API is setup at api.example.com.
A user that wants to use the API registers with us, adds his domain and gets an API key.
The user of the API will use his API key to encrypt his request data (via mcrypt) and sends it, via cURL to api.example.com.
My server checks from which domain this API request comes from and matches that domain to an API key in the database. If there is an API key, the API decrypts the request via mcrypt with that key and then using the same method encrypts and sends the result.
I'm stuck on step 4. Originally, I planned to use HTTP_REFERER to check it, but since cURL doesn't send one by default and it could be easily faked in the user-side code (CURLOPT_REFERER as far as I remember), I am stuck here.
Is there a method to know from which domain this API request comes from? I see that it can be done with some popular APIs like the reCAPTCHA one. Checking the _SERVER["REMOTE_HOST"] isn't really an option because of shared hosts (they have the same IPs) so this would not be able to prevent abuse (which would originate mostly from shared servers anyway).
Is there such a method to check for it? Thanks!
#Shafee has a good idea it just needed some tweaking. We're focusing on the visible part of the API call, which is the API key. This is visible in the URL and tells the API who is requesting the data. Rather than trying to prevent others from stealing this key and running their own cURL call with the domain they intercepted it from, we can 'just add' another key to the mix, this one not visible to those interceptors. I'm not saying stop checking where the request is coming from, it's still a good way to kick out invalid requests early on in the script, but with a second key, you guarantee that only the person requesting the data actually knows how to get the data (you're trusting them not to give it away to anyone).
So, when the user registers for a key, you're actually assigning two different keys to the user.
API_KEY - The public key that connects you to your domain. The system looks up the domain and key provided in order to find the next key.
MCRYPT_KEY - This is the key that will be used to actually encrypt that data via Mcrypt. Since it's encrypted data, only the requester and the server will know what it is. You use the key to encrypt the data and send the encrypted input with your API key to the server, which finds the key that it needs to decrypt that input via the API key and domain (and IP) that have been provided. If they did not encrypt the data with the proper key, then decrypting with the correct key will return gibberish and the json_decode() call will return NULL, allowing the script to simply return an 'invalid_input' response.
Ultimately with this method, do we even need to check where (domain/IP) the request is coming from? Using this method it really comes down to the API users not giving away their API/MCRYPT key pair to other users, similar to not giving away your username/password. Even so, any website can easily just go sign up to get their own key pair and use the API. Also to note, the API will not even return anything useful to their server unless the user on their end logs in using the correct username and password, so their end will already have that information. The only thing new our server is really returning is their email address upon successful validation of the user. Having said that, do we even need to use cURL? Could we not simply use file_get_contents('http://api.example.com/{$API_KEY}/{$MCRYPT_DATA}')? I realize I'm asking more questions in my answer...
You can varify what ip the request comes from, and you ofen can do a ptr search to get a domain name for that ip, but probely the ip adress have more then one domain, and you end up whit the wrong one, so i recomendate that the client send his domainname in the reques, maybe whit HTTP_REFERER, and that you make a dns check if that domain points to the ip asking for it, but notice that a domain, like google.com, can point to more then one ip.
(the ip could probely be faked to, whit some good hacking skill, but thats out of my knowledge)
How about introducing a second variable like lets say an app id. When a user registers her domain, associate this id with the domain. The user needs to submit the app id with each request without encryption along with the encrypted api call. Then you can look up the app id get the app secret and try to decrypt?
In order to best prevent abuse of your API, limit either the speed of requests, or limit the number of requests they can make. If someone is stupid and shares their API key, they'll only be limiting their own API usage, making it more economical for people who intend on abusing the API to get their own key.
Plus, what if someone decides to implement a desktop application using your API? Surely they won't require their users to send their IP addresses to them so that they can whitelist them?
Also, you can combine limiting speed/limiting requests, and limit speed based on the number of requests like how Verizon limits the speed of their 3G network if you pass a certain amount of data usage.
I know how to get the entire contacts list using Google Contacts API (I get a session token and use Google's Zend package for PHP).
But how can I get the person's name and email address? Currently, the Contacts API just seems to give all of the contacts. I'm not sure how to distinguish which email and name out of that list corresponds to the user's account.
Is there an easy way to get the user's full name and email address?
Any help would be useful. Thanks!
yes goto http://code.google.com/apis/contacts/docs/3.0/reference.html#ContactsFeed
and see the "Contacts feed"
they say to use the Default, it worked for me after using the default - lower case only.
request
http://www.google.com/m8/feeds/contacts/default/full
will give you the user's details.
http://www.google.com/m8/feeds/contacts/bla#gmail.com/full
will give you a contact info (if bla#gmail.com) is a contact.
If you ask for the "default" contact (i.e., me), you get what you need.
Mind that you need to write default with a lowercase d and not as written in the documentation.
THe xml returned for the default contact list will have the user's name and email within the "author" element. I don't know PHP, but the code might look something like this...
email = xml["author"].first["email"].first
name = xml["author"].first["name"].first
You can obtain this information by querying :
"https://www.google.com/m8/feeds/contacts/default/full?oauth_token=YourToken123"
and parsing your XML (SimpleXML example):
$user_email = $xmlResult->id;
$user_name = $xmlResult->author->name;
$xmlResult->author->name will give you the whole name as the user has configured it, so it's not certain that you will get in the "FirstName Lastname" format.