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的主要内容,如果未能解决你的问题,请参考以下文章