Yahooショップ、アマゾンのEC用のAPI プログラムサンプル
Yahooショップ、アマゾンといったECサイトのAPIについて調べてみた。リダイレクト用のURLにlocalhostを設定できない場合もあるようだ。BASEはダメとのこと。まあ、サーバ立てればいいのだけど。
広告用じゃなくて出店者向けのAPIのサンプル。広告向けはいっぱいあるけど出店者向けはあまりないような感じもするので。言語はDelphi。
コード
unit ecapi; interface uses Winapi.Windows,System.SysUtils,System.Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, Vcl.StdCtrls, IPPeerClient, strUtils, IdCustomTCPServer, IdCustomHTTPServer, IdHTTPServer, IdContext, IdMultipartFormData, IdGlobal, IdHashSHA, IdHMAC, IdHMACSHA1, IdCoder, IdCoder3to4, IdCoderMIME, HTTPApp, IdHashMessageDigest; const YAPIURL = 'https://circus.shopping.ecapis.jp/ShoppingWebService/V1/'; // YAPIURL= 'https://test.circus.shopping.ecapis.jp/ShoppingWebService/V1/'; YAUTHAPIURL = 'https://auth.login.yahoo.co.jp/yconnect/v1/token'; YREDIRECTURL = 'http://localhost/'; type Tecapi = class(tobject) private FASellerId, FAToken, FAWSAccessKeyId, FASecretKey, FYSellerId, FYToken, FYapp_id, FYSecretKey, FAMarketplaceId,FYRefreshToken: string; function TextCut(s: string; cut1: string; cut2: string): string; function GetMD5(msg: string; code: string): string; public property YSellerId: string read FYSellerId write FYSellerId; property YToken: string read FYToken write FYToken; property YRefreshToken: string read FYRefreshToken write FYRefreshToken; property Yapp_id: string read FYapp_id write FYapp_id; property YSecretKey: string read FYSecretKey write FYSecretKey; property ASellerId: string read FASellerId write FASellerId; property AToken: string read FAToken write FAToken; property AWSAccessKeyId: string read FAWSAccessKeyId write FAWSAccessKeyId; property ASecretKey: string read FASecretKey write FASecretKey; property AMarketplaceId: string read FAMarketplaceId write FAMarketplaceId; function editItem(PostStream: TStringList): string; function getStock(PostStream: TStringList): string; function uploadItemImage( filepass: string): string; function getreftoken(refresh_token: string ): string; function gettoken(code: string): string; function deleteItem( item_code: string): string; function reservePublish( mode: string; reserve_time: string): string; function getShopProductCodeList( query: string; types: string; sort: string; start: string; results: string): string; function getShopBrandList(query: string; types: string; sort: string; start: string; results: string): string; function getShopCategoryList( query: string; category_code: string; types: string; sort: string; start: string; results: string): string; function orderCount: string; function orderList(xml: string): string; function orderInfo(xml: string): string; function cutToken(code: string): string; function cutreftoken(code: string): string; function MwsRequest(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string): string; function MwsRequestFeedFlat(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string; postdata: string): string; function MwsRequestFeedXml(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string; postdata: string): string; end; implementation // Yahoo shop API function Tecapi.TextCut(s: string; cut1: string; cut2: string): string; var i: integer; begin i := Pos(cut1, s); if i > 0 then begin i := i + length(cut1); s := copy(s, i, 10000000); i := Pos(cut2, s); result := copy(s, 1, i - 1); end else begin result := ''; end; end; function Tecapi.cutToken(code: string): string; begin result := TextCut(code, '"access_token":"', '"'); end; function Tecapi.cutreftoken(code: string): string; begin result := TextCut(code, 'refresh_token":"', '"'); end; function Tecapi.editItem(PostStream: TStringList): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; begin result := ''; PostStream.Clear; ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http := TIdHTTP.Create(); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'editItem', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.getStock(PostStream: TStringList): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; begin result := ''; PostStream.Clear; http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'getStock', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.deleteItem( item_code: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add('seller_id=' + FYSellerId); PostStream.Add('item_code=' + item_code); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); // UTF8のサイトの場合 strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'deleteItem', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; PostStream.Free; strm.Free; end; end; // PostStream.Add('seller_id='); // PostStream.Add('item_code='); // PostStream.Add('name='); // PostStream.Add('path='); // PostStream.Add('product_category='); // PostStream.Add('price='); // 商品画像:商品コード.拡張子 // 商品詳細画像:商品コード_(1-5).拡張子 // http://developer.yahoo.co.jp/webapi/shopping/uploadItemImage.html function Tecapi.uploadItemImage( filepass: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; DataStream: TIdMultiPartFormDataStream; begin result := ''; DataStream := TIdMultiPartFormDataStream.Create; DataStream.AddFile('file', filepass, 'multipart/form-data'); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http := TIdHTTP.Create(); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'uploadItemImage?seller_id=' + FYSellerId, DataStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; DataStream.Free; end; end; function Tecapi.reservePublish(mode: string; reserve_time: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add('seller_id=' + FYSellerId); PostStream.Add('mode=' + mode); PostStream.Add('reserve_time=' + reserve_time); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'reservePublish', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; PostStream.Free; strm.Free; end; end; function Tecapi.getShopProductCodeList( query: string; types: string; sort: string; start: string; results: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; gettext: string; begin result := ''; gettext := 'seller_id=' + FYSellerId + '&query=' + query + '&type=' + types + '&sort=' + sort + '&start=' + start + '&results=' + results; http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Get(YAPIURL + 'getShopProductCodeList?' + gettext, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.getShopBrandList( query: string; types: string; sort: string; start: string; results: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; gettext: string; begin result := ''; gettext := 'seller_id=' + FYSellerId + '&query=' + query + '&type=' + types + '&sort=' + sort + '&start=' + start + '&results=' + results; http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Get(YAPIURL + 'getShopBrandList?' + gettext, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.getShopCategoryList( query: string; category_code: string; types: string; sort: string; start: string; results: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; gettext: string; begin result := ''; gettext := 'seller_id=' + FYSellerId + '&query=' + query + '&category_code=' + category_code + '&type=' + types + '&sort=' + sort + '&start=' + start + '&results=' + results; http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); // UTF8のサイトの場合 strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Get(YAPIURL + 'getShopCategoryList?' + gettext, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.orderCount: string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; gettext: string; begin result := ''; gettext := 'seller_id=' + FYSellerId; http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Get(YAPIURL + 'orderCount?' + gettext, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; end; end; function Tecapi.orderList(xml: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add(xml); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'orderList', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; PostStream.Free; strm.Free; end; end; function Tecapi.orderInfo(xml: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add(xml); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); http.ProtocolVersion := pv1_1; try http.IOHandler := ssl; http.Request.CustomHeaders.FoldLines := False; http.Request.CustomHeaders.AddValue('Authorization', 'Bearer ' + FYToken); http.Post(YAPIURL + 'orderInfo', PostStream, strm); strm.Position := 0; // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; PostStream.Free; strm.Free; end; end; // トークン関係 //ログインしないとトークンを取得するためのcodeが取得できない //https://auth.login.yahoo.co.jp/yconnect/v1/authorizatione= // //リフレッシュトークンからトークン取得 function Tecapi.getreftoken(refresh_token: string ): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add('grant_type=refresh_token'); PostStream.Add('refresh_token=' + refresh_token); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); try http.IOHandler := ssl; http.Request.BasicAuthentication := true; http.HandleRedirects := true; http.Request.Username := Yapp_id; http.Request.Password := YSecretKey; http.Post(YAUTHAPIURL, PostStream, strm); strm.Position := 0; result := strm.DataString; self.FYToken := cuttoken(strm.DataString); finally http.Free; ssl.Free; strm.Free; PostStream.Free; end; end; //トークン取得プロパティにも投入 function Tecapi.gettoken(code: string): string; var http: TIdHTTP; ssl: TIdSSLIOHandlerSocketOpenSSL; strm: TStringStream; PostStream: TStringList; begin result := ''; PostStream := TStringList.Create; PostStream.Clear; PostStream.Add('grant_type=authorization_code'); PostStream.Add('code=' + code); PostStream.Add('redirect_uri=' + YREDIRECTURL); http := TIdHTTP.Create(); ssl := TIdSSLIOHandlerSocketOpenSSL.Create(); strm := TStringStream.Create('', TEncoding.UTF8); try http.IOHandler := ssl; http.Request.BasicAuthentication := true; http.HandleRedirects := true; http.Request.Username := Yapp_id; http.Request.Password := YSecretKey; http.Post(YAUTHAPIURL, PostStream, strm); strm.Position := 0; self.FYToken := cuttoken(strm.DataString); FYRefreshToken := cutreftoken(strm.DataString); // 取得したハイパーテキストを出力 result := strm.DataString; finally http.Free; ssl.Free; strm.Free; PostStream.Free; end; end; // Amazon MWS API // //http://services.amazon.co.jp/services/automation/for-developer.html //https://mws.amazonservices.jp/scratchpad/index.html // //AParamsにコマンドを投入する // function Tecapi.GetMD5(msg: string; code: string): string; var md5: TIdHashMessageDigest5; begin md5 := TIdHashMessageDigest5.Create; //MD5は文字コードを合わせないとエラーが発生 try result := TIdEncoderMIME.EncodeBytes (md5.HashBytes(TIdBytes(TEncoding.UTF8.GetBytes(msg)))); if code = 'ASCII' then begin result := TIdEncoderMIME.EncodeBytes (md5.HashBytes(TIdBytes(TEncoding.ASCII.GetBytes(msg)))); end else if code = 'ANSI' then begin result := TIdEncoderMIME.EncodeBytes (md5.HashBytes(TIdBytes(TEncoding.ANSI.GetBytes(msg)))); end; finally md5.Free; end; end; function CustomSortASC(List: TStringList; Index1, Index2: integer): integer; // 昇順ソート begin // result := AnsiCompareStr(List[Index1], List[Index2]); // ロケール考慮/大文字小文字区別 result := CompareStr(List[Index1], List[Index2]); // ロケール無視/大文字小文字区別 // result := AnsiCompareText(List[Index1], List[Index2]); // ロケール考慮/大文字小文字無視 // result := CompareText(List[Index1], List[Index2]); // ロケール無視/大文字小文字無視 end; // アマゾンへのアクセス function Tecapi.MwsRequest(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string): string; var i: integer; sl: TStringList; AMethod, AHost, AURI, ARequest, AStrToSign, APath, ASignature: string; AKey, AValue, AQuery: string; AHTTP: TIdHTTP; AStream, AResultStream: TStringStream; UTC: TSystemTime; dt: Tdatetime; function urlencode_rfc3986(str: string): string; begin result := replacetext(Httpencode(str), '%7E', '~'); result := replacetext(result, '+', '%20'); end; function GenerateSignature(const AData, AKey: string): string; var AHMAC: TIdBytes; begin IdSSLOpenSSL.LoadOpenSSLLibrary; IF NOT TIdHashSHA256.IsAvailable THEN Raise Exception.Create('SHA-256 hashing is not available!'); With TIdHMACSHA256.Create do try Key := IndyTextEncoding_UTF8.GetBytes(AKey); AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData)); finally Free; end; result := TIdEncoderMIME.EncodeBytes(AHMAC); end; begin AMethod := 'POST'; AHost := AEndPoint; AURI := '/' + AFolder + '/' + AVersion; AQuery := ''; sl := TStringList.Create; try sl.Assign(AParams); sl.Values['SignatureMethod'] := 'HmacSHA256'; sl.Values['SignatureVersion'] := '2'; sl.Values['SellerId'] := FASellerId; sl.Values['AWSAccessKeyId'] := FAWSAccessKeyId; sl.Values['MarketplaceId'] := FAMarketplaceId; // UTCでないとエラーになる GetSystemTime(UTC); // タイムスタンプの後にはZが必要 dt := SystemTimeToDateTime(UTC); sl.Values['Timestamp'] := FormatDateTime('YYYY-MM-DD"T"HH:NN:SS"Z"', dt); sl.Values['Version'] := AVersion; // 確実にソートしないとエラーになる sl.CustomSort(CustomSortASC); FOR i := 0 TO sl.Count - 1 DO begin AKey := urlencode_rfc3986(sl.Names[i]); AValue := urlencode_rfc3986(sl.ValueFromIndex[i]); sl[i] := AKey + '=' + AValue; end; sl.StrictDelimiter := true; sl.Delimiter := '&'; sl.QuoteChar := #0; AQuery := sl.DelimitedText; AStrToSign := AMethod + #10 + Lowercase(AHost) + #10 + AURI + #10 + AQuery; ASignature := GenerateSignature(AStrToSign, FASecretKey); APath := 'https://' + AHost + AURI + '?' + AQuery + '&Signature=' + urlencode_rfc3986(ASignature); finally sl.Free; end; AHTTP := TIdHTTP.Create(nil); try AHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(AHTTP); AHTTP.Request.ContentType := 'text/xml; charset=UTF-8'; AHTTP.Request.Connection := 'Close'; AHTTP.Request.CustomHeaders.Add ('x-amazon-user-agent: MyApp/1.0 (Language=Delphi)'); AHTTP.HTTPOptions := AHTTP.HTTPOptions + [hoKeepOrigProtocol]; AHTTP.HTTPOptions := AHTTP.HTTPOptions - [hoForceEncodeParams]; AHTTP.ProtocolVersion := pv1_1; AStream := TStringStream.Create; AResultStream := TStringStream.Create('', TEncoding.UTF8); try AHTTP.Post(APath, AStream, AResultStream); result := AResultStream.DataString; finally AStream.Free; AResultStream.Free; end; finally AHTTP.Free; end; end; //FeedType //https://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html //_POST_FLAT_FILE_FULFILLMENT_DATA_ 出荷通知 //http://aws.typepad.com/jp_mws/2011/07/amazon-mws-order-fulfillment-feed.html //https://docs.developer.amazonservices.com/ja_JP/feeds/Feeds_FeedType.html function Tecapi.MwsRequestFeedFlat(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string; postdata: string): string; var i: integer; sl: TStringList; AMethod, AHost, AURI, ARequest, AStrToSign, APath, ASignature: string; AKey, AValue, AQuery: string; AHTTP: TIdHTTP; AStream, AResultStream: TStringStream; UTC: TSystemTime; dt: Tdatetime; naiyou: ansistring; function urlencode_rfc3986(str: string): string; begin result := replacetext(Httpencode(str), '%7E', '~'); result := replacetext(result, '+', '%20'); end; function GenerateSignature(const AData, AKey: string): string; var AHMAC: TIdBytes; begin IdSSLOpenSSL.LoadOpenSSLLibrary; IF NOT TIdHashSHA256.IsAvailable THEN Raise Exception.Create('SHA-256 hashing is not available!'); With TIdHMACSHA256.Create do try Key := IndyTextEncoding_UTF8.GetBytes(AKey); AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData)); finally Free; end; result := TIdEncoderMIME.EncodeBytes(AHMAC); end; begin AMethod := 'POST'; AHost := AEndPoint; AURI := '/' + AFolder + '/' + AVersion; AQuery := ''; AStream := TStringStream.Create('', TEncoding.GetEncoding(932)); AStream.WriteString(postdata); sl := TStringList.Create; try sl.Assign(AParams); sl.Values['SignatureMethod'] := 'HmacSHA256'; sl.Values['SignatureVersion'] := '2'; GetSystemTime(UTC); dt := SystemTimeToDateTime(UTC); sl.Values['Timestamp'] := FormatDateTime('YYYY-MM-DD"T"HH:NN:SS"Z"', dt); sl.Values['Version'] := AVersion; sl.Values['ContentMD5Value'] := GetMD5(AStream.DataString, 'ANSI'); sl.Values['SellerId'] := FASellerId; sl.Values['AWSAccessKeyId'] := FAWSAccessKeyId; sl.Values['MarketplaceId'] := FAMarketplaceId; // 確実にソートする sl.CustomSort(CustomSortASC); for i := 0 to sl.Count - 1 do begin AKey := urlencode_rfc3986(sl.Names[i]); AValue := urlencode_rfc3986(sl.ValueFromIndex[i]); sl[i] := AKey + '=' + AValue; end; sl.StrictDelimiter := true; sl.Delimiter := '&'; sl.QuoteChar := #0; AQuery := sl.DelimitedText; AStrToSign := AMethod + #10 + Lowercase(AHost) + #10 + AURI + #10 + AQuery; ASignature := GenerateSignature(AStrToSign, FASecretKey); APath := 'https://' + AHost + AURI + '?' + AQuery + '&Signature=' + urlencode_rfc3986(ASignature); finally sl.Free; end; AHTTP := TIdHTTP.Create(nil); try AHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(AHTTP); AHTTP.Request.ContentType := 'text/xml; charset=UTF-8'; AHTTP.Request.Connection := 'Close'; AHTTP.Request.CustomHeaders.Add ('x-amazon-user-agent: MyApp/1.0 (Language=Delphi)'); AHTTP.Request.CustomHeaders.Add // ('text/tab-separated-values; charset=UTF-8'); ('text/tab-separated-values; charset=Shift_JIS'); AHTTP.HTTPOptions := AHTTP.HTTPOptions + [hoKeepOrigProtocol]; AHTTP.HTTPOptions := AHTTP.HTTPOptions - [hoForceEncodeParams]; AHTTP.ProtocolVersion := pv1_1; AResultStream := TStringStream.Create('', TEncoding.UTF8); try try AHTTP.Post(APath, AStream, AResultStream); except end; result := AResultStream.DataString; finally AStream.Free; AResultStream.Free; end; finally AHTTP.Free; end; end; function Tecapi.MwsRequestFeedXml(const AFolder, AVersion: string; const AParams: TStringList; const AEndPoint: string; postdata: string): string; var i: integer; sl: TStringList; AMethod, AHost, AURI, ARequest, AStrToSign, APath, ASignature: string; AKey, AValue, AQuery: string; AHTTP: TIdHTTP; AStream, AResultStream: TStringStream; UTC: TSystemTime; dt: Tdatetime; naiyou: ansistring; function urlencode_rfc3986(str: string): string; begin result := replacetext(Httpencode(str), '%7E', '~'); result := replacetext(result, '+', '%20'); end; function GenerateSignature(const AData, AKey: string): string; var AHMAC: TIdBytes; begin IdSSLOpenSSL.LoadOpenSSLLibrary; IF NOT TIdHashSHA256.IsAvailable THEN Raise Exception.Create('SHA-256 hashing is not available!'); With TIdHMACSHA256.Create do try Key := IndyTextEncoding_UTF8.GetBytes(AKey); AHMAC := HashValue(IndyTextEncoding_UTF8.GetBytes(AData)); finally Free; end; result := TIdEncoderMIME.EncodeBytes(AHMAC); end; begin AMethod := 'POST'; AHost := AEndPoint; AURI := '/' + AFolder + '/' + AVersion; AQuery := ''; AStream := TStringStream.Create('', TEncoding.UTF8); AStream.WriteString(postdata); sl := TStringList.Create; try sl.Assign(AParams); sl.Values['SignatureMethod'] := 'HmacSHA256'; sl.Values['SignatureVersion'] := '2'; GetSystemTime(UTC); dt := SystemTimeToDateTime(UTC); sl.Values['Timestamp'] := FormatDateTime('YYYY-MM-DD"T"HH:NN:SS"Z"', dt); sl.Values['Version'] := AVersion; sl.Values['ContentMD5Value'] := GetMD5(AStream.DataString, ''); sl.Values['SellerId'] := FASellerId; sl.Values['AWSAccessKeyId'] := FAWSAccessKeyId; sl.Values['MarketplaceId'] := FAMarketplaceId; // 確実にソートする sl.CustomSort(CustomSortASC); for i := 0 to sl.Count - 1 do begin AKey := urlencode_rfc3986(sl.Names[i]); AValue := urlencode_rfc3986(sl.ValueFromIndex[i]); sl[i] := AKey + '=' + AValue; end; sl.StrictDelimiter := true; sl.Delimiter := '&'; sl.QuoteChar := #0; AQuery := sl.DelimitedText; AStrToSign := AMethod + #10 + Lowercase(AHost) + #10 + AURI + #10 + AQuery; ASignature := GenerateSignature(AStrToSign, FASecretKey); APath := 'https://' + AHost + AURI + '?' + AQuery + '&Signature=' + urlencode_rfc3986(ASignature); finally sl.Free; end; AHTTP := TIdHTTP.Create(nil); try AHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(AHTTP); AHTTP.Request.ContentType := 'text/xml; charset=UTF-8'; AHTTP.Request.Connection := 'Close'; AHTTP.Request.CustomHeaders.Add ('x-amazon-user-agent: MyApp/1.0 (Language=Delphi)'); AHTTP.Request.CustomHeaders.Add('text/tab-separated-values; charset=UTF-8'); // ('text/tab-separated-values; charset=Shift_JIS'); AHTTP.HTTPOptions := AHTTP.HTTPOptions + [hoKeepOrigProtocol]; AHTTP.HTTPOptions := AHTTP.HTTPOptions - [hoForceEncodeParams]; AHTTP.ProtocolVersion := pv1_1; AResultStream := TStringStream.Create('', TEncoding.UTF8); try try AHTTP.Post(APath, AStream, AResultStream); except end; result := AResultStream.DataString; finally AStream.Free; AResultStream.Free; end; finally AHTTP.Free; end; end; end.