Wednesday, November 28, 2012

Amazon Checkout HMAC-SHA1 With Classic ASP

I've been trying to implement Amazon Checkout for the last few days.  Using Classic ASP it's been a real nightmare: no sample code to work with.

I've finally cracked it with the help of some Google Checkout cryptography libraries , specifically the file "GlobalAPIFunctions.asp" located in the sample code linked to above.

You will also need to get the GCrypt COM object installed on your server.  I had to ask my hosting company to do this, it might already be installed since Google Checkout is popular.

Here is the code that worked.  Before you use it:

  • Download the GlobalAPIFunctions.asp file and install it on your server
  • Edit the include file URL to point to GlobalAPIFunctions.asp
  • Edit the AWSSecretKey, AWSAccessKeyID, and AWSMerchantID variables to match your Amazon Checkout account
  • Make sure GCrypt COM Object is installed
  • Edit the cart XML for your purposes


<!--#include virtual="/api/GlobalAPIFunctions.asp"-->

<%
        'This is a Base64 encode that doesn't put line breaks in like Google's does
Dim Base64Chars
Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" & _
"abcdefghijklmnopqrstuvwxyz" & _
"0123456789" & _
"+/"


' Functions for encoding string to Base64
Public Function base64_encode( byVal strIn )
Dim c1, c2, c3, w1, w2, w3, w4, n, strOut
For n = 1 To Len( strIn ) Step 3
c1 = Asc( Mid( strIn, n, 1 ) )
c2 = Asc( Mid( strIn, n + 1, 1 ) + Chr(0) )
c3 = Asc( Mid( strIn, n + 2, 1 ) + Chr(0) )
w1 = Int( c1 / 4 ) : w2 = ( c1 And 3 ) * 16 + Int( c2 / 16 )
If Len( strIn ) >= n + 1 Then
w3 = ( c2 And 15 ) * 4 + Int( c3 / 64 )
Else
w3 = -1
End If
If Len( strIn ) >= n + 2 Then
w4 = c3 And 63
Else
w4 = -1
End If
strOut = strOut + mimeencode( w1 ) + mimeencode( w2 ) + _
 mimeencode( w3 ) + mimeencode( w4 )
Next
base64_encode = strOut
End Function

Private Function mimeencode( byVal intIn )
If intIn >= 0 Then
mimeencode = Mid( Base64Chars, intIn + 1, 1 )
Else
mimeencode = ""
End If
End Function


' Function to decode string from Base64
Public Function base64_decode( byVal strIn )
Dim w1, w2, w3, w4, n, strOut
For n = 1 To Len( strIn ) Step 4
w1 = mimedecode( Mid( strIn, n, 1 ) )
w2 = mimedecode( Mid( strIn, n + 1, 1 ) )
w3 = mimedecode( Mid( strIn, n + 2, 1 ) )
w4 = mimedecode( Mid( strIn, n + 3, 1 ) )
If w2 >= 0 Then _
strOut = strOut + _
Chr( ( ( w1 * 4 + Int( w2 / 16 ) ) And 255 ) )
If w3 >= 0 Then _
strOut = strOut + _
Chr( ( ( w2 * 16 + Int( w3 / 4 ) ) And 255 ) )
If w4 >= 0 Then _
strOut = strOut + _
Chr( ( ( w3 * 64 + w4 ) And 255 ) )
Next
base64_decode = strOut
End Function

Private Function mimedecode( byVal strIn )
If Len( strIn ) = 0 Then
mimedecode = -1 : Exit Function
Else
mimedecode = InStr( Base64Chars, strIn ) - 1
End If
End Function

'AMAZON VARS
dim AWSSecretKey
dim AWSAccessKeyID
dim AWSMerchantID
dim AWSSignature
dim AWSCart
dim AWSCartB64

AWSSecretKey = "XXXXXXXXXXXXXXXXXXXXXXX"
AWSAccessKeyID = "123ABCDEFG"
AWSMerchantID = "123XZY"

'AMAZON VARS END

AWSCart = AWSCart & "<?xml version=" & """" & "1.0" & """" & " encoding=" & """" & "UTF-8" & """" & "?>"
AWSCart = AWSCart & "<Order xmlns=" & """" & "http://payments.amazon.com/checkout/2009-05-15/" & """" & ">"
AWSCart = AWSCart & "<Cart>"
AWSCart = AWSCart & "<Items>"

'while 'Iterate through the items in the cart here



'AMAZON ADD ITEM TO CART
AWSCart = AWSCart & "<Item>"
        AWSCart = AWSCart & "<SKU>" & YourSKU & "</SKU>"
        AWSCart = AWSCart & "<MerchantId>" & AWSMerchantID & "</MerchantId>"
      AWSCart = AWSCart & "<Title>" & YourItemName & "</Title>"
        AWSCart = AWSCart & "<Price>"
          AWSCart = AWSCart & "<Amount>" & YourPrice & "</Amount>"
          AWSCart = AWSCart & "<CurrencyCode>USD</CurrencyCode>"
        AWSCart = AWSCart & "</Price>"
        AWSCart = AWSCart & "<Quantity>" & YourQuantity & "</Quantity>"
      AWSCart = AWSCart & "</Item>"

'AMAZON ADD ITEM TO CART END
'wend 'Finished iterating through items in the cart

'AMAZON Process Cart

AWSCart = AWSCart & "</Items>"
  AWSCart = AWSCart & "</Cart>"
AWSCart = AWSCart & "</Order>"

AWSSignature = cryptObj.generateSignature(AWSCart, AWSSecretKey)
AWSCartB64 = base64_encode(AWScart)

set cryptObj = Nothing
%>
<html>
<body>
<!-- AMAZON CHECKOUT BUTTON -->
<script type='text/javascript' src='https://static-na.payments-amazon.com/cba/js/us/sandbox/PaymentWidgets.js'>
</script>

<!-- For Switching to Production, comment out the lines above and uncomment the lines below -->
<!-- <script type='text/javascript' src='https://static-na.payments-amazon.com/cba/js/us/PaymentWidgets.js'>
</script> -->

<div id="cbaButton1">
    <img src="https://payments-sandbox.amazon.com/gp/cba/button?type=cart&cartOwnerId=<%= AWSMerchantID %>&color=orange&size=large&background=white"/>
    <!-- For Switching to Production, comment out the line above and uncomment the line below -->
    <!--<img src="https://payments.amazon.com/gp/cba/button?type=cart&cartOwnerId=<%= AWSMerchantID %>&color=orange&size=large&background=white"/>-->
</div>

<script type='text/javascript'>
  new CBA.Widgets.StandardCheckoutWidget({
    merchantId:'<%= AWSMerchantID %>',
    orderInput: {
        format: "XML",
        value: "type:merchant-signed-order/aws-accesskey/1;order:<%= AWSCartB64 %>;signature:<%= AWSSignature %>;aws-access-key-id:<%= AWSAccessKeyID %>"},
        buttonSettings: { size: 'large',color:'orange',background:'white'}
  }).render("cbaButton1");
</script>
</body>
</html>
<!-- END AMAZON CHECKOUT BUTTON -->

Tuesday, November 20, 2012

New Website


I've been hard at work updating RebrandSoftware.com with a focus on apps.

The new site features easier navigation, the ability to review apps, a much better support section, and news via the official blog.  You can also get a glimpse of me and my family in the new About section.

Along with the new website comes a new app, Easy Calorie Counter which I will post about in more detail soon.

It's also much easier to track your app purchases now.  We keep the download links and registration information available on the new My Apps page, and also give you the ability to rate apps you purchase or switch computers.

Most of our apps are now on the Mac App Store, so Mac users can choose whether you want to get them there or through our website.

I've been working on the site for months now, but there are bound to be some issues when it goes live.  Hopefully we will be able to work through those quickly.