在“如何用MediaCapture解決二維碼掃描問題”這篇文章中,我們通過“成像”、“截圖”與“識別”三個步驟介紹了使用MediaCapture掃碼的主要過程及注意事項。本文主要針對“識別”的過程,對Barcode的概念作出一個較為簡單的介紹,同時也會討論ZXing的使用方法。
ZXing是一個Java實現的開源庫,可以支持多種Barcode的識別和生成,同時也為其它的語言提供了相應的接口,比如C++、Python、.Net等等。這里,我們使用ZXing.Net,可以很方便的集成在UWP環境中,便於掃碼工作的開發。
Barcode簡介
Barcode是一種機器可讀的數據表示方式,作為某種商品或產品的唯一標識。通常被翻譯成條碼,但我個人並不喜歡這種翻譯,因為不是所有的barcode都是條形的。當然,這應該是有歷史原因的。Barcode的形式多種多樣,按照它們的外觀,可以分為Linear barcode(一維碼)和Matrix barcode(二維碼)。你可能認為你對它們都有所了解,因為它們大概都是這個樣子的:
但事實上,它們有甚至有可能是這樣子的:
我們通常所說的二維碼和上文提到的二維碼有所不同,只是Matrix barcode的一種,叫做QR code。舉這些例子只是為了說明Barcode種類繁多,有些編碼格式並不常用,即使是ZXing也沒有做到所有格式的支持,開發者只需了解就好。
Code 39、Code 128、EAN、UPC、QR Code是我們生活中能經常見到的幾種編碼格式,同時ZXing對幾種格式都有比較好的支持。其中,UPC-A是一種國際通用的編碼格式,由12個數字構成,EAN-13是在UPC-A基礎上的一種擴充(多了一個數字)。快數一數你身邊的薯片的編碼是不是13位!如果是的話,它最前邊的兩個數字是不是“69”?在EAN-13的編碼體系中,前三位數字表示商品生產商的國家(並不是商品所屬公司的國家),中國的編碼是690~699,美國是(000~019、030~039、060~139),日本是(450~459、490~499),and so on。不同的編碼格式通常用在不同的領域,如果你看到了一個Code 39或者Code 128的Barcode,那么這很就可能是一個快遞編碼,這個時候你就可以去那些提供快遞查詢的網站查詢一下你的快遞信息,如果有API提供出來那就更是再好不過了。至於QR Code,就是我們經常用手機掃一掃的二維碼,表示的信息更是多種多樣,並不僅僅是一個url那么簡單,至於這些信息如何處理,是我們一會兒將要討論的內容。
配置工程
在另一篇文章中提到,可以在Visual Studio環境下,通過nuget管理器安裝ZXing.Net,如果你僅僅希望通過掃碼得到一個掃碼結果(比如字符串,或者是一個鏈接),當然可以這樣做,而且過程十分簡單。但這里我們並不推薦這種方法,因為從NuGet上得到的package只提供了一些簡單的API接口,並沒有將ZXing.Net的API全部提供出來,至於為什么這么做,說實話,我也不知道,可能是為了穩定性等原因。如果你是一個比較執着的programmer,也可以在使用NuGet包的情況下,自己實現其它豐富的功能,畢竟有ZXing的源代碼可以參考,這就是開源的好處!在這篇文章中,我們還是以簡單為主,畢竟ZXing.Net已經為我們提供了編譯好的動態連接庫,有什么理由讓我們不用呢?
Important 官網提供的庫和NuGet提供的庫API稍微有些不同,如果需要更換,需要稍作修改,但過程並不是很繁瑣。
你可以從http://zxingnet.codeplex.com/下載ZXing.Net的Release,壓縮包目錄下的/winrt/zxing.winrt.dll即是我們希望添加到工程的引用。
然后,把這個reference添加到相應的工程里就行:
獲取Barcode內容信息
首先,你可以按照“如何用MediaCapture解決二維碼掃描問題”這篇文章中提供的步驟,初始化攝像頭、設置Timer並添加Tick事件,在Tick事件中,通過調用ZXing.Net的API獲取掃碼結果。
private async void TimerTick(object sender, object e) { try { if (_mediaCapture == null) return; var props = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview); uint width = 0, height = 0; if (props is ImageEncodingProperties) { width = (props as ImageEncodingProperties).Width; height = (props as ImageEncodingProperties).Height; } else if (props is VideoEncodingProperties) { width = (props as VideoEncodingProperties).Width; height = (props as VideoEncodingProperties).Height; } System.Diagnostics.Debug.WriteLine("Start scanning..."); Result decodeResult = null; using (VideoFrame frameFormat = new VideoFrame(BitmapPixelFormat.Rgba8, (int)width, (int)height)) { using (var frame = await _mediaCapture.GetPreviewFrameAsync(frameFormat)) { var buffer = new Windows.Storage.Streams.Buffer( (uint)(4 * frame.SoftwareBitmap.PixelWidth * frame.SoftwareBitmap.PixelHeight)); frame.SoftwareBitmap.CopyToBuffer(buffer); var reader = new BarcodeReader(); decodeResult = reader.Decode(buffer.ToArray(), (int)width, (int)height, RGBLuminanceSource.BitmapFormat.RGB32); System.Diagnostics.Debug.WriteLine(decodeResult); if (decodeResult != null) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { resultTextBlock.Text = decodeResult.Text; }); } } } //You can handle decodeResult by other ways. if (decodeResult != null) await Windows.System.Launcher.LaunchUriAsync(new Uri(decodeResult.Text)); } catch (ArgumentNullException ane) { System.Diagnostics.Debug.WriteLine(ane.ToString()); } catch (UriFormatException ufe) { System.Diagnostics.Debug.WriteLine(ufe.ToString()); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Timer tick exception: {0}!", ex); } }
得到的Result包含兩個重要的屬性: Text和BarcodeFormat。其中,Text就是相關Barcode表示的文本信息,而BarcodeFormat則是對應的編碼方式。你可能會問,知道內容就好了,要編碼方式有什么用?這里有個問題是,同樣的一段文本信息(尤其是純數字信息)在不同的編碼方式下可能會有不同的含義(比如兩種完全不同的商品)。
解析內容
如同前面所說,Barcode可以表示各種各樣的信息,可能是“Hello UWP!”這樣的純文本,也可能是圖書的ISBN編碼,或者是一個網絡上的URL連接。這里,我們可以通過編碼類型來判斷,因為不同的編碼類型應用場景不一樣嘛,許多一維碼根本就不支持非數字文本。此外,ZXing也為我們提供的方便的接口(NuGet上的ZXing.Net並沒有),能標識出文本的具體內容:
ParsedResult parsedResult = ResultParser.parseResult(result);
parsedResult包含以下幾種信息:

// // Summary: // Represents the type of data encoded by a barcode -- from plain text, to a URI, // to an e-mail address, etc. public enum ParsedResultType { ADDRESSBOOK = 0, EMAIL_ADDRESS = 1, PRODUCT = 2, URI = 3, TEXT = 4, GEO = 5, TEL = 6, SMS = 7, CALENDAR = 8, WIFI = 9, ISBN = 10, VIN = 11 }
后續工作
有了以上的內容,我們就可以對信息作進一步的處理,這就需要依賴於第三方服務提供的API接口了。
快遞:
“快遞100”為用戶提供了一個非常方便的頁面,通過快遞條碼就可以輕松查詢到快遞信息。
http://m.kuaidi100.com/result.jsp?nu={0}
如果想要自定義頁面,則推薦使用其API: http://www.kuaidi100.com/openapi/
商品:
亞馬遜為其網站的商品提供了商品搜索的API,通過提供條碼Id及其類型,則可以查詢到相應商品信息。
在ItemLookup頁面中,填寫一些查詢的基本信息,Marketplace可供用戶選擇查詢的數據源,webservices.amazon.com為美國的市場,中國市場可以選擇webservices.amazon.cn。下面的三個參數需要用戶注冊亞馬遜的AWS服務(注冊過程相當復雜╮(╯_╰)╭)。
在ItemLookup的過程,設置ItemId(code信息)和IdType(這里可以選擇ASIN、SKU、UPC、EAN、ISBN),然后點擊Run request就可以生成Request請求的URL,並且能獲取到響應的服務器Response——一個xml文檔,包含商品的各種信息。
Signed Request URL:
http://webservices.amazon.com/onca/xml?AWSAccessKeyId=********************&AssociateTag=************&IdType=UPC&ItemId=431604028525&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp=2016-05-30T12%3A49%3A51.000Z&Signature=**********************************************
Response:

<?xml version="1.0" ?> <ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01"> <OperationRequest> <HTTPHeaders> <Header Name="UserAgent" Value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586"></Header> </HTTPHeaders> <RequestId>f90faa33-3fb2-4fd7-a885-abe33ea6967f</RequestId> <Arguments> <Argument Name="AWSAccessKeyId" Value="AKIAIZNMTNCCU6OFZG4A"></Argument> <Argument Name="AssociateTag" Value="************"></Argument> <Argument Name="IdType" Value="UPC"></Argument> <Argument Name="ItemId" Value="431604028525"></Argument> <Argument Name="Operation" Value="ItemLookup"></Argument> <Argument Name="ResponseGroup" Value="Images,ItemAttributes,Offers"></Argument> <Argument Name="SearchIndex" Value="All"></Argument> <Argument Name="Service" Value="AWSECommerceService"></Argument> <Argument Name="Timestamp" Value="2016-05-30T12:49:51.000Z"></Argument> <Argument Name="Signature" Value="********************************************"></Argument> </Arguments> <RequestProcessingTime>0.1724468780000000</RequestProcessingTime> </OperationRequest> <Items> <Request> <IsValid>True</IsValid> <ItemLookupRequest> <IdType>UPC</IdType> <ItemId>431604028525</ItemId> <ResponseGroup>Images</ResponseGroup> <ResponseGroup>ItemAttributes</ResponseGroup> <ResponseGroup>Offers</ResponseGroup> <SearchIndex>All</SearchIndex> <VariationPage>All</VariationPage> </ItemLookupRequest> </Request> <Item> <ASIN>B008BO4D9G</ASIN> <DetailPageURL>http://www.amazon.com/Nature-Made-Pharmacist-Recommended-Concentrate/dp/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB008BO4D9G</DetailPageURL> <ItemLinks> <ItemLink> <Description>Technical Details</Description> <URL>http://www.amazon.com/Nature-Made-Pharmacist-Recommended-Concentrate/dp/tech-data/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>Add To Baby Registry</Description> <URL>http://www.amazon.com/gp/registry/baby/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>Add To Wedding Registry</Description> <URL>http://www.amazon.com/gp/registry/wedding/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>Add To Wishlist</Description> <URL>http://www.amazon.com/gp/registry/wishlist/add-item.html%3Fasin.0%3DB008BO4D9G%26SubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>Tell A Friend</Description> <URL>http://www.amazon.com/gp/pdp/taf/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>All Customer Reviews</Description> <URL>http://www.amazon.com/review/product/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> <ItemLink> <Description>All Offers</Description> <URL>http://www.amazon.com/gp/offer-listing/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</URL> </ItemLink> </ItemLinks> <ImageSets> <ImageSet Category="swatch"> <SwatchImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL30_.jpg</URL> <Height Units="pixels">30</Height> <Width Units="pixels">15</Width> </SwatchImage> <SmallImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">37</Width> </SmallImage> <ThumbnailImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">37</Width> </ThumbnailImage> <TinyImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL110_.jpg</URL> <Height Units="pixels">110</Height> <Width Units="pixels">54</Width> </TinyImage> <MediumImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL._SL160_.jpg</URL> <Height Units="pixels">160</Height> <Width Units="pixels">79</Width> </MediumImage> <LargeImage> <URL>http://ecx.images-amazon.com/images/I/51j%2BGzAmXTL.jpg</URL> <Height Units="pixels">500</Height> <Width Units="pixels">247</Width> </LargeImage> </ImageSet> <ImageSet Category="variant"> <SwatchImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL30_.jpg</URL> <Height Units="pixels">30</Height> <Width Units="pixels">19</Width> </SwatchImage> <SmallImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">48</Width> </SmallImage> <ThumbnailImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">48</Width> </ThumbnailImage> <TinyImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL110_.jpg</URL> <Height Units="pixels">110</Height> <Width Units="pixels">71</Width> </TinyImage> <MediumImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L._SL160_.jpg</URL> <Height Units="pixels">160</Height> <Width Units="pixels">103</Width> </MediumImage> <LargeImage> <URL>http://ecx.images-amazon.com/images/I/51C8Vnbv71L.jpg</URL> <Height Units="pixels">500</Height> <Width Units="pixels">321</Width> </LargeImage> </ImageSet> <ImageSet Category="variant"> <SwatchImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL30_.jpg</URL> <Height Units="pixels">30</Height> <Width Units="pixels">22</Width> </SwatchImage> <SmallImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">56</Width> </SmallImage> <ThumbnailImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL75_.jpg</URL> <Height Units="pixels">75</Height> <Width Units="pixels">56</Width> </ThumbnailImage> <TinyImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL110_.jpg</URL> <Height Units="pixels">110</Height> <Width Units="pixels">82</Width> </TinyImage> <MediumImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL._SL160_.jpg</URL> <Height Units="pixels">160</Height> <Width Units="pixels">120</Width> </MediumImage> <LargeImage> <URL>http://ecx.images-amazon.com/images/I/31m-odZf5HL.jpg</URL> <Height Units="pixels">500</Height> <Width Units="pixels">375</Width> </LargeImage> </ImageSet> </ImageSets> <ItemAttributes> <Binding>Health and Beauty</Binding> <Brand>Nature Made</Brand> <CatalogNumberList> <CatalogNumberListElement>474911</CatalogNumberListElement> </CatalogNumberList> <EAN>0031604028527</EAN> <EANList> <EANListElement>0031604028527</EANListElement> <EANListElement>0783318987897</EANListElement> <EANListElement>0431604028525</EANListElement> </EANList> <Feature>USP VERIFIED - United States Pharmacopeia (USP) sets standards for medicines, food ingredients, and dietary supplements worldwide. Nature Made was the first supplement product to be verified by USP, including fish oil supplements.</Feature> <Feature>FOOD EQUIVALENT - Two fish oil pills contain the same amount of omega-3 fatty acids of two servings of fish.</Feature> <Feature>SOURCE AND PURITY - Comes from deep ocean water fish (NOT FARM RAISED) and state-of-the-art purification processes remove mercury. Omega-3 fish oil helps support a healthy heart.</Feature> <Feature>2 BOTTLES OF 200 GEL TABS EACH -There are 200 fish oil capsules in each of two bottles, for a total of 400 softgels.</Feature> <Feature>HIGH QUANTITY DOSAGE - Nature Made Fish Oil daily suggested usage contains 2,400 mg of fish oil with 720 mg of Omega-3 Fatty Acids (including 360 mg EPA and 240 mg DHA).</Feature> <IsAdultProduct>0</IsAdultProduct> <ItemDimensions> <Height Units="hundredths-inches">313</Height> <Length Units="hundredths-inches">613</Length> <Weight Units="hundredths-pounds">174</Weight> <Width Units="hundredths-inches">625</Width> </ItemDimensions> <Label>Nature Made</Label> <Manufacturer>Nature Made</Manufacturer> <MPN>474911</MPN> <NumberOfItems>1</NumberOfItems> <PackageDimensions> <Height Units="hundredths-inches">320</Height> <Length Units="hundredths-inches">630</Length> <Weight Units="hundredths-pounds">180</Weight> <Width Units="hundredths-inches">620</Width> </PackageDimensions> <PackageQuantity>1</PackageQuantity> <PartNumber>474911</PartNumber> <ProductGroup>Health and Beauty</ProductGroup> <ProductTypeName>HEALTH_PERSONAL_CARE</ProductTypeName> <Publisher>Nature Made</Publisher> <Size>400 Softgels</Size> <Studio>Nature Made</Studio> <Title>Nature Made Fish Oil (400 Softgels) Pharmacist Recommended Fish Oil Pills (2400mg Fish Oil Concentrate, 720mg of Omega 3 Fatty Acids, 360mg EPA, 240 mg DHA)</Title> <UPC>431604028525</UPC> <UPCList> <UPCListElement>431604028525</UPCListElement> <UPCListElement>783318987897</UPCListElement> <UPCListElement>031604028527</UPCListElement> </UPCList> </ItemAttributes> <OfferSummary> <LowestNewPrice> <Amount>1560</Amount> <CurrencyCode>USD</CurrencyCode> <FormattedPrice>$15.60</FormattedPrice> </LowestNewPrice> <TotalNew>64</TotalNew> <TotalUsed>0</TotalUsed> <TotalCollectible>0</TotalCollectible> <TotalRefurbished>0</TotalRefurbished> </OfferSummary> <Offers> <TotalOffers>1</TotalOffers> <TotalOfferPages>1</TotalOfferPages> <MoreOffersUrl>http://www.amazon.com/gp/offer-listing/B008BO4D9G%3FSubscriptionId%3DAKIAIZNMTNCCU6OFZG4A%26tag%3Dfreshomer-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D386001%26creativeASIN%3DB008BO4D9G</MoreOffersUrl> <Offer> <OfferAttributes> <Condition>New</Condition> </OfferAttributes> <OfferListing> <OfferListingId>lt2bT68NjTRG7AuG%2FAAqcBmiJtLextibUqq62er5gQHN%2FtsGphHchT6YZGwo9DRl4CDw8UuCEQki2TAilIIVkKZ03DwP194gQLXxDlAXT%2BvPLPifatvCMnSk9skoDe%2FETTBJg3o7sdO%2B%2FevV0UWM6Q%3D%3D</OfferListingId> <Price> <Amount>2135</Amount> <CurrencyCode>USD</CurrencyCode> <FormattedPrice>$21.35</FormattedPrice> </Price> <Availability>Usually ships in 24 hours</Availability> <AvailabilityAttributes> <AvailabilityType>now</AvailabilityType> <MinimumHours>0</MinimumHours> <MaximumHours>0</MaximumHours> </AvailabilityAttributes> <IsEligibleForSuperSaverShipping>0</IsEligibleForSuperSaverShipping> <IsEligibleForPrime>1</IsEligibleForPrime> </OfferListing> </Offer> </Offers> </Item> </Items> </ItemLookupResponse>
當然,這只是Amazon為我們提供的一個開發工具,在真正開發過程中,需要用code來構造Amazon的數據請求。
一些數據常量:

private const string AWS_ACCESS_KEY_ID = "********************"; private const string AWS_SECRET_KEY = "****************************************"; private const string AWS_ASSOCIATE_TAG = "************"; private const string FORMAT_SORTABLE_TIME = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000Z'"; private static readonly string HASH_ALGORITHM_NAME = MacAlgorithmNames.HmacSha256; private const string ENDPOINT_ITEM_SEARCH_BY_PRODUCT_ID = "http://webservices.amazon.com/onca/xml?AWSAccessKeyId={0}&AssociateTag={1}&IdType={2}&ItemId={3}&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp={4}&Signature={5}"; private const string FORMAT_STRING_TO_SIGN = "GET\nwebservices.amazon.com\n/onca/xml\nAWSAccessKeyId={0}&AssociateTag={1}&IdType={2}&ItemId={3}&Operation=ItemLookup&ResponseGroup=Images%2CItemAttributes%2COffers&SearchIndex=All&Service=AWSECommerceService&Timestamp={4}";
通過ItemId和IdType獲取商品信息:

public static async Task<AmazonItem> GetProductsById(String id, String idType) { try { String time = DateTime.Now.ToUniversalTime().ToString(FORMAT_SORTABLE_TIME); String stringToSign = String.Format(FORMAT_STRING_TO_SIGN, AWS_ACCESS_KEY_ID, AWS_ASSOCIATE_TAG, idType, id, WebUtility.UrlEncode(time)); IBuffer buffMsg; CryptographicKey hmacKey; IBuffer buffHMAC; String hmac = createHMAC(stringToSign, HASH_ALGORITHM_NAME, AWS_SECRET_KEY, out buffMsg, out hmacKey, out buffHMAC); String url = String.Format(ENDPOINT_ITEM_SEARCH_BY_PRODUCT_ID, AWS_ACCESS_KEY_ID, AWS_ASSOCIATE_TAG, idType, id, WebUtility.UrlEncode(time), WebUtility.UrlEncode(hmac)); HttpClient httpClient = new HttpClient(); HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, new Uri(url)); req.Headers.AcceptEncoding.Clear(); HttpResponseMessage resp = await httpClient.SendRequestAsync(req); String responseStr = ""; if (resp.IsSuccessStatusCode) { IBuffer buf = await resp.Content.ReadAsBufferAsync(); responseStr = Encoding.UTF8.GetString(buf.ToArray()); } if (String.IsNullOrEmpty(responseStr)) return null; //Get data form xml string. LookupResponse response = null; try { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(responseStr))) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(LookupResponse)); response = xmlSerializer.Deserialize(stream) as LookupResponse; } } catch (Exception) { return null; } if (response == null || response.Items == null || response.Items.Count <= 0) return null; return response.Items[0]; } catch { return null; } }
中間有一個簽名的過程需要用到HMAC的方法:

private static String createHMAC(String strMsg, String strAlgName, String key, out IBuffer buffMsg, out CryptographicKey hmacKey, out IBuffer buffMAC) { MacAlgorithmProvider objMacProv = MacAlgorithmProvider.OpenAlgorithm(strAlgName); String strNameUsed = objMacProv.AlgorithmName; BinaryStringEncoding encoding = BinaryStringEncoding.Utf8; buffMsg = CryptographicBuffer.ConvertStringToBinary(strMsg, encoding); IBuffer buffKeyMaterail = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8); hmacKey = objMacProv.CreateKey(buffKeyMaterail); buffMAC = CryptographicEngine.Sign(hmacKey, buffMsg); return CryptographicBuffer.EncodeToBase64String(buffMAC); }
經過這些過程,就可以拿到Amazon的數據了,至於sample code中的LookupResponse如何構造,請參考AWS API以及Response返回數據。
后記
關於Barcode的處理還要看實際的應用場景,本文只是通過舉例提到針對某些場景的處理方式,歡迎大家多多交流經驗。
關於淘寶是否有對外開放的API,我本人並沒有調研或者使用過,如果有的話,希望大家分享一下開發經驗,謝謝!