Monday, March 31, 2008

Apple iCal Backup Applescript

I was browsing through TUAW the other day and came across this nice little applescript for backing up an iCal calendar. Little scripts like this sure seem to come in handy if you're ever having to wipe your system clean (in fact I'd like to make one for Mail since it seems to be such a pain to back up that info and get it all to save).

I haven't had a chance to really delve into it, but it seems like you should be able to do this without all the keystrokes and clicks, but I could wrong. Also, be sure to read their disclaimer. The script is a little limited in exactly what it can do.

TUAW Applescript: backup iCal calendars

Monday, March 17, 2008

WHITEvoid - 3D Perspective in Flash

I woke up today not even thinking that my mind would be blown today.

But I came across interactive agency WHITEvoid's portfolio application and I'm still nerding out about it.

Very simple. Very clean. Very impressive.

Take a look at WHITEvoid's portfolio application.

Tuesday, February 26, 2008

CakePHP Authorize.net Component

My last post I threw a lot of love at CakePHP. After a few more weeks though....I still love it. It has made development so much easier, quicker, and better organized. I've been able to reuse code more easily, and have been trying to stick to the whole DRY concept (Don't Repeat Yourself). CakePHP is making it easier and easier.


Anyway, we're just wrapping up a new ecommerce site that needed to interface with the Authorize.net gateway to process credit cards. We've done this on a bunch of other sites, but it's also been somewhat difficult to work with and hasn't been easy to debug either. For this project I created a new CakePHP component to interface with Authorize.net's AIM integration system.

Figured if any other CakePHP developers out there want a (hopefully) easier way to process cards through Authorize.net you can feel free to use this component.



class AuthorizeNetComponent extends Object {

### Created By Graydon Stoner - www.getstonered.com ###
###


//////////// Controller Usage \\\\\\\\\\\\\
/*
$components = array('AuthorizeNet');

$billinginfo = array("fname" => "First",
"lname" => "Last",
"address" => "123 Fake St. Suite 0",
"city" => "City",
"state" => "ST",
"zip" => "90210",
"country" => "USA");

$shippinginfo = array("fname" => "First",
"lname" => "Last",
"address" => "123 Fake St. Suite 0",
"city" => "City",
"state" => "ST",
"zip" => "90210",
"country" => "USA");

$response = $this->AuthorizeNet->chargeCard('########', '##############', '4111111111111111', '01', '2010', '123', true, 110, 5, 5, "Purchase of Goods", $billinginfo, "email@email.com", "555-555-5555", $shippinginfo);
$response:Array = $this->AuthorizeNet->chargeCard($loginid:String, $trankey:String, $ccnum:String, $ccexpmonth:String, $ccexpyear:String, $ccver:String, $live:Boolean, $amount:Number, $tax:Number, $shipping:Number, $desc:String, $billinginfo:Array, $email:String, $phone:String, $shippinginfo:Array);

////////// USAGE NOTES \\\\\\\\\\\\

PARAMETERS
$loginid : Your Authorize.net Login ID
$trankey : Your Authorize.net Transaction Key
$ccnum : The system removes any spaces in the string to meet Authorize.net requirements
$ccexpmonth : 2 digit month string
$ccexpyear : 2 or 4 digit year string
$ccver : The 3 or 4 digit card verificaton code found on the back of Visa/Mastercard and the front of AmEx
$live : Whether to process as a live or test transaction - true : Live Transcation - false : Test Transaction
$amount : Total amount of the transaction. This must include both tax and shipping if applicable.
$tax : Tax amount charged (if any)
$shipping : Shipping cost (if any)
$desc : Description of the transaction to be logged into Authorize.net system
$billinginfo : Associative Array containing values for customer billing details
$email : Customer email
$phone : Customer phone
$billinginfo : Associative Array containing values for customer shipping details

RESPONSE
$response : Array (1 based) containing the Payment Gateway Resonse fields

// Important Response Values
$response[1] = Response Code (1 = Approved, 2 = Declined, 3 = Error, 4 = Held for Review)
$response[2] = Response Subcode (Code used for Internal Transaction Details)
$response[3] = Response Reason Code (Code detailing response code)
$response[4] = Response Reason Text (Text detailing response code and response reason code)
$response[5] = Authorization Code (Authorization or approval code - 6 characters)
$response[6] = AVS Response (Address Verification Service response code - A, B, E, G, N, P, R, S, U, W, X, Y, Z)
(A, P, W, X, Y, Z are default AVS confirmation settings - Use your Authorize.net Merchant Interface to change these settings)
(B, E, G, N, R, S, U are default AVS rejection settings - Use your Authorize.net Merchant Interface to change these settings)
$response[7] = Transaction ID (Gateway assigned id number for the transaction)
$response[38] = MD5 Hash (Gateway generated MD5 has used to authenticate transaction response)
$response[39] = Card Code Response (CCV Card Code Verification response code - M = Match, N = No Match, P = No Processed, S = Should have been present, U = Issuer unable to process request)

For more information about the Authorize.net AIM response consult their
AIM Implementation Guide at http://developer.authorize.net/guides/AIM/ and
go to Section Four : Fields in the Payment Gateway Response for more details.

NOTES
This component is meant to abstract payment processing on a website.
As varying sites require different requirements for information, security,
or card processing (like changing Address Verification requirement) the
component does not try to provide any logic to determine if a transaction
was successful. It is up to the user implementing this code to process the
response array and provide response accordingly.

*/

// class variables go here

function startup(&$controller) {
// This method takes a reference to the controller which is loading it.
// Perform controller initialization here.
}

function chargeCard($loginid, $trankey, $ccnum, $ccexpmonth, $ccexpyear, $ccver, $live, $amount, $tax, $shipping, $desc, $billinginfo, $email, $phone, $shippinginfo) {

// setup variables
$ccexp = $ccexpmonth . '/' . $ccexpyear;

$DEBUGGING = 1; # Display additional information to track down problems
$TESTING = 1; # Set the testing flag so that transactions are not live
$ERROR_RETRIES = 2; # Number of transactions to post if soft errors occur

$auth_net_login_id = $loginid;
$auth_net_tran_key = $trankey;
### $auth_net_url = "https://certification.authorize.net/gateway/transact.dll";
# Uncomment the line ABOVE for test accounts or BELOW for live merchant accounts
$auth_net_url = "https://secure.authorize.net/gateway/transact.dll";

$authnet_values = array
(
"x_login" => $auth_net_login_id,
"x_version" => "3.1",
"x_delim_char" => "|",
"x_delim_data" => "TRUE",
"x_url" => "FALSE",
"x_type" => "AUTH_CAPTURE",
"x_method" => "CC",
"x_tran_key" => $auth_net_tran_key,
"x_relay_response" => "FALSE",
"x_card_num" => str_replace(" ", "", $ccnum),
"x_card_code" => $ccver,
"x_exp_date" => $ccexp,
"x_description" => $desc,
"x_amount" => $amount,
"x_tax" => $tax,
"x_freight" => $shipping,
"x_first_name" => $billinginfo["fname"],
"x_last_name" => $billinginfo["lname"],
"x_address" => $billinginfo["address"],
"x_city" => $billinginfo["city"],
"x_state" => $billinginfo["state"],
"x_zip" => $billinginfo["zip"],
"x_country" => $billinginfo["country"],
"x_email" => $email,
"x_phone" => $phone,
"x_ship_to_first_name" => $shippinginfo["fname"],
"x_ship_to_last_name" => $shippinginfo["lname"],
"x_ship_to_address" => $shippinginfo["address"],
"x_ship_to_city" => $shippinginfo["city"],
"x_ship_to_state" => $shippinginfo["state"],
"x_ship_to_zip" => $shippinginfo["zip"],
"x_ship_to_country" => $shippinginfo["country"],
);

$fields = "";
foreach ( $authnet_values as $key => $value ) $fields .= "$key=" . urlencode( $value ) . "&";

///////////////////////////////////////////////////////////

// Post the transaction (see the code for specific information)

### $ch = curl_init("https://certification.authorize.net/gateway/transact.dll");
### Uncomment the line ABOVE for test accounts or BELOW for live merchant accounts
$ch = curl_init("https://secure.authorize.net/gateway/transact.dll");
### curl_setopt($ch, CURLOPT_URL, "https://secure.authorize.net/gateway/transact.dll");
curl_setopt($ch, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1)
curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim( $fields, "& " )); // use HTTP POST to send form data

### Go Daddy Specific CURL Options
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, true);
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($ch, CURLOPT_PROXY, 'http://proxy.shr.secureserver.net:3128');
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
### End Go Daddy Specific CURL Options

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // uncomment this line if you get no gateway response. ###
$resp = curl_exec($ch); //execute post and get results
curl_close ($ch);

// Parse through response string

$text = $resp;
$h = substr_count($text, "|");
$h++;
$responsearray = array();

for($j=1; $j <= $h; $j++) {
$p = strpos($text, "|");
if ($p === false) { // note: three equal signs
// x_delim_char is obviously not found in the last go-around
// This is final response string
$responsearray[$j] = $text;
}
else {
$p++;
// get one portion of the response at a time
$pstr = substr($text, 0, $p);
// this prepares the text and returns one value of the submitted
// and processed name/value pairs at a time
// for AIM-specific interpretations of the responses
// please consult the AIM Guide and look up
// the section called Gateway Response API
$pstr_trimmed = substr($pstr, 0, -1); // removes "|" at the end
if($pstr_trimmed==""){
$pstr_trimmed="";
}
$responsearray[$j] = $pstr_trimmed;
// remove the part that we identified and work with the rest of the string
$text = substr($text, $p);
} // end if $p === false
} // end parsing for loop
return $responsearray;
} // end chargeCard function
} ?>

Drop me a line in the comments with any projects you're using this component in.

Tuesday, February 5, 2008

I Love CakePHP

I'd heard a lot about CakePHP and how much it can help speed up development. But for some reason I kept resisting trying it out. Call me old school, but I still would rather code with a normal text editor than the majority of software out there.


Not being really well versed with the whole Model/View/Controller concept, I took a bit of time trying to get the hang of how everything is put together.

But once I got that under my belt, programming has been a breeze. Two days to create a good content management system is a new record for me. In fact, the entire APX Insider was developed using CakePHP.

Soon I'll post some components I made for uploading and resizing images since I didn't really feel like anything I could find out there was all that simple to implement.

Thursday, January 31, 2008

New APX Alarm Site - I Am APX and APX Insider

We're proud to announce the launch of two new websites for security sales company APX Alarm.


I Am APX is a full flash website targeted at recruiting new salesmen (and saleswomen) to work for APX. The site features interactive streaming flash video in multiple areas, and was designed to appear to APX's target demographic, 18-25 year old men and women. The site also includes interviews with APX employees who explain what working for APX is like and what new recruits can expect while they are out pounding the pavement.

APX Insider is a news portal specifically for APX employees, in particular their sales force. The site was modeled around news portals such as ESPN.com and features an interface where editors and contributors can add news articles with images, and the system also pulls sales stats to show top salesman, regions, and offices, helping foster synergistic competition between employees. Unfortunately, it's password protected, so unless you work for APX, you're out of luck.

Sunday, January 27, 2008

President Gordon B Hinckley Dies at Age 97


I was watching TV and heard a special report that shocked and numbed me.

President Gordon B. Hinckley, President and Prophet of the Church of Jesus Christ of Latter-day Saints (Mormon) died a little more than an hour ago.

Few people, with the exception of maybe my parents, have had such a profound impact on my life and who I am as this great man. I've grown up listening to his counsel and discourses and look at him like my own father or grandpa.

If you'd like to read some of his addresses check out the following links.


Wednesday, January 9, 2008

Carpe Testes (Softly)

We might not have a great reputation yet, but there is some great interactive coming out of Salt Lake City.

Struck (most well known for its work in the Shave Everywhere site) has put together a nice viral website for the Sean Kimerling Testicular Cancer Foundation. The site is a great example that a well done site doesn't have to be over the top to be effective (but you do need some great video to make up for it).

Check out Carpe Testes

Wednesday, December 12, 2007

You Wouldn't Understand

I absolutely hate this slogan that Palm is using. It has to be one of the worst ever. Seriously.




It's a Palm thing? That's the best they could come up with?

Monday, December 10, 2007

Nike's Interactive Getting Lazy

I was checking out some of Nike's sites over at their jumpman23 site and noticed some interesting things about the Carmelo Anthony site for his new shoe, the M4.

1. As is the case with almost all Nike sites, they do an amazing job with their graphic design. In this case, the great imagery works really well with all the hand-drawn illustrations.
2. Nice, subtle beat doesn't wear out its welcome too fast like you see on so many other sites.
3. I could have sworn I had seen this exact layout and navigation on another Nike site. After doing a little digging I found an older Jumpman 23 site for the XX2 shoe.

Check out both sites and let me know if you think Nike is lazy, or if this is just a good use of repurposing a website with a new look and feel.

My vote = lazy.

P.S. I'm not sure if Wieden + Kennedy spearheaded this site or if Nike went through R/GA. Anyone know?

Wednesday, November 21, 2007

Apple's Give Up on Windows Vista Ads

As a Mac user the majority of the time you can take this post for what it's worth (although up until about 2 years ago I used Windows exclusively).

I love seeing clever advertising anywhere. The blogosphere is inundated with examples of creative advertising in the real world, but on the web advertising is usually relegated to poorly designed static or flash banner advertisements. Most are bad. Some are horrible. So when you see something clever you can't help but want to share it.

Visit c|net.com's Windows Vista page and you'll see one of the more clever uses of banner ads I think I've seen. A horizontal and skyscraper ad work in conjunction to poke fun at Vista using Apple's Mac/PC adds that have been all over TV the past few months.



I'd love to find out what Apple had to do to get c|net to agree to this. Even if you love Vista, I think you'd have to agree this is one of the best uses of banners anywhere on the interweb.