Paypal 空指针异常 nvp.get("ACK") Java

Posted

技术标签:

【中文标题】Paypal 空指针异常 nvp.get("ACK") Java【英文标题】:Paypal Null Pointer Exception nvp.get("ACK") Java 【发布时间】:2014-09-12 11:54:03 【问题描述】:

我整天都在为这个看似简单的集成而苦苦挣扎。我真的希望你能帮助我。

我需要在我的 Java webapp 中使用 PayPal 快速结账。我只需要下一个订单并将客户重定向到 PayPal 页面。

主页运行良好,但是当我尝试查看时,我得到了 NullPointerException。 NullPointerException 在我的 Checkout 类的第 36 行被抛出。当我尝试获取 ACK 时调用它。

我整天都在努力解决这个问题。

不确定这是否相关: 我创建了第二个项目,tapestry5 项目并使用了 Rest SDK,但当我尝试调用 setExpressCheckoutResponse.getAck() 时仍然出现异常。我发现该项目中引发异常的行是 service.setExpressCheckout(setExpressCheckoutReq);

如果您知道我该如何解决这个问题,请帮助我查看任何有关带有 servlet 的 paypal hello world 的教程或我可以查看的任何资源。

这是我一直在尝试的代码:

我的 web.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>Integration Wizard</display-name>
    <description></description>

    <servlet>
        <servlet-name>Checkout</servlet-name>
        <servlet-class>Checkout</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Checkout</servlet-name>
        <url-pattern>/checkout</url-pattern>
    </servlet-mapping>

 <servlet>
        <servlet-name>OrderConfirm</servlet-name>
        <servlet-class>OrderConfirm</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>OrderConfirm</servlet-name>
        <url-pattern>/orderconfirm</url-pattern>
    </servlet-mapping>

     <servlet>
        <servlet-name>Cancel</servlet-name>
        <servlet-class>Cancel</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Cancel</servlet-name>
        <url-pattern>/cancel</url-pattern>
    </servlet-mapping>



    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
    </servlet-mapping>
</web-app>  

我的 HelloWorld.java(主页)

public class HelloWorld extends HttpServlet 

  private String message;

  public void init() throws ServletException 
      message = "Hello World";
  

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
      response.setContentType("text/html");

      PrintWriter out = response.getWriter();
      out.println("");

      out.println("<!-- INFO: The post URL \"checkout.java\" is invoked when clicked on \"Pay with PayPal\" button.-->");

      out.println("<form action='/1/checkout' METHOD='POST'>");
      out.println("  <input type='image' name='paypal_submit' id='paypal_submit'  src='https://www.paypal.com/en_US/i/btn/btn_dg_pay_w_paypal.gif' border='0' align='top' alt='Pay with PayPal'/>");
      out.println("</form>");

      out.println("<!-- Add Digital goods in-context experience. Ensure that this script is added before the closing of html body tag -->");

      out.println("<script src='https://www.paypalobjects.com/js/external/dg.js' type='text/javascript'></script>");

      out.println("<script>");

      out.println("var dg = new PAYPAL.apps.DGFlow(");
      out.println("");
      out.println("trigger: 'paypal_submit',");
      out.println("expType: 'instant'");
       out.println("//PayPal will decide the experience type for the buyer based on his/her 'Remember me on your computer' option.");
      out.println(");");

      out.println("</script>");
  

  public void destroy() 
  

我的 Checkout.java(这里 NullPointerException 在第 36 行抛出)

public class Checkout extends HttpServlet 

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException 


        String paymentAmount = "15.00";

        String returnURL = "localhost:8080/1/HelloWorld";

        String cancelURL = "localhost:8080/1/HelloWorld";

        Map item = new HashMap();
        item.put("name", "item name");
        item.put("amt", paymentAmount);
        item.put("qty", "1");

        PaypalFunctions ppf = new PaypalFunctions();
        HashMap nvp = ppf.setExpressCheckout(paymentAmount, returnURL,
                cancelURL, item);
        String strAck = nvp.get("ACK").toString();

        if (strAck != null && strAck.equalsIgnoreCase("Success")) 

            // ' Redirect to paypal.com
            String redirectURL = "https://www.sandbox.paypal.com/incontext?token="
                    + nvp.get("TOKEN").toString();

            response.sendRedirect(redirectURL);
         else 
            // Display a user friendly Error on the page using any of the
            // following error information returned by PayPal

            String ErrorCode = nvp.get("L_ERRORCODE0").toString();
            String ErrorShortMsg = nvp.get("L_SHORTMESSAGE0").toString();
            String ErrorLongMsg = nvp.get("L_LONGMESSAGE0").toString();
            String ErrorSeverityCode = nvp.get("L_SEVERITYCODE0").toString();
        
    

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException 
        doGet(request, response);
    


我的 PaypalFunctions.java

public class PaypalFunctions 
    private String gv_APIUserName;
    private String gv_APIPassword;
    private String gv_APISignature;

    private String gv_APIEndpoint;
    private String gv_BNCode;

    private String gv_Version;
    private String gv_nvpHeader;
    private String gv_ProxyServer;
    private String gv_ProxyServerPort;
    private int gv_Proxy;
    private boolean gv_UseProxy;
    private String PAYPAL_URL;

    public PaypalFunctions() 

        gv_APIUserName = "dusan.stanojevic95-facilitator_api1.gmail.com";
        gv_APIPassword = "1405890612";
        gv_APISignature = "AexbutlMdUCD618gs-q4m-DJpUxEAoU-uNDtNNLAb47Su-QoOlNbIjeo";

        boolean bSandbox = true;

        String PAYPAL_DG_URL = null;
        if (bSandbox == true) 
            gv_APIEndpoint = "https://api-3t.sandbox.paypal.com/nvp";
            PAYPAL_URL = "https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=";
            PAYPAL_DG_URL = "https://www.sandbox.paypal.com/incontext?token=";
         else 
            gv_APIEndpoint = "https://api-3t.paypal.com/nvp";
            PAYPAL_URL = "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=";
            PAYPAL_DG_URL = "https://www.paypal.com/incontext?token=";
        

        String HTTPREQUEST_PROXYSETTING_SERVER = "";
        String HTTPREQUEST_PROXYSETTING_PORT = "";
        boolean USE_PROXY = false;

        gv_Version = "84";

        // WinObjHttp Request proxy settings.
        gv_ProxyServer = HTTPREQUEST_PROXYSETTING_SERVER;
        gv_ProxyServerPort = HTTPREQUEST_PROXYSETTING_PORT;
        gv_Proxy = 2; // 'setting for proxy activation
        gv_UseProxy = USE_PROXY;

    

    /*********************************************************************************
     * SetExpressCheckout: Function to perform the SetExpressCheckout API call
     * 
     * Inputs: paymentAmount: Total value of the purchase currencyCodeType:
     * Currency code value the PayPal API paymentType: 'Sale' for Digital Goods
     * returnURL: the page where buyers return to after they are done with the
     * payment review on PayPal cancelURL: the page where buyers return to when
     * they cancel the payment review on PayPal
     * 
     * Output: Returns a HashMap object containing the response from the server.
     *********************************************************************************/
    public HashMap setExpressCheckout(String paymentAmount, String returnURL,
            String cancelURL, Map item) 

        /*
         * '------------------------------------ ' The currencyCodeType and
         * paymentType ' are set to the selections made on the Integration
         * Assistant '------------------------------------
         */

        String currencyCodeType = "USD";
        String paymentType = "Sale";

        /*
         * Construct the parameter string that describes the PayPal payment the
         * varialbes were set in the web form, and the resulting string is
         * stored in $nvpstr
         */
        String nvpstr = "&PAYMENTREQUEST_0_AMT=" + paymentAmount
                + "&PAYMENTREQUEST_0_PAYMENTACTION=" + paymentType
                + "&RETURNURL=" + URLEncoder.encode(returnURL) + "&CANCELURL="
                + URLEncoder.encode(cancelURL)
                + "&PAYMENTREQUEST_0_CURRENCYCODE=" + currencyCodeType
                + "&REQCONFIRMSHIPPING=0" + "&NOSHIPPING=1"
                + "&L_PAYMENTREQUEST_0_NAME0=" + item.get("name")
                + "&L_PAYMENTREQUEST_0_AMT0=" + item.get("amt")
                + "&L_PAYMENTREQUEST_0_QTY0=" + item.get("qty")
                + "&L_PAYMENTREQUEST_0_ITEMCATEGORY0=Digital";

        /*
         * Make the call to PayPal to get the Express Checkout token If the API
         * call succeded, then redirect the buyer to PayPal to begin to
         * authorize payment. If an error occured, show the resulting errors
         */

        HashMap nvp = httpcall("SetExpressCheckout", nvpstr);

        String strAck = nvp.get("ACK").toString();
        if (strAck != null && strAck.equalsIgnoreCase("Success")) 

            return nvp;
        

        return null;
    

    /*********************************************************************************
     * GetShippingDetails: Function to perform the GetExpressCheckoutDetails API
     * call
     * 
     * Inputs: None
     * 
     * Output: Returns a HashMap object containing the response from the server.
     *********************************************************************************/
    public HashMap getPaymentDetails(String token) 
        /*
         * Build a second API request to PayPal, using the token as the ID to
         * get the details on the payment authorization
         */

        String nvpstr = "&TOKEN=" + token;

        /*
         * Make the API call and store the results in an array. If the call was
         * a success, show the authorization details, and provide an action to
         * complete the payment. If failed, show the error
         */

        HashMap nvp = httpcall("GetExpressCheckoutDetails", nvpstr);
        String strAck = nvp.get("ACK").toString();

        if (strAck != null
                && (strAck.equalsIgnoreCase("Success") || strAck
                        .equalsIgnoreCase("SuccessWithWarning"))) 

            return nvp;
        
        return null;
    

    /*********************************************************************************
     * ConfirmPayment: Function to perform the DoExpressCheckoutPayment API call
     * 
     * Inputs: None
     * 
     * Output: Returns a HashMap object containing the response from the server.
     *********************************************************************************/
    public HashMap confirmPayment(String token, String payerID,
            String finalPaymentAmount, String serverName, Map item) 

        /*
         * '------------------------------------ ' The currencyCodeType and
         * paymentType ' are set to the selections made on the Integration
         * Assistant '------------------------------------
         */
        String currencyCodeType = "USD";
        String paymentType = "Sale";

        /*
         * '----------------------------------------------------------------------------
         * '---- Use the values stored in the session from the previous SetEC
         * call
         * '----------------------------------------------------------------------------
         */
        String nvpstr = "&TOKEN=" + token + "&PAYERID=" + payerID
                + "&PAYMENTREQUEST_0_PAYMENTACTION=" + paymentType + "&PAYMENTREQUEST_0_AMT="
                + finalPaymentAmount;

        nvpstr = nvpstr + "&PAYMENTREQUEST_0_CURRENCYCODE=" + currencyCodeType + "&IPADDRESS="
                + serverName;

        nvpstr = nvpstr + "&L_PAYMENTREQUEST_0_NAME0=" + item.get("name")
                + "&L_PAYMENTREQUEST_0_AMT0=" + item.get("amt")
                + "&L_PAYMENTREQUEST_0_QTY0=" + item.get("qty")
                + "&L_PAYMENTREQUEST_0_ITEMCATEGORY0=Digital";

        /*
         * Make the call to PayPal to finalize payment If an error occured, show
         * the resulting errors
         */
        HashMap nvp = httpcall("DoExpressCheckoutPayment", nvpstr);
        String strAck = nvp.get("ACK").toString();
        if (strAck != null
                && (strAck.equalsIgnoreCase("Success") || strAck
                        .equalsIgnoreCase("SuccessWithWarning"))) 
            return nvp;
        
        return null;

    

    /*********************************************************************************
     * httpcall: Function to perform the API call to PayPal using API signature @
     * methodName is name of API method. @ nvpStr is nvp string. returns a NVP
     * string containing the response from the server.
     *********************************************************************************/
    public HashMap httpcall(String methodName, String nvpStr) 

        String version = "2.3";
        String agent = "Mozilla/4.0";
        String respText = "";
        HashMap nvp = null; // lhuynh not used?

        // deformatNVP( nvpStr );
        String encodedData = "METHOD=" + methodName + "&VERSION=" + gv_Version
                + "&PWD=" + gv_APIPassword + "&USER=" + gv_APIUserName
                + "&SIGNATURE=" + gv_APISignature + nvpStr;

        try 
            URL postURL = new URL(gv_APIEndpoint);
            HttpURLConnection conn = (HttpURLConnection) postURL
                    .openConnection();

            // Set connection parameters. We need to perform input and output,
            // so set both as true.
            conn.setDoInput(true);
            conn.setDoOutput(true);

            // Set the content type we are POSTing. We impersonate it as
            // encoded form data
            conn.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");
            conn.setRequestProperty("User-Agent", agent);

            // conn.setRequestProperty( "Content-Type", type );
            conn.setRequestProperty("Content-Length",
                    String.valueOf(encodedData.length()));
            conn.setRequestMethod("POST");

            // get the output stream to POST to.
            DataOutputStream output = new DataOutputStream(
                    conn.getOutputStream());
            output.writeBytes(encodedData);
            output.flush();
            output.close();

            // Read input from the input stream.
            DataInputStream in = new DataInputStream(conn.getInputStream());
            int rc = conn.getResponseCode();
            if (rc != -1) 
                BufferedReader is = new BufferedReader(new InputStreamReader(
                        conn.getInputStream()));
                String _line = null;
                while (((_line = is.readLine()) != null)) 
                    respText = respText + _line;
                
                nvp = deformatNVP(respText);
            
            return nvp;
         catch (IOException e) 
            // handle the error here
            return null;
        
    

    /*********************************************************************************
     * deformatNVP: Function to break the NVP string into a HashMap pPayLoad is
     * the NVP string. returns a HashMap object containing all the name value
     * pairs of the string.
     *********************************************************************************/
    public HashMap deformatNVP(String pPayload) 
        HashMap nvp = new HashMap();
        StringTokenizer stTok = new StringTokenizer(pPayload, "&");
        while (stTok.hasMoreTokens()) 
            StringTokenizer stInternalTokenizer = new StringTokenizer(
                    stTok.nextToken(), "=");
            if (stInternalTokenizer.countTokens() == 2) 
                String key = URLDecoder.decode(stInternalTokenizer.nextToken());
                String value = URLDecoder.decode(stInternalTokenizer
                        .nextToken());
                nvp.put(key.toUpperCase(), value);
            
        
        return nvp;
    

    /*********************************************************************************
     * RedirectURL: Function to redirect the user to the PayPal site token is
     * the parameter that was returned by PayPal returns a HashMap object
     * containing all the name value pairs of the string.
     *********************************************************************************/
    public void RedirectURL(HttpServletResponse response, String token) 
        String payPalURL = PAYPAL_URL + token;

        // response.sendRedirect( payPalURL );
        response.setStatus(302);
        response.setHeader("Location", payPalURL);
        response.setHeader("Connection", "close");
    

    // end class

【问题讨论】:

你能告诉我们Checkout类的第72行是哪一行吗? 是这一行吗:String strAck = nvp.get("ACK").toString(); - 如果是这样,要么 nvp 为空,要么在映射中找不到“ACK”键的值。可以调试看看吗? 非常抱歉,它在第 36 行 String strAck = nvp.get("ACK").toString();我检查过,nvp 为空。我考虑过我没有正确设置我的测试 PayPal 的可能性,我看不出我可能在哪里犯了错误,但这可能是导致这种奇怪的错误行为的原因吗? 【参考方案1】:

我无法解决我的问题,但是我能够完成我的项目。我删除了所有代码并尝试了以下示例项目:

https://github.com/paypal/merchant-sdk-java.

项目成功了,所以我只是更改了值,删除了所有不必要的代码并重写了该项目以在我的 Tapestry5 应用程序中工作。

这些天我会回去找出为什么以前使用的代码不起作用,我在想糟糕的 maven 依赖项,但我们会看到。

感谢大家的帮助。

【讨论】:

【参考方案2】:

请更改以下变量:

String returnURL = "localhost:8080/1/HelloWorld";
String cancelURL = "localhost:8080/1/HelloWorld";

String returnURL = "http://localhost:8080/1/HelloWorld";
String cancelURL = "http://localhost:8080/1/HelloWorld";

问题:无法验证 Url,因为它没有“http://”

【讨论】:

以上是关于Paypal 空指针异常 nvp.get("ACK") Java的主要内容,如果未能解决你的问题,请参考以下文章

Collectors.toMap空指针异常

java中的空指针异常怎么解决

SpringBoot配置拦截器空指针异常

java hashmap空指针异常

java的equals提示空指针异常

我的构造函数里面报空指针异常了!求大神帮忙