4
votes

I have been trying to implement the paypal IPN system in our company website. When I test my script in the IPN sandbox tool, it is validated and everything goes well, however when I move it live, the IPN returned as INVALID but the payment has been completed well. When I check the IPN history in my account, I can see this IPN message with the HTTP Response 200:

mc_gross=0.01&invoice=40&protection_eligibility=Ineligible&item_number1=&payer_id=mypayerId&tax=0.00&payment_date=08:06:52 Sep 03, 2013 PDT&payment_status=Completed&charset=windows-1252&mc_shipping=0.00&mc_handling=0.00&first_name=myName&mc_fee=0.01&notify_version=3.7&custom=18528&payer_status=verified&business=bussiness_mail&num_cart_items=1&mc_handling1=0.00&verify_sign=AJ.HL1f2A9aoBiFQCLn.3J-QkKQGAF.RVW8er5rbGJ6SsQFWBbStuRtD&payer_email=myMail&mc_shipping1=0.00&tax1=0.00&txn_id=61052338B4613440H&payment_type=instant&last_name=MySurname&item_name1=Paquete Lite&receiver_email=mybussiness_mail&payment_fee=&quantity1=1&receiver_id=SVRXVCZYE2AYC&txn_type=cart&mc_gross_1=0.01&mc_currency=EUR&residence_country=ES&transaction_subject=18528&payment_gross=&ipn_track_id=38c492cbe6257

My IPNHandler is a Java Servlet. The doPost Action is:

 @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // Java JSP
    log.error("IPN doPost " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds());

    // read post from PayPal system and add 'cmd'
    Enumeration en = request.getParameterNames();
    String str = "cmd=_notify-validate";
    while (en.hasMoreElements()) {
        String paramName = (String) en.nextElement();
        String paramValue = request.getParameter(paramName);
        paramValue = new String(paramValue.getBytes("iso-8859-1"), "utf-8");
        str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue);
    }

    boolean isSandbox = "true".equals(PropertiesManager.getProperty("signbox", "PaypalSandbox"));
    // post back to PayPal system to validate
    // NOTE: change http: to https: in the following URL to verify using SSL (for increased security).
    // using HTTPS requires either Java 1.4 or greater, or Java Secure Socket Extension (JSSE)
    // and configured for older versions.
    String url = null;
    if (isSandbox){
        url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
    }else{
        url = "https://www.paypal.com/cgi-bin/webscr";
    }
    log.error("La url de a la que redirigimos a Paypal es " + url);
    URL u = new URL(url);
    URLConnection uc = u.openConnection();
    uc.setDoOutput(true);
    uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    PrintWriter pw = new PrintWriter(uc.getOutputStream());
    pw.println(str);
    pw.close();

    BufferedReader in = new BufferedReader(
            new InputStreamReader(uc.getInputStream()));
    String res = in.readLine();
    in.close();
    log.error("Tras abrir la conexión, res es = " + res);

    // assign posted variables to local variables
    String idUser = request.getParameter("custom");
    String idCompra = request.getParameter("invoice");
    String paymentStatus = request.getParameter("payment_status");
    String paymentAmount = request.getParameter("mc_gross");
    String fee = request.getParameter("mc_fee");
    String paymentCurrency = request.getParameter("mc_currency");
    String txnId = request.getParameter("txn_id");
    String receiptId = request.getParameter("receipt_id");
    String receiverEmail = request.getParameter("receiver_email");
    String payerEmail = request.getParameter("payer_email");
    String paymentType = request.getParameter("payment_type");
    String txnType = request.getParameter("txn_type");

    if (!"instant".equals(paymentType) || !"cart".equals(txnType)) {
        log.debug("NO ES UN CART CHECKOUT. Detalles:");
        log.debug("idCompra=" + idCompra);
        log.debug("status=" + paymentStatus);
        log.debug("amount=" + paymentAmount);
        log.debug("currency=" + paymentCurrency);
        log.debug("transactionId=" + txnId);
        log.debug("receiptId=" + receiptId);
        log.debug("receiverEmail=" + receiverEmail);
        log.debug("payerEmail=" + payerEmail);
        log.debug("paymentType=" + paymentType);
        log.debug("txnType=" + txnType);

        return;
    }

    **//HERE THE RESPONSE IS INVALID IN LIVE MODE**
    if (res != null && res.equals("VERIFIED")) { //res = "VERIFIED" res = "INVALID"
        // more code not important for this issue....

Any idea? As I said, payments are completed but the IPN is sended INVALID.

2
Turn off the sandbox: boolean isSandbox = "false". Seems to be the #1 cause of sandbox = verified, live = invalid. The simple things can trip us up!Patanjali

2 Answers

1
votes

I know this is old but it might help someone else, I think you need to POST the data for validation.

According to Paypal IPN Docs:

//After receiving an IPN message from PayPal, 
//you must respond to PayPal with a POST message 
//that begins with "cmd=_notify-validate".
//Append to your message a duplicate of the 
//notification received (the same IPN fields 
//and values in the exact order you received them)

...
URL u = new URL(url);
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
uc.setRequestMethod("POST");
...
0
votes

To receive IPN message data from PayPal, your listener must follow this request-response flow:

1.Your listener listens for the HTTPS POST IPN messages that PayPal sends with each event.

2.After receiving the IPN message from PayPal, your listener returns an empty HTTP 200 response to PayPal. Otherwise, PayPal resends the IPN message.

3.Your listener sends the complete message back to PayPal using HTTPS POST.

Prefix the returned message with the cmd=_notify-validate variable, but do not change the message fields, the order of the fields, or the character encoding from the original message.

Send response messages back to PayPal:

for more info see also: https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNImplementation/#specs