0

I'm using the sandbox "Notification Serial Number" node. I'm acknowledging fine and getting the serial-number. When I go to get the message as described in "Requesting Notifications", I get a response body of two letters: OK .. Instead I need the the notification message.

https://developers.google.com/checkout/developer/Google_Checkout_HTML_API_Notification_API#responding_to_notifications

Here is my code:

public static enum Account {
    sandbox, production;
    String merchantId, merchantKey, url;
    static {
        sandbox.merchantId = "9999999999999999";
        sandbox.merchantKey = "Ran0mUPPERlowerCaArAcTeRs";
        sandbox.url = "https://sandbox.google.com/checkout/";
        production.merchantId = "...";
        production.merchantKey = "...";
        production.url = "https://checkout.google.com/";
    }
}

// https://developers.google.com/checkout/developer/Google_Checkout_HTML_API_Notification_API
    //notification api entry-point
    public static void sandbox() throws IOException, GoogleCheckoutException,
            ParseException {

        String sn = request.params.get("serial-number");
        if (sn == null)
            error();//playframework sends an error response code

        //GoogleCheckoutApi.Account.sandbox is an enum with my information
        //try to process first (or exception), then confirm below
        processNotification(GoogleCheckoutApi.Account.sandbox, sn);

        // confirm request
        // https://developers.google.com/checkout/developer/Google_Checkout_HTML_API_Notification_API#responding_to_notifications

        String s = "<notification-acknowledgment xmlns=\"http://checkout.google.com/schema/2\" serial-number=\""
                + sn + "\" />";
        response.out.write(s.getBytes());
    }

static final String URL_REPORTS_FORM = "api/checkout/v2/reportsForm/Merchant/";

public static void processNotification(Account account, final String sn)
            throws IOException, GoogleCheckoutException, ParseException {

        System.out.println(new Date() + "\tGoogle Notification IN\t" + sn);
        Map<String, String> parms = new HashMap<String, String>() {
            {
                put("_type", "notification-history-request");
                put("serial-number", sn);

            }
        };
        HttpURLConnection c = requestPost(account.url + URL_REPORTS_FORM
                + account.merchantId, authProperties(account), parms, null);

        try {
            if (c.getResponseCode() != 200)
                throw new GoogleCheckoutException("Error Response Code "
                        + c.getResponseCode() + " from google API\n"
                        + c.getResponseMessage());

            handleResponse(account, c.getResponseMessage());

        } finally {
            c.disconnect();
        }
    }

private static void handleResponse(Account account, String responseMessage)
        throws IOException, ParseException {

    if (responseMessage.equals("OK")) {
        System.out.println(new Date() + "\tGoogle Notification IN\tOK");
        return;
    }

    //...other code to log and save the message...
}


//...requestPost seems to work fine.  I know I'm authenticating correctly.
public static HttpURLConnection requestPost(String requestURL,
        Map<String, String> properties, Map<String, String> params,
        String content) throws IOException {
    // derived from
    // http://www.codejava.net/java-se/networking/an-http-utility-class-to-send-getpost-request
    URL url = new URL(requestURL);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    connection.setDoInput(true);
    connection.setInstanceFollowRedirects(false);
    connection.setRequestMethod("POST");
    if (properties != null)
        for (String key : properties.keySet()) {
            String value = properties.get(key);
            connection.setRequestProperty(key, value);
        }

    connection.setUseCaches(false);
    if (params != null && params.size() > 0) {
        StringBuffer requestParams = new StringBuffer();
        for (String key : params.keySet()) {
            String value = params.get(key);
            requestParams.append(URLEncoder.encode(key, "UTF-8"));
            if (value != null)
                requestParams.append("=").append(
                        URLEncoder.encode(value, "UTF-8"));

            requestParams.append("&");
        }
        // remove &
        requestParams.setLength(requestParams.length() - 1);//
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Length", String
                .valueOf(requestParams.length()));

        OutputStreamWriter writer = new OutputStreamWriter(connection
                .getOutputStream());

        writer.write(requestParams.toString());
        writer.close();
    } else if (content != null) {
        connection.setDoOutput(true);
        // sends POST data
        connection.setRequestProperty("Content-Length", String
                .valueOf(content.length()));

        OutputStreamWriter writer = new OutputStreamWriter(connection
                .getOutputStream());

        writer.write(content);
        writer.close();
    }
    return connection;
}
static final BASE64Encoder encoder = new BASE64Encoder();
private static Map<String, String> authProperties(final Account account) {
    return new HashMap<String, String>() {
        {
            put("Content-Type", "application/xml; charset=UTF-8");
            put("Accept", "application/xml; charset=UTF-8");
            put(
                    "Authorization",
                    "Basic "
                            + encoder
                                    .encode((account.merchantId + ":" + account.merchantKey)
                                            .getBytes()));
        }
    };
}

This code outputs:

Wed Mar 20 17:57:39 UTC 2013    Google Notification IN  748115991100000-00005-6
Wed Mar 20 17:57:39 UTC 2013    Google Notification IN  OK

Instead of "OK" I was expecting to see the entire message.

Kara
  • 6,115
  • 16
  • 50
  • 57
jcalfee314
  • 4,642
  • 8
  • 43
  • 75
  • Not a java guy and just curious about this comment above: `playframework sends an error response code`. What/why did u mention "playframework" - is the merchant account a "Play" (Android) account? – EdSF Mar 26 '13 at 01:20
  • playframework.org is a lot like Ruby on Rails but for Java. It removes most or perhaps all boiler-plat code (monkey code is what I call it; A monkey could do it). That is the only framework specific method so I put a comment in-case someone uses it without the framework. – jcalfee314 Mar 26 '13 at 13:44
  • Again, not a Java/Rails guy (am .Net) - AFAIK, "OK" is part of the response _header_. The response _body_ should contain the data. Treading on dangerous ground here (not a java guy), you also have a `return` on the OK check after you write out some text, wouldn't that exit the procedure (and not run the rest of the code)? – EdSF Mar 30 '13 at 22:04
  • Thanks for posting .. The OK is in the body. Also, I had no meaningful response headers. I wonder if that message is not available yet and Google just gives up and says "OK" .. The connection that received the serial number is still open. In other words, I make the history request before I close the serial number notification connection. – jcalfee314 Mar 31 '13 at 17:29

0 Answers0