VB.NETでアマゾンAPIを使う

VB.NETでのProduct Advertising API 署名認証

VB.NETでのProduct Advertising API 署名認証してみました。
いろいろなサンプルとかあるけど、VB.NETの完全なサンプル見つからないし、
わかりにくかったので、情報集めて、動くようにしました。
Amazonが署名認証導入してから、ハマっている人たくさんいそう。

 

 

VS.NET2008で作ってます。
まず、System.WEBを参照に追加。
次に以下のモジュールを追加

 

**********************************************************************

 

Module ModuleAmazonAPI

 

 

    Dim sAssociateTag As String = "[アソシエイトタグ]"
    Dim sAccessKeyId As String = "[アクセスキーID]"
    Dim sSecretAccessKey As String = "[シークレットアクセスキー]"

 

 

    Public Function MakeAmazonRequest( _
    ByVal sAssociateTag As String, _
    ByVal sAccessKeyId As String, _
    ByVal sSecretAccessKey As String, _
    ByVal sSearchKeyWord As String) As String

 

        Dim dictRequest As New Dictionary(Of String, String)
        'リクエストパラメータをハッシュテーブルに保存
        dictRequest("Service") = "AWSECommerceService"
        dictRequest("Version") = "2008-04-07"
        dictRequest("AssociateTag") = sAssociateTag
        dictRequest("ContentType") = "Text/XML"
        dictRequest("Operation") = "ItemSearch"
        dictRequest("ResponseGroup") = "Small,ItemAttributes,Reviews,EditorialReview,Images,BrowseNodes,SalesRank,Offers"
        dictRequest("AWSAccessKeyId") = sAccessKeyId
        dictRequest("SearchIndex") = "All"
        dictRequest("Keywords") = sSearchKeyWord

 

        Dim dteNow As DateTime = DateTime.UtcNow
        Dim sTimeStamp As String = dteNow.ToString("yyyy-MM-ddTHH:mm:ssZ")
        'タイムスタンプはGMT
        dictRequest("Timestamp") = sTimeStamp

 

 

        Dim pc As New ParamComparer()
        Dim sortedHash As New SortedDictionary(Of String, String)(dictRequest, pc)

 

        ' Get the canonical query string
        Dim canonicalQS As String = ConstructCanonicalQueryString(sortedHash)

 

        '以下の部分を追加
        '============================
        'GET
        'ecs.amazonaws.jp
        '/onca/xml
        '============================
        Dim builder As New System.Text.StringBuilder()
        builder.Append("GET").Append(vbLf).Append(CStr("ecs.amazonaws.jp").ToLower()).Append(vbLf).Append("/onca/xml").Append(vbLf).Append(canonicalQS)

 

        Dim stringToSign As String = builder.ToString()
        Dim toSign As Byte() = System.Text.Encoding.UTF8.GetBytes(stringToSign)

 

        Dim secret As Byte()
        secret = System.Text.Encoding.UTF8.GetBytes(sSecretAccessKey)
        Dim signer As System.Security.Cryptography.HMAC
        signer = New Security.Cryptography.HMACSHA256(secret)

 

        Dim sigBytes As Byte() = signer.ComputeHash(toSign)
        Dim signature As String = Convert.ToBase64String(sigBytes)

 

        Dim qsBuilder As New System.Text.StringBuilder()
        qsBuilder.Append(" http://").Append("ecs.amazonaws.jp").Append("/onca/xml").Append("?").Append(canonicalQS).Append("&Signature=").Append(PercentEncodeRfc3986(signature))

 

        Return qsBuilder.ToString()

 

    End Function

 

    Private Function PercentEncodeRfc3986(ByVal str As String) As String
        str = System.Web.HttpUtility.UrlEncode(str, System.Text.Encoding.UTF8)
        'str.Replace("'", "%27").Replace("(", "%28").Replace(")", "%29").Replace("*", "%2A").Replace("!", "%21").Replace("%7e", "~")
        str = str.Replace("'", "%27").Replace("(", "%28").Replace(")", "%29").Replace("*", "%2A").Replace("!", "%21").Replace("%7e", "~").Replace("+", "%20")

 

 

        Dim sbuilder As New System.Text.StringBuilder(str)
        For i As Integer = 0 To sbuilder.Length - 1

 

            If sbuilder(i) = "%"c Then
                'コメント化
                'If [Char].IsDigit(sbuilder(i + 1)) AndAlso [Char].IsLetter(sbuilder(i + 2)) Then
                sbuilder(i + 1) = [Char].ToUpper(sbuilder(i + 1)) '日本語対策で追加
                sbuilder(i + 2) = [Char].ToUpper(sbuilder(i + 2))
                'End If
            End If

 

        Next
        Return sbuilder.ToString()
    End Function

 

 

    Private Function ConstructCanonicalQueryString(ByVal sortedParamMap As SortedDictionary(Of String, String)) As String
        Dim builder As New System.Text.StringBuilder()

 

        If sortedParamMap.Count = 0 Then
            builder.Append("")
            Return builder.ToString()
        End If

 

        For Each kvp As KeyValuePair(Of String, String) In sortedParamMap

 

            builder.Append(PercentEncodeRfc3986(kvp.Key))
            builder.Append("=")
            builder.Append(PercentEncodeRfc3986(kvp.Value))
            builder.Append("&")
        Next
        Dim canonicalString As String = builder.ToString()
        canonicalString = canonicalString.Substring(0, canonicalString.Length - 1)
        Return canonicalString
    End Function

 

    Class ParamComparer
        Implements IComparer(Of String)
        Public Function Compare(ByVal p1 As String, ByVal p2 As String) As Integer Implements IComparer(Of String).Compare
            Return String.CompareOrdinal(p1, p2)
        End Function
    End Class

 

End Module

 

 

**********************************************************************

 

使いかたは、

 

**********************************************************************

        Dim sAssociateTag As String = "[アソシエイトタグ]"
        Dim sAccessKeyId As String = "[アクセスキーID]"
        Dim sSecretAccessKey As String = "[シークレットアクセスキー]"
        Dim sURL as String

 

        sURL = MakeAmazonRequest(sAssociateTag, sAccessKeyId, sSecretAccessKey, "ラーメンマン")

 


**********************************************************************

 

sURLでアクセスすれば、検索結果を得られます。

初心者が初報酬を得るなら