Corey, I have a start-up in Austin seeking experienced advisors and wanted to present our concept.
Send an email, under 500 words, to [email protected].
Claire Keane

oozey mess

⁂
let's talk about Bridgerton tea, my ask is open
hello vonnie
Cosimo Galluzzi
Xuebing Du
occasionally subtle
Cosmic Funnies

Kaledo Art

Discoholic 🪩
cherry valley forever
tumblr dot com
$LAYYYTER

#extradirty
Lint Roller? I Barely Know Her
Mike Driver

roma★

titsay
Not today Justin

seen from United States

seen from United States
seen from United States
seen from Pakistan
seen from Brazil

seen from Malta

seen from United States

seen from United States

seen from United States
seen from Ukraine
seen from United Kingdom

seen from Malaysia
seen from United States

seen from Malaysia

seen from Netherlands
seen from United States
seen from United States
seen from United States

seen from United States

seen from Oman
@artofidea-blog
Corey, I have a start-up in Austin seeking experienced advisors and wanted to present our concept.
Send an email, under 500 words, to [email protected].
images are not working on post : creating-an-amazon-payments-seller-account
Yeah, this is a problem with Tumblr. I've moved the blog to http://artofidea.com and am in the process of getting a new image host.
Great article on going from contract to FT. You gave really sensible advice!
Glad you liked it! Please note that this blog has moving to http://www.artofidea.com (this article is there).
how do i file my taxes as a w-2 contractor
You'd file the same way as you would for a regular job. Technically, as a W2, you're not really a contractor. You're legally a temporary employee of the contracting firm who sends your paychecks.
Introducing ArtOfIdea.com
Good news everybody! This blog is going away. Wait, that's not very good news at all. Actually, the blog is just moving. I've always intended the coreybutler.com domain name for another purpose, and in 2013 that project will finally take shape. This blog is finally being given a name and a new identity at [The Art of Idea](http://artofidea.com). The articles here are being transitioned to the new site, and you will see lots of changes on artofidea.com as I work to implement something more than the stock theme that comes with the new blogging engine. The new site has a new RSS feed, as well as the ability to subscribe via email. I also have a lot of new material to release in 2013. Until the migration is complete & this domain is ready for it's new purpose, this site will remain. However; there will not be any further updates to it... everything is already working on the other site. I look forward to seeing you all on the new site!
Call For Developers: Ext JS & Sencha Touch
Are you an Ext JS or Sencha Touch developer looking for a gig? Perhaps you're a Flash or Flex developer looking for a switch? Or maybe you're just darn good with JavaScript? If any of this fits you, please get in touch with me! Brian Moeskau & I have formed ThinkFirst, LLC. The company itself is young (kinda), but certainly not new to Sencha frameworks. Brian co-founded Ext JS back in 2007. I've been helping clients build applications since founding a consulting firm in 2002. But we have a problem... there is so much demand we can't fill all the contract opportunities coming in! Come work with us! We have full time and part time opportunities.
Private npm Registry Hosting?
Does anyone know of a private npm registry hosting service? I'm thinking about starting one. **Background/Challenge** Like most people developing Node apps, I use npm regularly. Simply put, it is awesome. More recently, I have been building a lot of my own modules. In most cases, they need to remain private. However; I still need to distribute them to specifc developers... sometimes in different organizations. I've been looking for a simple way to do this, so I recently setup my own private npm registry. It works pretty well, but the workflow & management of it all feels a bit muddy. I have a few ideas on how this could be cleaner, some features I think would be awesome, and I see opportunity. But, just because I do doesn't mean anyone else does. This makes for several questions... **Questions** Assuming there aren't any services providing this (I haven't found any yet), I thought it might be worth creating something. So, my questions are: 1. Is this something you, as a Node developer, would be interested in? 2. If so, what type of features would you want? 3. Are you currently maintaining you own private npm registry? Pain points? 4. How much time do you spend organizing, refactoring, and distributing your node code? Any feedback would be appreciated. I'm really just exploring the idea at the moment, so I have no specific expectations. I don't even know if this is a good idea... I thought some discussion/feedback would help determine that. Thanks to anyone who participates!
What I'm Up To Now
It has been pretty quiet on this blog for a while - more than I was anticipating. I've been pretty involved in my projects and have a lot of (positive) things going on in my personal life. So, I figured I'd take a moment to address some happenings. **Startups** First, I have been really busy. I am working on three startup efforts in addition to some consulting projects. All of them have kept me deep in the trenches of development - both tech and business development. All of them have had their own challenges, and I have learned a lot more than I thought I would. That part has been awesome. **Exploring Web Technology** Some of you know I came from a ColdFusion background. I still do a little bit of it, but I spend far less time developing with it than ever before. It's not a lack of interest. I just know the language very well. When I see a place for it in a project, I can crank through the code very quickly and move on to more time consuming efforts. I'm spending most of my time in the JavaScript world now. Over the last two years, I dug into NodeJS pretty deeply. I'd already been using Sencha for quite a while, and I've had the chance to explore JQuery, Backbone, and many other interesting frameworks. I view the world of JavaScript as the frontier. There is a lot going on and the shape of it is still evolving. Working with it is time consuming, but rewarding. Questions are answered every day, sometimes with a number of different answers. There are still a lot of unanswered questions though. That's what excites me... I am enjoying finding and sometimes creating answers. **Data Management, DW/BI, & Consulting** Others may know me as a data warehousing and business intelligence consultant. Cognos you say? I certainly have done a lot of that... a whole lot. However; my trek into the JavaScript world has brought new friends, like Redis, MongoDB, CouchDB, and other NoSQL systems. I've really enjoyed working with these, and I've even had the opportunity to leverage some of these tools with the more traditional RDBMS platforms that many DW/BI environments are built on. Since these things are still mostly used in newer web applications, less of my consulting hours have been spent in DW/BI and more on web and platform architecture. **Training?** Over the weeks I'll be making new announcements (probably some shameless plugs), and possibly putting up some new tutorials around the JavaScript stack & NoSQL. I've been contemplating the idea of releasing an affordable video training series on how the new technologies fit in with more traditional ones, and I've even thought about writing a book on the subject. But as any entrepreneur knows, you have to figure out whether there is an audience for it. So, would anyone find value in that? **Final Thoughts** I may be splitting this blog into two separate ones focused on technology and business development respectively. That probably won't make a difference to anyone, but I think it's prudent to keep each blog focused.
NodeJS & Microsoft Azure
I've been working with NodeJS for just under 2 years now, primarily from my Windows-based desktop. NodeJS was restricted to *nix platforms, which gave me a lot of appreciation for the Macbook Pro I was loaned. Seeing as my desktop is a workhorse that's more powerful than the combined computing power of most of my data center, I installed some virtual servers to use Node on Linux. This works quite well, but has some annoyances. For example, I develop with Eclipse and Aptana, and I ended up writing ANT build scripts to automatically upload my changes to my virtual server.
Yesterday, an interesting effort from Microsoft was released, providing some cool functionality for Windows users. Take a look at the video below.
If you're unfamiliar, Microsoft started contributing resources to a native NodeJS port a while ago. The workflow wasn't very smooth though. Installing Node modules meant manually cloning them from Github. It just felt dirty in comparison to the Linux alternatives. It appeared as though Microsoft was (and is still) targeting IIS integration, i.e. more as a plugin to IIS than a replacement.
Now I haven't used Node with Azure yet, but a few key points really stood out. The biggest was the fact that npm appears to work as it does in Linux. That is a big win for my workflow.
I also really liked the fact there is a NodeJS Azure Emulator for Windows. I've been training a lot of people in the ways of Node lately, all of whom are Windows users. Walking people through a virtual server installation was consuming a lot of time. Now, it appears as though a single link can get these folks up and running quickly.
My first question was whether or not I could use the emulator to develop my applications locally, but still deploy to my existing Linux servers. I'm sure Microsoft wouldn't be terribly thrilled with this, but they've at least taken away my reason for completely switching to a Mac.
Since I've been wrapped up in the wonderful world of Node, Linux, and JavaScript, I really haven't had much time to consider Azure as a platform. I've been looking at Rackspace, Amazon EC2 (which I use today), and several other VPS providers though. This video made me look, and the pricing for Azure is actually pretty comparable (in some cases cheaper) than what I've seen with these other services.
Of course, I have some testing to do. We'll see how well this holds up with the ever-changing world of NodeJS and the multitude of packages that sprout up, but I am currently encouraged by what I've seen.
UPDATE: There's a nice little tutorial on using NodeJS on Windows 7 over at dailyjs.com.
Using Github with Adobe and Aptana
Git has become a popular source code management system, and Github has contributed to its continually gaining popularity.
Though there is a learning curve, using basic features of Git is pretty intuitive, especially with several of the freely available tools available today. However; getting your environment configured to work with Github can be a test of patience.
This guide is relevant to any Eclipse-based IDE, but for demonstration purposes, I'll be showing how to connect Adobe ColdFusion Builder 2 to Github. This guide should also work for Adobe Flash Builder, CFEclipse, or any other Eclipse-based IDE.
There are many ways to accomplish this task, but I've chosen to incorporate Aptana Studio 3 into my Adobe development environments. Aptana Studio is known as a Rails-oriented plug in for Eclipse, but I started using it for it's strong JavaScript support. It happens to have one of the more straightforward Git connectors.
Install Aptana for ColdFusion Builder
For this guide, it does not matter whether you've installed ColdFusion Builder as a standalone product or as an Eclipse plug in. Both versions run on Eclipse, meaning both have the ability to install Eclipse plug ins.
NOTE:
Your installation must be in a location with local administrative privileges, or at least healthy write privileges. In my first attempt, I tried installing ColdFusion Builder on a Windows 7 system controlled by Active Directory. While I was able to install everything with elevated privileges, I could not run it with elevated privileges. As a result, everything appeared to work, until trying to sync with Github. At this point, it simply failed to sync with permission issues. If anyone has insight on how to fix that with an unprivileged account, I'd love to hear about it.
The simplest way to install Aptana Studio is through the Eclipse update feature. In ColdFusion/Flash Builder, this is found under:
Help → Install New Software
This brings up the installation screen. You'll need to add the Aptana Studio update site to the list by clicking on the Add button. Provide a name and the location of the update site as shown below:
Name: Aptana
Location: http://download.aptana.com/studio3/plugin/install
If prompted, restart ColdFusion Builder.
**With some installations, I've had some issues using the “Apply Changes Now” option.**
Aptana may prompt you to install msysgit, which will work, but I recommend using the Setup Git page for installing Git on your computer anyway. There may be times, especially while learning, where you may wish to use Git from the command line. It is also helpful in creating the SSH keys you'll need to connect to Github. Regardless of your choice, you should be able to create local Git repositories at this point.
Quick Aside
For those new to Git, it is a source code management system. It works differently from CVS, Subversion, or SourceSafe. One important note is that you cannot directly connect to remote/hosted repositories like Github/BitBucket. All communication with these remote repositories is handled by a local repository stored on your computer. Aptana Studio and other Git tools help by auto-creating local repositories as well as communicating with remote repositories.
Connecting your project to Git
Right-click on the project you want to associate with Git and select
Team → Share Project
You'll be prompted for a repository type, which should be Aptana Git.
Next, the wizard will help create a local Git repository.
Select the Project and click the Create button. This will create your local Git repository. Then click finish. At this point, you've created your first Git repository! Now it's time to clean things up so our repository stays tidy.
Ignore Files
Git uses a file called .gitignore to prevent certain files/directories from being included in your repository. It's typically good form to not include your .gitignore file in your repository, so step one is to make it ignore itself. Ignoring files and directories is pretty straightforward. Simply right click the file name and
Add to .gitignore
It may be desirable to add wild card entries to your .gitignore file as well. For example, Eclipse users will be familiar with the .project file, and you may also see a .git directory in your project. I find it useful to ignore every file/directory in my project, as well as files that aren't relevant to my project (like .thumb). Gitignore, which is just a text file, can be edited to support wild cards. You can add the following:
.*
_*
settings.xml
This would ignore all files/directories that start with a dot or underscore, such as .project, .git, or _NOTES. It will also ignore the XML metadata settings file most Adobe products use to manage a project. As a result, these files will not end up in your remote project repository.
Using Github
Github is just one of several Git services, but it is extremely popular. It's free for open source projects and inexpensive for private projects. BitBucket is an alternative that has free open and private projects in addition to a commercial service. Setup between the two is similar, but we'll stick to Github for this tutorial.
First, you must have a personal Github account, so sign up for a free account. Next, you'll need an SSH key to connect with your repositories. You'll need an SSH key on every computer you work on. Github allows you to add multiple keys, so I have repeated the same process on my laptop, desktops, and workstations.
The simplest and most common way to create an SSH key and add it to your Github account is described in detail at http://help.github.com/win-set-up-git/. This is the recommended method.
Add a Repository
If you haven't already, create a Github repository. This is done from the Dashboard of your Github account:
I recommend starting with a free open source repository until you're comfortable with how everything works.
Connecting Your Project to Github with Aptana
At this point, you should have a Github repository created on Github.com and a local repository associated with your project. It's time to tie the two of them together.
The Aptana plug in provides a menu option for adding a remote repository, but I have had limited success with this. Therefore, I'm going to show how to manually configure a remote connection to Github.
Manual Remote Repository Configuration
In your project directory, you should see a .git directory. If you're working on a Mac, this directory may be hidden. This directory contains a file called config, which needs to be modified. When you open the file, you will see a core attribute only. We need to add a remote connection and identify the master branch, as shown below. For copy/paste purposes, I've provided a demo config below:
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "Test"]
url = [email protected]:mygithubname/myrepository.git
fetch = +refs/heads/*:refs/remotes/test/*
[branch "master"]
remote = Test
merge = refs/heads/master
Save this file and you're done.
Using Github
Push & Pull:
Assuming you followed this guide and configured everything correctly, you should be able to push and pull from your remote repository. However; you first need to commit changes to your local repository. Remember, all interaction with a remote repository is done through your local repository. If there are no changes committed to your local repository, then no changes will be pushed to your remote repository. The advantage of doing this is you can make as many changes as you like before sharing with other developers. That means you can screw up and fix as much as you like before ever publishing to the world.
Once you've added some files to your project and are ready to push them to Github, right-click on the project and go to
Team → Commit
You will need to stage any/all changes you've made and add a message, as shown below:
Click on the Commit button to save your changes in your local Git repository.
Now you can push your changes to Github. To do this, right click on the project and go to:
Team → Push To Remote
Select the remote repository that was configured in prior steps.
Once you push to the remote repository, you should see progress in the output console (if you have it open). Please note that the first time you push to a remote repository, it may be quite slow. You will also be prompted to accept the RSA fingerprint from Github (which you must do). This will add Github to your Known Hosts file if it isn't already there.
Finally, go check out your Github page. You should see your code there.
Next Steps
Now that you have a project working with Github, you should start to use the features and get familiar with it. Browse the documentation the Github website. Github has several interesting hooks and features that make it useful. A common feature is the Readme.md file. Github uses “Github Flavored Markdown” to create visually appealing documentation. If a Readme.md file is found in your project root, it will automatically be displayed on the page. This is how many developers provide introductory notes about their project for the community. Of course this can be expanded through use of the wiki or pages.
I anticipate covering Github issues and how to integrate Github issue management directly into ColdFusion/Flash/Eclipse Builder in an upcoming post.
Please let me know if you find this useful!
Feel free to find me on Github.
Sencha Meetup Reminder
Just a reminder that I'll be discussing NoSQL, SSJS (NodeJS), and how it fits into the Sencha technologies tonight at 7pm in the vAuto offices in Austin, TX. If you're in the area, come join us! This will be a highly interactive presentation and discussion. You can learn more at http://www.meetup.com/ExtJS-Austin/events/30006511/. If you want to hack as we discuss, read on!
We just wanted to let everyone know that the demos presented will be highly interactive, and there will also be opportunities for a little independent hacking for anyone so inclined, so please bring a laptop if you're interested. Even if you don't plan on doing any hacking, you'll still enjoy having your laptop or iPad with you for the demos... ;)
If you would like to participate in some hacking or run the demos yourself, read on -- otherwise, you may safely skip the rest of this email.
Most of the required setup for specific tools will be covered during the presentation, but for maximum efficiency it would be really great if you prepare beforehand by installing a few things on your own, if needed. These will take a few minutes to install, and the steps can vary depending on your specific OS / environment:
(FYI, life will be best for those on OSX or Linux -- Windows support, while it might work, is very much lacking at this time in the Node world. YMMV.)
Install Python 2.6 or higher Optional - only needed if you are going to build Node or its libraries from source.
Install NodeJS This is the base framework, required for all demos. Installation instructions
Install npm (Node package manager) This is required to install all other node libs that will be used. Installation instructions
Once you have these tools working, installing other libs via npm is a piece of cake, and we'll cover all of that in the presentation. Thanks for reading this far, and we'll see you at the meetup!
Mongoose Schema Structure
NodeJS has become a prominent part of my development stack over the last few months, as has MongoDB. The folks from Learnboost have created several great NodeJS packages, one of which is MongooseJS. Mongoose is a MongoDB wrapper that helps developers define schemas or data objects stored in MongoDB. Though the library is powerful and pretty feature rich, there isn't much written on best practice use of it. I've decided to share my approach in hopes of sparking discussion around this topic.
For those who aren't familiar with Mongoose, it is a NodeJS wrapper around MongoDB. Being a NoSQL document store, MongoDB has no defined data structure. For those coming the world of SQL, this can be a bit alarming. Mongoose adds a data integrity layer to applications through the use of Schemas. A schema can be but isn't necessarily a "database" or "table" within MongoDB. However; this is really outside the scope of this article. Head over to the MongoDB site and lookup collections or the Mongoose website for more information.
If you're familiar with Mongoose, you know it's possible to define many Schemas in a single JavaScript file. For small applications, this isn't a big deal. However; handling a lot of schemas can get confusing with no organizational pattern.
Personally, I liked the idea of keeping my schemas organized in a one-schema-per-file manner where the file is named in representation of the data it represents. This helps isolate schema logic and keep it in the context of a single file. Furthermore, you can simply look in a single directory to see the schemas.
To accomplish this, I created MDB, available freely on my Github page.
MDB handles a lot of common stuff. For example, it supports connecting to single MongoDB instances or replica sets, it auto-includes and registers schema models, and I've added autoconnect, debugging, custom and generic errors, and connection timeouts... all wrapped up with some sugar syntax.
If you use it, please let me know. If you modify it, let me know. If you add to it, please share with everyone!
Not a question, just a "Thanks" for CFAmazon. I left comments in one of the posts, will tweet and facebook about it. It was a great help, and you obviously did all the hard work, but I just did an Amazon Payment integration for our company in just a few days... You made a great project in CFAmazon!
I'm thrilled it got you going quickly!
Attitude of Gratitude & Reaction Redaction
As a tech entrepreneur, it's easy to get caught up in "the code". It's important to remember that tech entrepreneurship isn't all about being a top notch programmer. Success in a startup requires leadership, which begins with inner-person leadership & discipline.
Attitude of Gratitude & Reaction Redaction is an approach I've been using to help keep myself focused on the big picture. The approach is simple. Every evening I list two reactions I may have been able to control better and five things I'm grateful happened.
Practice Makes Perfect
I practice this out loud with a partner (my girlfriend), but it could be done on your own. There are some very subtle nuances worth enforcing as this is practiced. For example, we always call it Attitude of Gratitude and Reaction Redaction, but share in the opposite order (i.e. reaction redaction first). It's a simple mind trick that helps enforce a positive attitude by name alone, but also concludes on a positive note. This is especially useful when getting over a bad day.
By regularly sharing with a partner, a mental list starts accumulating throughout the day. Consistency in concept helps retain a focus on the big picture. This can significantly change your attitude.
Why Bother?
Leadership & productivity are often a balancing act with the leader being the fulcrum. If the fulcrum itself is wobbly, it's hard to ever find balance.
The Challenge
It sounds simple, but some days can be pretty challenging. Bad days are prone to "gratitude blocks" while good days may seem like all of your reactions were great. Forcing yourself to find something good on a bad day reveals silver linings. Forcing yourself to find something you wish you could change (which doesn't necessarily mean something bad) helps keep people grounded & focused.
For example, I had a particularly long day riddled with problems. It was topped off with the dog doing his business in the middle of the road. I was frustrated, but saw the silver lining in the fact he didn't do it indoors. After dropping him off, a bird did it's business on my shoulder - all within about 5 minutes. Even though I felt like the world's animals had something against me, I was happy it didn't happen to my car or my partner. On a larger scale, it ultimately helped bring me and my partner closer together. We have something to look back on and say "remember when that happened?!"
By practicing a positive attitude and focusing my reactions on the bigger picture, I was able to regain/maintain my composure and move on. Life has setbacks, and the measure of a good leader is how quickly you move on. Don't ever let a poor mood be the biggest roadblock in your life.
Transitioning to Leadership
The viral effect of this practice helps in many ways. It trickles into work, into life, and into our personality. If you're not already a positive person, this might help. If you are, it might help maintain or even grow the positive vibe you give off.
When you're in a position of leadership, the attitude defines the culture of the day. It's important to keep things consistent, and a positive approach typically results in positive results.
GitHub Projects
I've recently moved several projects over to GitHub. Most of the open source work I've released is based on ColdFusion or Ext JS (Sencha). There are 5 projects at the moment.
I added a link on the right to my GitHub repositories. Or you can click here.
CFAmazon is the latest and probably most regularly updated right now. The code library is quite functional, but I don't have a lot of live examples. You can download them and run on your own, or see the recent presentation I gave on Slideshare.
AssetTracker is a full web-based GUI application written with a ColdFusion back end and an Ext JS front end. It connects to Active Directory and helps document all of the stuff Active Directory doesn't track about your computers. For example, I use it to keep track of ColdFusion apps running on a specific server, track IP addresses (pub/priv), etc. Screenshots are available at http://open.ecorgroup.com.
PostIt is a full web-based GUI application written with a ColdFusion back end and an Ext JS front end. The visual interface allows people to construct surveys that generate XML, allowing developers to apply common XSL/CSS for custom display. It also supports reporting. This was mostly an experiment converting an older application to ColdFusion 9, so there are a few issues that are pretty easy to work around. You can read about it in the Best of CF9 Contest. Screenshots available at http://open.ecorgroup.com.
BugConnect is a ColdFusion wrapper for Bugzilla. It supports creating a custom interface when the ugly Bugzilla interface is simply too much for end users to handle. I probably won't be updating this project anymore, but I've put it on GitHub for archive purposes. If anyone is interested in contributing to it or taking it on, let me know.
CFExtConnect is a replacement for Ext.Direct, specifically targeting ColdFusion interaction. It simplifies the process of communicating with CF from Ext.
What's Next?
To be completely honest, I don't anticipate updating these projects much anymore, except for CFAmazon. I'm not saying the projects are dead, because there are people using them (including me). However; the motivation and time is lacking. Sponsorship would help with the motivation, mostly because I am running a consulting firm and working on 4 other startups. There are a few thoughts I've had regarding each project, which I feel comfortable sharing publicly.
AssetTracker & PostIt are both based on Ext 3.x. I have moved to Ext 4, which is significantly different. Even though the apps are probably backward compatible (shout out to the guy working on compatibility at Sencha), the Ext data model package is so different (in a great way) that the ColdFusion portion would be easier to rewrite. I'd also like to see more standard JSON out of CF. Furthermore, I am considering a commercial SaaS version of both of these projects. The feedback so far (which has been minimal) is people are interested in using the applications, not developing them. A friend of mine recently commented on AssetTracker being a thesis in CF/Ext. I certainly hope there is educational value, but the project has a fair number of infrastructure requirements my company could better support out of our data center.
BugConnect was created to support a public beta testing site we had. That project has taken a significant turn in a different direction and Bugzilla is no longer the right fit for it. I still use Bugzilla regularly, but I don't have a need to have Bugzilla facing the public anymore.
CFExtConnect is the most likely to get updated from time to time, for odd reasons. I use ColdFusion in some very non-traditional ways. I've recently favored using SSJS (Server Side JavaScript) instead of CF for web back ends, and my CF development focuses more on processes like ETL, Gateways, and bulk data processing. However; I also do a lot of transition work helping companies upgrade and integrate different technologies. I can see myself continuing to add features to this library, but it will be primarily dependent on the needs of the clients I'm working with.
So what new stuff will be coming out?
CFAmazon will continue, but you can also expect to see new projects using new technologies.
Aside from running a web consulting practice, I also run a data warehousing and business intelligence practice. We use a lot of Cognos, and I've been coming across a few clients interested in using ColdFusion to increase their Cognos capabilities. It's a niche, but one I've seen slowly crop up over the years.
Outside of that, all I can do is speculate. Tell me what you're interested in seeing. That's how some open source projects have started in the past.
ACFUG Presentation: CFAmazon
Short notice, but I'll be presenting my work on CFAmazon at the Austin ColdFusion User Group meeting tomorrow. Details are available here. Or, if you can't make it, the presentation is up on Slideshare. It's also up on SlideSix. Contact me if you want to see the live examples.
Using ColdFusion with Amazon Payments
With Amazon Payments, web developers can simplify the checkout and payment process for millions of people who are already registered Amazon customers. Amazon Payments offers a hosted e-commerce solution and a payments-only service called Amazon Simple Pay, but what do you use when you want to integrate Amazon Payments into your own e-commerce site?
Checkout by Amazon offers an API for developers who want to integrate the service into their own website. The API offers significant flexibility for developers, but there is so much it can sometimes be difficult to know where to start. Luckily, there is a ColdFusion wrapper and examples available at https://github.com/ecorgroup/amazon. After reading this, you should have an idea of how to get Checkout by Amazon working on your ColdFusion website.
There are three high level areas every developer should be aware of before getting started.
XML-based Carts & Signatures
All information sent between your website and Amazon is formatted as XML. Security is important, especially when dealing with online payments. Therefore, all XML must be signed with a unique signature. Creating the signature is a part of the process where many questions arise, so they’re addressed in detail below. XML-based carts are covered in the basic integration guide provided on Seller Central (your Amazon merchant account).
Callback API
The Callback API offers developers advanced customization capabilities for the checkout process. This API can be used to programmatically override default taxes, manage promotions, and create special shipping options. It is called the Callback API because it uses callback URLs defined in Seller Central (the merchant portal) to communicate with your website. Details of the callback API are covered in the Callback API PDF guide.
Instant Payment Notification
IPN can be used to perform custom actions for an order. This feature will post information to a predefined URL when an order is placed or cancelled. This is a good way to log orders in your own database, update your CRM application, or create a follow-up request. IPN is covered in the Integration Guide.
Working with Amazon Payments requires an account. See the entry on Creating an Amazon Payments Seller Account.
XML-based Shopping Cart
Creating an order is a matter of passing a shopping cart to Amazon via XML. The XML must be signed with a unique key in order for Amazon to consider it valid. The first step is, of course, to create the XML shopping cart. The XML file must validate to the XSD provided by Amazon. The code should look something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<Order xmlns="http://payments.amazon.com/checkout/2009-05-15/">
<Cart>
<Items>
<Item>
<SKU>ABC123</SKU>
<MerchantId>AEIOU1234AEIOU</MerchantId>
<Title>Red Fish</Title>
<Price>
<Amount>19.99</Amount>
<CurrencyCode>USD</CurrencyCode>
</Price>
<Quantity>1</Quantity>
</Item>
</Items>
</Cart>
</Order>
The CFAmazon library provides cart and item CFC objects that can be used to intuitively prepare an order. Creating the XML is a matter of calling the cart.getXml() method.
<cfscript>
cart = createObject("component","com.amazon.cba.cart");
cart.init('ACCESSKEY','SECRET','MERCHANTID',true);
//Add a regular item to the cart.
cart.addItem('Red Fish',19.99,1);
//Add a customized item to the cart.
item = createObject("component","com.amazon.cba.item");
item.init('Blue Fish',29.99,1);
item.setWeight(1.75,"lb");
cart.addCustomItem(item);
</cfscript>
<cfdump var="#cart.getXml()#" label="Order XML"/>
The code above (found in CFAmazon xml-signed.cfm example) creates an XML cart with two different items, one of which has a custom weight. To see the XML, dump the cart object.
Now that an order is prepared, it must be signed and submitted to Amazon Payments for processing. Amazon provides some standard JavaScript widgets that can be used to generate the Checkout by Amazon button shown below:
To create the button, the JavaScript file must be included in the head of page:
<script language="javascript" src="https://payments-sandbox.amazon.com/cba/js/PaymentWidgets.js"></script>
Put a <div> with a unique ID into the page wherever the button should show up. Before the </body> tag, JavaScript must be included to actually create the button.
<body>
<div id="signedBtn"/>
<cfoutput>
<script>
new CBA.Widgets.StandardCheckoutWidget({
merchantId:'#cart.merchantID#',
orderInput:{
format:"XML",
value: "type:merchant-signed-order/aws-accesskey/1;order:#toBase64(cart.getXml())#;signature:#cart.getXmlSignature()#;aws-access-key-id:#cart.accessKeyID#"
},
buttonSettings:{
size:'large',
color:'orange',
background:'green'
}
}).render("signedBtn");
</script>
</cfoutput>
</body>
Let’s break down the code. First, the cart object contains all of the parameters required for submitting an order. The merchantID and accessKeyID , highlighted in grey and yellow, are defined when the cart is initialized (these values are found in your Seller Central account). The order (in turquoise) is the Base64 encoding of your XML cart. A signature, highlighted in green, can be generated using the getXmlSignature() method of the cart object.
The code above is enough to generate a checkout button for an order. When the user clicks on the button, a window will pop up asking them to login to Amazon to complete the order.
Digging Deeper: How is the signature generated?
Generating the signature is typically the most problematic part of the process. CFAmazon abstracts the complexity of creating a signature by hand, but here is a breakdown for those who are interested. The signature is generated using the XML cart (string) and a unique key (your Access Secret assigned in Seller Central) encrypted using HMAC-SHA1. The getXmlSignature() method is a shortcut method that converts the XML cart to a string and passes the data and your Access Secret to a common method found in the factory.cfc file shown below.
<cffunction name="sign" access="public" output="false" returntype="String">
<cfargument name="data" type="String" required="true"/>
<cfargument name="key" type="String" required="true"/>
<cfscript>
var sformat = "UTF-8";
var ekey = createObject("java","javax.crypto.spec.SecretKeySpec");
var secret = ekey.Init(arguments.key.getBytes(sformat),"HmacSHA1");
var mac = createObject("java","javax.crypto.Mac");
//Initialize the MAC
mac = mac.getInstance(ekey.getAlgorithm());
mac.init(secret);
return toBase64(mac.doFinal(arguments.data.getBytes(sformat)));
</cfscript>
</cffunction>
The function above creates a java object to do the encryption and returns a Base64 encoded string that can be used as the signature.
The Callback API
If you’re running a promotion, have special shipping options, or need to specify taxes for a specific order on the fly, then the callback API is necessary. Use of the callback API requires additional XML code. Once again, CFAmazon attempts to abstract the complexity of creating the XML. Observe the code below (xml-signed-callbacks.cfm):
<cfscript>
cart = createObject("component","com.amazon.cba.cart");
cart.init('ACCESSKEY','SECRET','MERCHANTID',true);
//Initialize callbacks
cart.setCallbackUrl('CALLBACKURL');
cart.setCalculatePromotions(true);
//Add a regular item to the cart.
cart.addItem('Red Fish',19.99,2,'12345SKU');
//Add a customized item to the cart.
item = createObject("component","com.amazon.cba.item");
item.init('Blue Fish',29.99,1);
item.setWeight(1.75,"lb");
item.setSKU('6789SKU');
cart.addCustomItem(item);
//Add a regular item to the cart.
cart.addItem('Fish Tank',49.99,1,'SKU123');
</cfscript>
This example sets the callback URL and indicates a custom promotion needs to be calculated and applied to the order. Notice that all of the items are assigned a unique SKU number. SKU numbers act as a unique identifier and are required to use the callback API. When the user clicks the Checkout with Amazon button, Amazon creates a form POST to the callback URL. Your website must be able to handle this request and respond in a timely fashion (under 5 seconds) in order to be considered valid.
CFAmazon includes a file called callback.cfm which contains example code for your callback URL. An object called callback.cfc provides several helper methods to simplify the process of creating a response. Since Amazon uses a POST request to callback URL, all of the data is available in the FORM scope, but it is URL encoded.
<!--- Create an Amazon Factory to help with processing the callback --->
<cfset callback = createObject("component","com.amazon.cba.callback")/>
<cfset callback.init('ACCESSKEY','SECRET','MERCHANTID',true)/>
<!--- Callback API Response --->
<cftry>
<!--- 1. Verify the request is from Amazon. --->
<cfset valid = callback.verifyRequestIsFromAmazon(urldecode(form.UUID),urldecode(form.Timestamp),form.Signature)/>
<cfif not valid>
<!--- Handle fake requests --->
<cfexit>
</cfif>
<!--- 2. Parse the XML Request Data --->
<cfset callback.parseRequest(urldecode(form['order-calculations-request']))/>
<!--- 3. Calculate Promotional Discounts --->
<cfscript>
//Get all Item SKU numbers from the order
skus = callback.getAllItemSkuNumbers();
//Create & apply a basic promotion/discount
callback.addPromotion("halfoffbluefish","Half Off Blue Fish!",.5,false);
callback.applyPromotion(skus[2],"halfoffbluefish"); //applied to the second item (Blue Fish)
</cfscript>
<cfoutput>#callback.generateResponse()#</cfoutput>
<cfcatch type="any">
<!--- Respond to Amazon with an error --->
<cfoutput>#toString(callback.getXmlResponse("INTERNAL_SERVER_ERROR",cfcatch.message&" "&cfcatch.detail))#</cfoutput>
</cfcatch>
</cftry>
Since your callback URL is open to the whole world, it is important to verify that the callback request is actually from Amazon. The verifyRequestIsFromAmazon method (found in factory.cfc) is used to accomplish this. This function generates a valid signature and compares it to the signature submitted to your callback page. Additionally, it checks the timestamp against your local server time to make sure the request was submitted within the last 15 minutes. If either of these conditions fails, the request is not considered valid and processing cannot continue.
Once the request is validated, the callback can processed. Amazon posts an attribute called order-calculations-request containing the XML cart with additional nodes (such as customer address). CFAmazon parses this content into an attribute (struct) called REQUEST, simply to make the data more manageable and accessible.
Next, the custom promotion must be defined and applied to the items you want to discount. The addPromotion method defines a unique ID for the promotion, a description, and a fixed or percentage-based discount value. The addPromotion method associates the promotion with the SKU number of the discounted item. Both of these methods set flags that help the callback object generate a proper XML response with only the requested callback information.
Finally, the XML response is generated and output to the page. Amazon uses this to complete the order process with the specified customizations applied in real time.
It’s important to note that the callback API is very flexible and very powerful. CFAmazon only implements the most common functionality. If your website requires more customization, read the Callback API Guide (PDF) provided by Amazon. Once you have gained an understanding of how callbacks are processed, the callback.cfc file should be updated with your modifications. If you implement any additional functionality, please consider contributing it to the CFAmazon project!
Instant Payment Notification
IPN provides developers the ability to direct the user’s browser to different locations after they complete or cancel the order. Amazon automatically sends a confirmation email to the customer upon completion of a transaction, but IPN can come in handy if you want to setup a “Thank You” landing page, log the order, or perform any other post-order processing. Amazon will direct the user’s browser to the appropriate URL defined in your Seller Central “Checkout Pipeline” settings shown below. This is a basic redirect that contains a number of URL parameters. For testing purposes, it’s a good idea to simply dump the URL scope to the screen (i.e. <cfdump var="#url#">) in order to see all of the data available.
Conclusion
CFAmazon is really just a starting point for working with Amazon Payments. There are many more features available for developers. Keep an eye on the GitHub repository and RIAForge for updates, and of course submit your own modifications for the benefit of the community!