Send an email via MailChimp - api

I think problem is around $api->listSubscribers()
include('../libs/mailchimp/MCAPI.class.php');
$options = array('list_id' => '$list_id', 'subject' => 'Prova', 'from_name' => 'name', 'from_email' => 'info#example.com');
$content = array('html' => '<p>Testo di prova</p>');
$api = new MCAPI($apikey);
$campaignId = $api->campaignCreate('trans', $options, $content);
$api->listSubscribe($options['list_id']);
$api->campaignSendNow($campaignId);
if ($api->errorCode){
echo "Unable to Create New Campaign!";
echo "\n\tCode=".$api->errorCode;
echo "\n\tMsg=".$api->errorMessage."\n";
} else {
echo "New Campaign ID:".$campaignId ."\n";
}
Why does'nt it send an email?

You have a several issues here:
The first one is that you are not doing error checking after each API call. If you take the error checking code from the bottom and stick it after the listSubscribe() call, you'll immediately get an error because you aren't passing any sort of subscriber data (at the very least you need the email address). The docs for listSubscribe are here
Once you do that - unless you've thoroughly read and considered the options in the listSubscribe docs - your second issue is going to be that you are running listSubscribe with the double_optin parameter set to true (the default), which means they won't be subscribed until clicking a link in the confirmation email.
Next, that code is just going to get you in trouble, and probably quickly. If you are going to use psuedo-transcational campaigns it is imperrative that you only create ONE psuedo-trans campaign per type of email and then send that campaign over and over. That's how they are intended to work. Not doing that is going to cause you to fill up your account with a whole bunch of trash campaigns at which point there's no point in using a psuedo-trans campaign since that's the same as creating/sending a regular campaign to a single user over and over.

Do you get any errors?
It seems you are not including the api key, it should look like:
$api = new MCAPI($apikey);
Instead of:
$api = new MCAPI('apikey');
You get the API Key from your api dashboard: http://admin.mailchimp.com/account/api

Related

How to use shutterstock API to search and get photos in a simple way

I am making a site that allows users to search and send to print a shutterstock photo
Like this one:
https://wallprint.ee/
I am following the Shutterstock API documentation and trying to use this to connect, search and pick photos:
https://github.com/shutterstock/php-shutterstock-api
is this the best and easiest way to do it?!!
This is the way I am trying now:
require_once __DIR__ . '/vendor/autoload.php';
$clientId = '***';
$clientSecret = '****';
$client = new Shutterstock\Api\Client($clientId, $clientSecret);
var_dump($client);
// perform an image search for puppies
$client->get('images/search', array('query' => 'puppies'));
$imageResponse = $client->get('images', array('id' => array(1, 2, 3)));
if ($imageResponse->getStatusCode() != 200) {
// error handler
}
$images = $imageResponse->getBody()->jsonSerialize()['data'];
// etc
I expected:
Some kind of response with the content.
I got
Client error: GET https://api.shutterstock.com/v2/images?id=1&id=2&id=3 resulted in a 403 Forbidden response: {"message": "You do not have access to this route. Please contact api#shutterstock.com for more information"}
I read that since I use 'get'
I am told that a free APP can't do using get:
https://developers.shutterstock.com/documentation/authentication#accounts-and-limitations
I wrote about that already to api#shutterstock.com
But what options do I have to develop it in a simplest and painfree manner?
I'm Errol and I work on the API here at Shutterstock. Typically, you will receive this error because your app does not have access to call that route.
Unfortunately, there is no other options to achieve what wallprint is doing without having print partnership with Shutterstock. We want you to have access to the API endpoints you need that way developers like yourself can create awesome apps, however, it needs to be done in a way that doesn't violate Shutterstocks license or terms of service.
Should you have any questions or concerns about this, please drop us a message at api#shutterstock.com

Wit.ai seems to be jumping randomly between stories

I have two separate simple stories on my Wit.ai bot,
the first one takes in the word "Debug", sends "test" then runs a function that outputs context stuff to the console called test_context()
the second one takes in an address, runs a function that changes the context called new_session(), then sends a confirmation of the change to the user structured like "your location has been changed to {address}"
when I type directly into the wit.ai test console it seems to correctly detect the stories and run the corresponding functions, but when I try to use it through the Node.js API it seems to act completely randomly.
Sometimes when typing in an address it will run test_context() followed by new_session(), then output no text, sometimes it will just output the test text followed by the address text and run no functions, sometimes it will act correctly.
The same behavior happens when inputting "Debug" as well.
The back end is set up correctly, as 2 other stories seem to be working perfectly fine.
Both of these stories were working fine earlier today, I have made no changes to the wit stories themselves and no change to the back-end has even touched the debug function.
Is this a known issue?
I encountered this problem as well.
It appears to me as when you do not handle setting context variables in the story from wit.ai correctly (by setting them to null for example), it messes up the story. As a developer it is your own responsability to handle the story correctly "client side", so I can understand wit.ai lets weird stuff happen when you do not do this. Maybe wit.ai decided to jump stories to keep their bot from crashing, still remains a bit mysterious to me. Maybe your problem is of a different kind, just sharing a similair observation and my solution.
Exactly for reasons of testing I created three stories;
handle greetings
tell what the weather in city x is
identify when you want to plan a meeting
The bot is connected to facebook and I handle actions (like planning a meeting) on my nodejs express server.
I said to the bot "I want to plan a meeting tomorrow", resulting in a wit date/time. One timeslot by the way. This is going ok. Then I sent the message "I want to plan a meeting this morning". This resulted in TWO date/time variables in the wit.ai context. In turn, my code could not handle this; two timestamps resulted in null (probably json message getting more complicated and I try to get the wrong field). This in turn resulted in null for the context variable that had to be returned.
So what I did is to catch the error for when the context variable is not filled and just fill in [wit.js could not find date]. This fixed the problem, even though I now of course need to handle this error better.
Old code:
'createAppointment': ({sessionId, context, text, entities}) => {
return new Promise(function(resolve, reject) {
const myDateTime = firstEntityValue(entities, 'datetime');
console.log('the time trying to send ',myDateTime);
createAppointment(context, myDateTime)
context.appointmentText = myDateTime
return resolve(context);
},}
New, working code:
'createAppointment': ({sessionId, context, text, entities}) => {
return new Promise(function(resolve, reject) {
const myDateTime = firstEntityValue(entities, 'datetime');
console.log('the time trying to send ',myDateTime);
if(myDateTime){
createAppointment(context, myDateTime)
context.appointmentText = myDateTime
return resolve(context);
} else {
context.appointmentText = '[wit.js could not find date]'
return resolve(context);
}
});
},
Hope this helps

Outlook webhook notification subscription

I already implemented outlook notification rest api into my code and its work fine but today it suddenly failed and gives me 400 error.
Request outlook for create subscription for notification
Output::
{"error":{"code":"ErrorInvalidParameter","message":"The parameter 'Resource' is invalid."}}
My post data as below ::
URL => outlook.office.com/api/v2.0/me/subscriptions
$subscriptionParameters = json_encode(array(
"#odata.type" => "#Microsoft.OutlookServices.PushSubscription",
"Resource" => "https://outlook.office.com/api/v2.0/me/events",
"NotificationURL" => "https://mydomain/acceptnotification.php",
"ChangeType" => "Created, Updated, Deleted",
"ClientState" => "c75831bd-fad3-4191-9a66-280a48528679"
));
Pass above data to outlook with access_token and email address using cUrl
Please suggest me.
Thank you for reporting this issue. Microsoft engineering team is investigating it right now. Meanwhile, a workaround that worked for multiple subscription cases is to use relative URL for the resource property
e.g.
"Resource": "me/events",
Thanks.

Google OpenIDConnect: Why am I not getting an 'openid_id' value along with 'sub'?

I've read all the documentation I can find on migrating from Google OpenID 2 to OAuth 2/OpenIDConnect, and am currently using a nice class from phpclasses.org . This class seems to work quite well with both Google and Facebook (haven't yet tried other providers), but I'm having a problem with just one aspect of Google's migration path that is quite critical to me: obtaining the google user's old OpenID identifier in addition to the new OpenIDConnect 'sub' value for that user. I've got users registered in my database only through their old OpenID identifiers.
According to Step 3 in Google's Migration Guide it looks like all I should need to do is add a parameter "openid.realm=http://www.example.com" to the authentication request sent to https://accounts.google.com/o/oauth2/auth.
I looked up in my old code what the realm was that I used for its OpenID registration process (it was 'http://' . $_SERVER['HTTP_HOST'];), and then I made sure that the redirect urls in my application were compatible with that realm.
I added that value (url-encoded) as the value of an openid.realm parameter passed on the authentication request made within the class. But when the class exchanged the token for an access token, it got back the correct email, name, sub, etc, but there was no openid_id parameter present. BTW, my scope parameter is 'openid email profile'
Does anyone have a suggestion for what else I should try, or what I can do to determine what the problem is? Does anyone have successful experience getting the openid_id parameter value in php code? I'd really rather not go the client-side route with their "Sign-in with Google" button, and according to the docs that really shouldn't be necessary (plus there's no particular reason to believe it would solve my problem if I did it).
Just discovered it's in the id_token returned along with the access_token when you exchange the authorization_code for the access_token.
In the Migration Document, Step 3 first two paragraphs:
When you send an OpenID Connect authentication request URI to Google
as described in Step 1, you include an openid.realm parameter. The
response that is sent to your redirect_uri includes an authorization
code that your application can use to retrieve an access token and an
ID token. (You can also retrieve an ID token directly from the OpenID
Connect authentication request by adding id_token to the response_type
parameter, potentially saving a back-end call to the token endpoint.)
The response from that token request includes the usual fields
(access_token, etc.), plus an openid_id field and the standard OpenID
Connect sub field. The fields you need in this context are openid_id
and sub:
This is confusing and misleading/wrong. What token request? The authentication request returns an authorization code that you can exchange for an access_token and an id_token. The parenthetical remark about adding id_token to the response_type doesn't help much, as the various ways I tried to do that resulted in an error. But in any event, the
"usual fields (access_token, etc.), plus an openid_id field..."
is wrong. The access_token never appears in the same list at the openid_id field. The access_token appears in a list with the id_token, and the openid_id field is encoded within the id_token!
For testing purposes, you can decode an id_token using https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=<string>
In this documentation I couldn't find a useful description for how to decode an id_token, only caveats about their being sensitive, and how to validate them (though validation is not needed if obtained directly from a google endpoint as is the case here). I downloaded google's php client, and extracted code from it (src/Google/Auth/OAuth2.php and src/Google/Utils.php). And from that it's easy enough to figure out how to decode the id_token string: explode on ., base64_decode element 1, and json_decode that.
Update 2015-05-21: In reply to #Arthur's "answer", which would have been more appropriate as a comment on this answer. I would have commented on that answer myself, but comments aren't allowed to be very long and don't allow image uploads, plus I thought this extra info improves my answer...
Below is a screenshot from netbeans/xdebug, showing the array elements I get when decoding the id_token I get. Interesting that the intersection of the fields listed here with the fields listed by #Arthur is the null set. So I suspect that whatever #Arthur is decoding, it is not an id_token of the kind described here. I'm not familiar enough with this stuff even to guess what it is that's being decoded in that answer.
I'm afraid I don't have the time to dig through the library I use to extract the exact code path that produces the id_token I decoded to get this array using the simple algorithm I described. But I can tell you that the library I use is this: http://www.phpclasses.org/package/7700-PHP-Authorize-and-access-APIs-using-OAuth.html
Using it just as documented does not give you the id_token you need for this for two reasons:
The pre-configured server for Google with Oauth 2 doesn't handle the openid.realm parameter. To handle that, I added the following server definition to the oauth_configuration.json file:
"Google-OpenIdConnect":
{
"oauth_version": "2.0",
"dialog_url": "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope={SCOPE}&state={STATE}&openid.realm={REALM}",
"offline_dialog_url": "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope={SCOPE}&state={STATE}&access_type=offline&approval_prompt=force",
"access_token_url": "https://accounts.google.com/o/oauth2/token"
},
Just after the call to Initialize(), you need to add
$client->store_access_token_response = true;
Without that, the actual access_token response is not accessible (at least not the way I'm using the class). With those two changes in place, my exact code to get the openid_id using this class is as follows:
protected function jwt_decode($jwt) {
$segments = explode(".", $jwt);
if (count($segments) != 3) {
throw new Exception("Wrong number of segments in token: $jwt");
}
// Parse envelope.
$envelope = json_decode($this->urlSafeB64Decode($segments[0]), true);
if (!$envelope) {
throw new Exception("Can't parse token envelope: " . $segments[0]);
}
// Parse token
$json_body = $this->urlSafeB64Decode($segments[1]);
$payload = json_decode($json_body, true);
return $payload;
}
protected function getOpenid_id() {
require_once 'Phpclasses/Http/Class.php';
require_once 'Phpclasses/OauthClient/Class.php';
require 'Phpclasses/Google/private/keys.php';
$client = new oauth_client_class;
$client->configuration_file = $phpclasses_oauth_dir . '/oauth_configuration.json';
$client->server = 'Google-OpenIdConnect';
$client->redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . strtok($_SERVER['REQUEST_URI'], '?');
$client->client_id = $GOOGLE_APPID;
$client->client_secret = $GOOGLE_APPSECRET;
$client->scope = 'openid email';
$client->realm = $this->getRequest()->getScheme() . '://' . $this->getRequest()->getHttpHost();
$me = null;
if (($success = $client->Initialize())) {
// set *after* the call to Initialize
$client->store_access_token_response = true;
if (($success = $client->Process())) {
if (strlen($client->authorization_error)) {
$client->error = $client->authorization_error;
$success = false;
}
elseif (strlen($client->access_token)) {
$success = $client->CallAPI('https://www.googleapis.com/oauth2/v1/userinfo', 'GET', array(), array('FailOnAccessError' => true), $user);
$me = (array) $user;
if (!array_key_exists('id_token', $client->access_token_response)) {
throw new Exception('No id_token in \$client->access_token_response');
}
$openid_id = $this->jwt_decode($client->access_token_response['id_token']);
$me['openid_id'] = $openid_id;
}
}
$success = $client->Finalize($success);
}
if ($client->exit)
exit;
$client->ResetAccessToken();
if ($success) {
return $me;
}
// Code to handle failure...
}
Despite sootsnoot's (own) answer I still can't find the openid_id field anywhere. When decoding the id_token there are only "issuer", "issued_to", "audience", "user_id" , "expires_in" , "issued_at", "email" and "nonce" fields.
No "openid_id" field in sight..
Any ideas?
In response to sootsnoot's response :) And I apologize for not having enough reputation to comment, otherwise would have done so.
Am using an OpenID Connect library that takes endpoints from auto-config: https://accounts.google.com/.well-known/openid-configuration
So assume the endpoints are not the problem. Indeed it seems I was checking the wrong id_token. However, even when checking the correct one I still don't see the "openid_id" field. I now see everything you have, except that I have a "nonce" field instead of the "openid_id" field:
stdClass::__set_state(array( 'iss' => 'https://accounts.google.com', 'sub' => ****, 'azp' => ****, 'email' => ****, 'nonce' => ****, 'at_hash' => ****, 'email_verified' => true, 'aud' => ****, 'iat' => ****, 'exp' => 1432300788, ))
Must be doing something wrong, but what...
Final update:
Found the issue: was passing realm parameter as openid_realm=... instead of openid.realm=...
Oh do I feel stupid... :)

Docpad : show error/success message on contact form

I added a route in my docpad.coffee file to handle form submissions, that I validate using the express-validator middleware. Now depending on the validation, I want to redirect the users to the same contact page but displaying either a success message when validation is successful (here I'll send an email), or display the error messages.
I didn't manage to pass the validation message to the template to display it. I tried almost all combinations of dynamic: true/false, res.locals = validationMessages, res.sessions = validationMessages, res.templateData = validationMessages with no success.
Furthermore, adding dynamic: true made the changes to the content not appear at all, whatever refresh strategy I use (private mode, cleaning cache, relaunching Docpad, refreshing without cache, etc.). I should probable file a bug about it.
How to ?
I'm using Docpad 6.53.0 (latest to date), node 0.10.15, on OS X 10.8.4
I cheated on this one a bit by appending a hash to the redirect url (eg: "www.mywebsite.com/#messagesent"). I then use client side javascript to read the hash and then show the appropriate message. Something like this:
if (location.hash == "#messagesent") {
$('#message-sent').show();
setTimeout(function () {
$('#message-sent').fadeOut(1000);
}, 1000);
}
Not quite what you were asking though :)