XML appears valid, but still getting Error 400

SOLVED
Highlighted
Occasional Participant

XML appears valid, but still getting Error 400

This is my first attempt at using the PHP wrapper for the CTCT API so please be gentle.

 

I'm attempting to generate a new campaign and schedule it from a script on my website.  The XML that is generated from the campaign's createXML function is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom">
	<link href="/ws/customers/customer/campaigns" rel="edit"/>
	<id>http://api.constantcontact.com/ws/customers/USER/campaigns/0</id>
	<title type="text">Powder Alert: 02-21-2013</title>
	<updated>2009-10-19T18:34:53.105Z</updated>
	<author>
		<name>Constant Contact</name>
	</author>
	<content type="application/vnd.ctct+xml">
		<Campaign xmlns="http://ws.constantcontact.com/ns/1.0/" id="http://api.constantcontact.com/ws/customers/USER/campaigns/0">
			<Name>Powder Alert: 02-21-2013</Name>
			<Status>draft</Status>
			<Date>2009-10-19T18:34:53.105Z</Date>
			<Subject>Test Company POWDER ALERT: 0 New Inches</Subject>
			<FromName>Test Name</FromName>
			<ViewAsWebpage>NO</ViewAsWebpage>
			<ViewAsWebpageLinkText>
			</ViewAsWebpageLinkText>
			<ViewAsWebpageText>
			</ViewAsWebpageText>
			<PermissionReminder>NO</PermissionReminder>
			<PermissionReminderText>
			</PermissionReminderText>
			<GreetingSalutation>
			</GreetingSalutation>
			<GreetingName>FirstName</GreetingName>
			<GreetingString>
			</GreetingString>
			<OrganizationName>Test Company</OrganizationName>
			<OrganizationAddress1>P.O. Box 123</OrganizationAddress1>
			<OrganizationAddress2>
			</OrganizationAddress2>
			<OrganizationAddress3>
			</OrganizationAddress3>
			<OrganizationCity>Spokane</OrganizationCity>
			<OrganizationState>[US] Washington</OrganizationState>
			<OrganizationInternationalState>
			</OrganizationInternationalState>
			<OrganizationCountry>United States</OrganizationCountry>
			<OrganizationPostalCode>99201</OrganizationPostalCode>
			<IncludeForwardEmail>YES</IncludeForwardEmail>
			<ForwardEmailLinkText>Forward to a friend</ForwardEmailLinkText>
			<IncludeSubscribeLink>YES</IncludeSubscribeLink>
			<SubscribeLinkText>Subscribe for powder alerts and conditions updates</SubscribeLinkText>
			<EmailContentFormat>HTML</EmailContentFormat>
			<EmailContent>&lt;html&gt;This is a test&lt;/html&gt;</EmailContent>
			<EmailTextContent>This is a test</EmailTextContent>
			<StyleSheet>
			</StyleSheet>
			<ContactLists>
				<ContactList id="http://api.constantcontact.com/ws/customers/USER/lists/84">
					<link xmlns="http://www.w3.org/2005/Atom" href="/ws/customers/USER/lists/84" rel="self"/>
				</ContactList>
			</ContactLists>
			<FromEmail>
				<Email id="http://api.constantcontact.com/ws/customers/USER/settings/emailaddresses/9">
					<link xmlns="http://www.w3.org/2005/Atom" href="/ws/customers/USER/settings/emailaddresses/9" rel="self"/>
				</Email>
				<EmailAddress>test@test.com</EmailAddress>
			</FromEmail>
			<ReplyToEmail>
				<Email id="http://api.constantcontact.com/ws/customers/USER/settings/emailaddresses/9">
					<link xmlns="http://www.w3.org/2005/Atom" href="/ws/customers/USER/settings/emailaddresses/9" rel="self"/>
				</Email>
				<EmailAddress>test@test.com</EmailAddress>
			</ReplyToEmail>
		</Campaign>
	</content>
	<source>
		<id>http://api.constantcontact.com/ws/customers/USER/campaigns/0</id>
		<title type="text">Campaigns for customer</title>
		<link href="campaigns"/>
		<link href="campaigns" rel="self"/>
		<author>
			<name>customer</name>
		</author>
		<updated>2013-02-21T09:43:03+01:00</updated>
	</source>
</entry>

 I've validated the XML structure and looked at the example from the wiki to make sure that all of the required fields are there, but still get the 400 response from the CTCTRequest's cURL call.  Any assistance would be greatly appreciated.

 

Tags (5)
1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Employee

Re: The PHP side of the equation

HI Brett,

 

In trying to set this up on my end I have found it to be convoluted.  I am getting a 403 error when I try to run this:

 

.
.
.
$AddCampaign = $ConstantContact->addCampaign($myCampaign, $VerifiedEmailAddresses['addresses'][0]); //$ID = "1112583316584"; //Get campaign details $CampaignDetails = $ConstantContact->getCampaignDetails($myCampaign); $campaignID = $CampaignDetails->id; //Schedule campaign $CampaignResult = $ConstantContact->getCampaignByID($campaignID); $schedule = $ConstantContact->scheduleCampaign($CampaignResult, "2013-11-13T20:03:35.000Z");

 

When I run this, hard coding the campaign ID, everything runs fine.

 

.
.
.
$AddCampaign = $ConstantContact->addCampaign($myCampaign, $VerifiedEmailAddresses['addresses'][0]);

$ID = "1112583316584";

//Schedule campaign
$CampaignResult = $ConstantContact->getCampaignByID($ID);
$schedule = $ConstantContact->scheduleCampaign($CampaignResult, "2013-11-13T20:03:35.000Z");

 

Quite honestly, I'm not sure if this can be done in an automated fashion without grabbing the server response, exploding the id node to get the newly created campaign ID, and then running the last two lines of code above.  I wanted to give you some answer before the day was up, but let me know if you find a more elegant way to do this.

 

Best Regards,

Shannon W.

API Support Specialist

View solution in original post

13 REPLIES 13
Highlighted
Employee

Re: XML appears valid, but still getting Error 400

Hi,

 

Could I have the PHP code you're using with our wrapper to generate this XML?  Are the from and replyto email addresses being set to the 9th verified email address in your account?  I do notice that the state and country values you're using might be an issue.  Try using "US" for the country and "WA" for the state.

 

Best Regards,

Shannon W.

API Support Specialist

Highlighted
Occasional Participant

The PHP side of the equation

 

   Thank you very much for taking a look into my post here.  I have removed all of the company-specific information on there, but should still illustrate what I'm going for:

 

<?php

	//SET DEFAULTS AND GET PHP WRAPPER FOR CONSTANT CONTACT
	date_default_timezone_set ('America/Los_Angeles');
	require_once 'includes/ct2/ConstantContact.php';
	require_once 'includes/ct2/config.php';

	//IF WE ALREADY HAVE A VALIDATED USER SESSION, PROCEED TO SEND EMAIL
	if (@$DatastoreUser) {

		//POWDER ALERT EMAIL SETTINGS
		$subject	= "Lookout Pass POWDER ALERT: " . $_SESSION['lookout_powder_depth'] . " New Inches";
		$from_name	= "Test Name";
		$from		= "testfrom@test.com";
		$reply		= "testreply@test.com";
		$cmp_name	= "Powder Alert: " . date("m-d-Y");
		
		//CREATE A NEW CONSTANT CONTACT OBJECT
		$ConstantContact = new ConstantContact ( "oauth2", $apikey, $username, $accessToken );

		//gets verified account email addresses which can be used as from and rely-to addresses
		$VerifiedEmailAddresses = $ConstantContact->getVerifiedAddresses();

		// Try building new campaign
		try {

			// Build Campaign Object
			$myCampaign = new Campaign ();
			
			$myCampaign->name			= $cmp_name;
			$myCampaign->subject		= $subject;
			$myCampaign->fromName		= $from_name;

			foreach( $VerifiedEmailAddresses['addresses'] as $VEmail ){
				if( $VEmail->email == $from ){
					$myCampaign->fromAddress = $VEmail;
				}
			}

			$fromAddress				= $from;
			$myCampaign->replyAddress	= $reply;
			$replyAddress				= $reply;

			$myCampaign->id						= "http://api.constantcontact.com/ws/customers/USER/campaigns/0";
			$myCampaign->permissionReminder		= "NO";
			$myCampaign->permissionReminderText	= "";
			$myCampaign->greetingName			= "FirstName";
			$myCampaign->greetingSalutation		= "";
			$myCampaign->greetingString			= "";
			$myCampaign->orgName				= "Test Company";
			$myCampaign->orgAddr1				= "P.O. Box 123";
			$myCampaign->orgAddr2				= "";
			$myCampaign->orgAddr3				= "";
			$myCampaign->orgCity				= "Spokane";
			$myCampaign->orgState				= "[US] Washington";
			$myCampaign->orgInternationalState	= "";
			$myCampaign->orgPostalCode			= "99201";
			$myCampaign->orgCountry				= "United States";
			
			// Include the forward to a friend option
			$myCampaign->incForwardEmail		= "YES";
			$myCampaign->forwardEmailLinkText	= "Forward to a friend";
			
			// Include the subscribe link
			$myCampaign->incSubscribeLink	= "YES";
			$myCampaign->subscribeLinkText	= "Subscribe for powder alerts and conditions updates";

			$myCampaign->emailContentFormat	= "HTML";
			$myCampaign->styleSheet			= "";
			
			$html = "<html>This is a test</html>";

			$text = "This is a test";

			// Create the HTML and TEXT versions of the email from the email templates
			$myCampaign->emailContent		= htmlspecialchars( $html );
			$myCampaign->textVersionContent = $text;
			
			// Add ConditionsReporting Test list as the only list for sending email out to
			$myCampaign->lists = array('http://api.constantcontact.com/ws/customers/USER/lists/84');
			
			// Adds your new campaign to your Constant Contact Account
			$CampaignResult = $ConstantContact->addCampaign ( $myCampaign, $myCampaign->fromAddress );
			// $CampaignResult will now hold the referenced campaign object
			
			// Immediately send the campaign to the included list(s)
			$response = $ConstantContact->scheduleCampaign($CampaignResult, date(DATE_ATOM));

			// Release the Lookout powder depth session variable after it has been used
			unset($_SESSION['lookout_powder_depth']);

		// Catch all errors
		} catch ( Exception $e ) {
			echo $e . " needs to be corrected before submission";
			die;
		}
	} else {
		
		//IF WE DO NOT HAVE A VALID USER SESSION IN PLACE, REQUIRE A VALIDATION THROUGH CONSTANT CONTACT
		//you must encode your redirect URL and the link contains the variables from config.php
		$theRequest = urlencode ( $verificationURL );
		echo "<a href='https://oauth2.constantcontact.com/oauth2/oauth/USER/authorize?response_type=code&client_id=" 
			. $apikey . "&redirect_uri=" 
			. $theRequest
			. "'>Click here to Authenticate</a>";
	}
?>

 

Highlighted
Employee

Re: The PHP side of the equation

Hi,

 

I believe the issue was in how some objects were being created, like the verified address and lists.  I got this code working in my environment.

 

<?php
session_start ();
require_once 'ConstantContact.php';
require_once 'config.php';

$ConstantContact = new ConstantContact ( "oauth2", $apikey, $username, $accessToken );

// Get all lists
$lists = $ConstantContact->getLists();

// Get verified email addresses 
$VerifiedEmailAddresses = $ConstantContact->getVerifiedAddresses();

// Istantiate $myCampaign to the Campaign 
$myCampaign = new Campaign();

$cmp_name	= "Powder Alert: " . date("m-d-Y") ;
$myCampaign->name = $cmp_name;

// Set the lists that this email will go to
$myCampaign->lists = array($lists['lists'][0]->id, $lists['lists'][1]->id);

$myCampaign->subject = "This is the subject";
$myCampaign->emailContentFormat = "HTML";
$myCampaign->permissionReminder		= "NO";
$myCampaign->permissionReminderText	= "";
$myCampaign->greetingName			= "FirstName";
$myCampaign->greetingSalutation		= "";
$myCampaign->greetingString			= "";
$myCampaign->orgName				= "Test Company";
$myCampaign->orgAddr1				= "P.O. Box 123";
$myCampaign->orgAddr2				= "";
$myCampaign->orgAddr3				= "";
$myCampaign->orgCity				= "Spokane";
$myCampaign->orgState				= "WA";
$myCampaign->orgInternationalState	= "";
$myCampaign->orgPostalCode			= "99201";
$myCampaign->orgCountry				= "US";
	
// Include the forward to a friend option
$myCampaign->incForwardEmail		= "YES";
$myCampaign->forwardEmailLinkText	= "Forward to a friend";
	
// Include the subscribe link
$myCampaign->incSubscribeLink	= "YES";
$myCampaign->subscribeLinkText	= "Subscribe for powder alerts and conditions updates";

$myCampaign->styleSheet			= "";

// HTML must be entered with out entities encoded.  The wrapper will dot his for you
$myCampaign->emailContent = "<HTML><BODY>This is your test email</BODY></HTML>";
$myCampaign->textVersionContent = "Test";

$AddCampaign = $ConstantContact->addCampaign($myCampaign, $VerifiedEmailAddresses['addresses'][0]);

?>

 

 

Best Regards,

Shannon W.

API Support Specialist

Highlighted
Occasional Participant

Re: The PHP side of the equation

 

Shannon,

 

   Thanks for continuing to assist with this issue.  I have managed to apply the modifications that you made to the example code that I had pulled this from previously and it does appear to be creating a valid campaign object that is getting saved to the proper CTCT account for scheduling.  This account does not appear to have the ability to use the PHP scheduling function.  I suspect that I will have to contact an administrator and ask for that functionality to be allowed?

 

   I would also like to ask you, while I have your attention on the topic, about the - seemingly - excessive number of variations to the Constant Contact PHP wrapper code and examples that are linked to from various parts of the community forum here.  I've found four different versions posted from within the forums at the following locations and all four appear to have slightly different base functionality and different approaches to the example code that is included with them.  Three of the four have example code that does not work at all as written (the last is the only one that worked): 

 

   If you could provide the *definitive* PHP Wrapper URL and/or links to recent code samples that are known to be current and correct it would help me (and other relative newcomers to CTCT) keep from needlessly hacking on code that doesn't work in the first place.

 

   Thanks very much, again, for your continued assistance.

Highlighted
Employee

Re: The PHP side of the equation

Hi Brett,

 

Yes, you will want to email us at webservices@constantcontact.com with your Constant Contact username and the API Key that you wish to have scheduling priveleges.

 

As for the links, your assessment is fair, and it's hard to police all of the documentation that's still out there and searchable.  The first two links are deprecated/unsupported.  I'm not sure if sourceforge allows us to remove something once it's up, but I will check.  We use github, and anything on Sourceforge is deprecated  The second link is someone who forked our current wrapper.

 

The third link is officially supported and I encourange all new users to use it.  The fourth is my OAuth2 example, which I created because we had many users stumped by how to implement OAuth2.  I continue to support it, though we do hope to have an even better process in the future which will prevent most users from needing to implement the OAuth2 process themselves.  That fourth link will likely be the example we continue to point to for users needing to implement OAuth2.

 

I'll look into the create campaign example in the third (supported) link to make sure it doesn't have any glaring issues. It might, in fact, be best for me to replace it with a simpler script.

 

Generally, I'd advise new users to go to our "Code samples" page first, and come to us on the forums (here) or at webservices@constantcontact.com if you need a basic example and can't find it or find an issue with one of the examples.

 

Best Regards,

Shannon W.

API Support Specialist

Highlighted
Occasional Participant

Re: The PHP side of the equation

 

   OK... we are really getting close here.  I can feel it.

 

   I have been able to create new campaigns that seem to appear correctly when logging into the CTCT administration system.

 

   The API key associated with this account is supposed to have been given permisison to access scheduling functionality, but I have added the following PHP call to my function that is being met with a "HTTP Status 403 - Not Allowed to access customer" error message.

 

	$response = $ConstantContact->scheduleCampaign($CampaignResult, date(DATE_ATOM));

 

   Is this not the proper format for scheduling a newly created campaign?

 

   Thanks again.

Highlighted
Employee

Re: The PHP side of the equation

Hi Brett,

 

Unfortunately it's a little more complicated than that.  The wrapper expects a campaign object to be scheduled, so it would be a matter of retrieving the campaign ID from the response, creating a campaign object, doing a getCampaignByID, then using that campaign object to use the scheduleCampaign method.  Perhaps I'm overcomplicating, but I don't think you can use the response itself to create a campaign object properly.  Sorry I don't have any examples to give on that at the moment.

 

Best Regards,

Shannon W.

API Support Specialist

Highlighted
Occasional Participant

Re: The PHP side of the equation

 

   Thanks for the replay, as always.  I do not see any reference to a "getCampaignByID" function anywhere within the PHP wrapper code.  Is see a getCampaignDetails, a getCampaigns and a getCampaignsByStatus.  Do I need to verify that I'm using the same PHP wrapper code that you are or do I need to use one of the campaign collection methods and just loop through all of the returned references until I find the one that I'm looking to send?

 

   Thanks again.

 

-b-

Highlighted
Employee

Re: The PHP side of the equation

Hi Brett,

 

edit: the getCampaignbyID method is in the ConstantContact.php file in the file located here (line 269):

 

The main PHP wrapper I use is here.  Sorry if you found another one and were using that, but they should all have the getCampaignByID method.

 

Best Regards,

Shannon W.

API Support Specialist

Developer Portal

View API documentation, code samples, get your API key.

Visit Page

Register for our "Making Sense of Online Marketing for Retail" Webinar

Join us on Thursday, August 13th at 2pm ET for a free webinar where we'll discuss how to incorporate online marketing into your retail store.

Read More
Featured