2

This is a follow-up to: https://stackoverflow.com/questions/6285578/getting-started-with-asp-net-mvc3-google-checkout

Now I finally started to know what's going on with the Google Checkout API. I decided to do everything on the server side. So I wrote some code but I could not make a successful call to the API. Here's my code:

        var str = string.Format("{0}:{1}", MERCHANT_ID, MERCHANT_KEY);
        var auth = EncodeTo64(str);
        var request = WebRequest.Create("https://sandbox.google.com/checkout/api/checkout/v2/requestForm/Merchant/747839340759259");
        ((HttpWebRequest) request).Accept = "application/xml;charset=UTF-8";
        request.Headers.Add("Authorization", "Basic " + auth);
        request.ContentType = "application/xml;charset=UTF-8";
        request.Method = "POST";
        string postData = "_type=hello";
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentLength = byteArray.Length;
        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();
        // Get the response.
        WebResponse response = request.GetResponse();
        ViewData.Add("status", ((HttpWebResponse)response).StatusDescription);
        dataStream = response.GetResponseStream();
        var reader = new StreamReader(dataStream);
        string responseFromServer = reader.ReadToEnd();
        ViewData.Add("responseFromServer", responseFromServer);
        reader.Close();
        dataStream.Close();
        response.Close();
        return View();

First I was getting a 401 error, but I got that resolved. Now I keep getting The remote server returned an error: (400) Bad Request. on the line that says WebResponse response = request.GetResponse();. So it has to be something wrong with my C# code I guess?

NOTE: The HTTP post should have the following headers.

Authorization: Basic MTIzNDU2Nzg5MDpIc1lYRm9aZkhBcXlMY0NSWWVIOHFR (which is the base64 encoding of Merchant_ID:Merchant_Key

Content-Type: application/xml;charset=UTF-8

Accept: application/xml;charset=UTF-8

So any suggestion on how I could resolve this issue?

UPDATE: I think I figured out the source of the problem, but I cannot figure out how to solve it. Here's a link that explains it: This Stream Does Not Support Seek Operations

UPDATE 2: I finally got fiddler to catch the call, and here's what I found out:

REQUEST:

POST 

https://sandbox.google.com/checkout/api/checkout/v2/requestForm/Merchant/747839340759259

HTTP/1.1

Accept: application/xml;charset=UTF-8

Content-Type: application/x-www-form-urlencoded

Range: bytes=1024-

Authorization: Basic NzQ3ODM5MzQwNzU5MjU5OjVKNS1tRkpIZVBWc25hXzVFOW5mZ2c=

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)

Host: sandbox.google.com

Content-Length: 257

Expect: 100-continue

Connection: Keep-Alive


_type=checkout-shopping-cart&item_name_1=Baseball&item_description_1=White+baseball&item_currency_1=USD&item_price_1=5.99&item_quantity_1=2&item_name_2=Baseball+Glove&item_description_2=XL+Baseball+Glove&item_currency_2=USD&item_price_2=30&item_quantity_2=1

RESPONSE:

HTTP/1.1 400 Bad Request

Content-Type: application/x-www-form-urlencoded; charset=US-ASCII

Transfer-Encoding: chunked

Date: Thu, 09 Jun 2011 19:32:49 GMT

Expires: Thu, 09 Jun 2011 19:32:49 GMT

Cache-Control: private, max-age=0

X-Content-Type-Options: nosniff

X-Frame-Options: SAMEORIGIN

X-XSS-Protection: 1; mode=block

Set-Cookie: S=payments_api=GWZzws2nBZR-KMGHgKJlTQ; Expires=Thu, 09-Jun-2011 20:02:49 GMT; Path=/; Secure; HttpOnly

Server: GSE

74
_type=error&error-message=Carts+must+contain+at+least+one+item.&serial-number=c8677c3d-3e80-48e8-bd84-f01fa3b02165

0
Community
  • 1
  • 1
Kassem
  • 8,116
  • 17
  • 75
  • 116
  • 1
    Can you use fiddler and check what you're actually sending? – alexn Jun 09 '11 at 17:47
  • Heads up: You might not want to share your merchant ID (url) and merchant key (in the base64) with everyone on the Internet. – Jesse Buchanan Jun 09 '11 at 17:56
  • @alexn: Nothing showed up in fiddler... that's weird. It means that the API is not being called in the first place! Now I'm even more lost! – Kassem Jun 09 '11 at 18:06
  • If you get a 400 response it's definitely being called. Are you sure that Fiddler is capturing correctly? – alexn Jun 09 '11 at 18:09
  • @alexn: You are right. It was Fiddler not catching the calls. I've updated my post, please take a look at it. – Kassem Jun 09 '11 at 19:39
  • hey,im currently having problems with trying out the sandbox test (link you provided) and was wondering what i would need inside the form tags im using this to create it <%using(Html.Beginform(null,null,Formmethod.post,new{@action="url", @accept_charset="utf-8"}). But I would get a 503 error. any advice is very much appreciated. Thanks! – gdubs May 07 '12 at 12:25

2 Answers2

1

You state:

The HTTP post should have the following headers.

Content-Type: application/xml;charset=UTF-8

yet that is clearly not xml in your payload, and that isn't an xml header in the trace... it looks to me simply that you aren't sending the right data to the API.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • @Marc Gravell: +1! I felt there's something fishy about this. But seriously, Google has messed up their documentation big time! I've got those guidelines and code snippets from the HTML API and they clearly said those are the headers I need to send, and I should be sending name:value pairs. On the other hand, if I used the XML API, I should be sending data using XML which I'm currently doing but it's causing some problems! Btw, what should I be using instead of application/xml in order to send name:value pairs? – Kassem Jun 09 '11 at 20:38
  • @Marc Gravell: I cannot thank you enough! I finally made a successful call to the Google Checkout API using WebClient.UploadValues! :) But it returns a byte array, is there a way I could get some readable data out of it? The reason why I know it was a successful call is because I saw the expected response in Fiddler... Anway, thanks again, I really appreciate your help :) – Kassem Jun 10 '11 at 06:42
  • @Kassem - well, what does the binary look like? Your first test should be to run it through `client.Encoding.GetString(bytes)` - see what it looks like. – Marc Gravell Jun 10 '11 at 06:52
  • @Marc Gravell: This is the result of `client.Encoding.GetString(bytes)` : `_type=bye&serial-number=455dc780-53fb-40d4-a63a-6df1119f32cd` which is exactly what I'm looking for. Now, do I split on the `&` or is there a better way of doing this? Preferably getting it into any type of collection because that would make it easier to deal with... – Kassem Jun 10 '11 at 06:58
  • @Marc Gravell: Alright, I will look further into it, and if I couldn't find a better way of doing it I'll just split. Anyway, thank you for your time, I really appreciate your help :) – Kassem Jun 10 '11 at 07:05
0

This may be a dumb question, but is there a reason that you're not using Google's .NET DLL?

I realize the example on google code is for a windows form app, but the objects used to post the checkout request should work just fine from your controller.

Paul
  • 35,689
  • 11
  • 93
  • 122
  • I tried but I couldn't get it to work, probably because I'm completely new to the whole Google Checkout API. Could you provide an example of how to get started using GCheckoutV2.5.0.6 inside ASP.NET MVC? Just the initial steps because I was completely lost and there isn't really any documentation for the library which I could refer to... – Kassem Jun 09 '11 at 18:01