VB.NETでのAmazonのProduct Advertising API 署名認証してみました。
PA-APIとも言います。
PA-API経由で売上が発生しないと、PA-APIを使用することができなくなります。
いろいろなサンプルとかあるけど、VB.NETの完全なサンプル見つからないし、
わかりにくかったので、情報集めて、動くようにしました。
Amazonが署名認証導入してから、ハマっている人たくさんいそう。
VS.NET2008で作ってます。
まず、System.WEBを参照に追加。
次に以下のモジュールを追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
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 = 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 'コメント化 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 |
使いかたは、
1 2 3 4 5 6 |
Dim sAssociateTag As String = "[アソシエイトタグ]" Dim sAccessKeyId As String = "[アクセスキーID]" Dim sSecretAccessKey As String = "[シークレットアクセスキー]" Dim sURL as String sURL = MakeAmazonRequest(sAssociateTag, sAccessKeyId, sSecretAccessKey, "ラーメンマン") |
sURLでアクセスすれば、検索結果を得られます。