gpt4 book ai didi

jakarta-ee - PayPal REST API未执行付款。无法将付款对象的状态从“已创建”更改为“已批准”或“已完成”

转载 作者:太空宇宙 更新时间:2023-11-03 16:18:58 25 4
gpt4 key购买 nike

我正在使用Servlet生成HTML页面,这些页面旨在使用新的REST API执行PayPal付款。我尚未能够生成状态为已批准或已创建的付款。我已经从github页面上的PaymentWithPayPalServlet.java示例中尝试了变体,并且在下面添加了最接近的变体。对于哪个对象应该接收“已批准”或“已完成”的更新状态以及何时接收,我不清楚。

尽管我在下面包括了完整的代码,但是这里是我的想法的快速分解。也许有人可以纠正我哪里出错了...

我创建了一个包含所有适当属性/属性的Payment对象。

Payment payment = new Payment();
payment.setIntent("sale");
payment.setPayer(payer);
payment.setTransactions(transactions);
payment.setRedirectUrls(redirectUrls);
Payment createdPayment = payment.create(apiContext);


现在,createdPayment对象的状态为“已创建”。在代码末尾,我将用户重定向到payPal页面,在该页面上我假设payPal将在执行之前批准付款。请注意,这与示例文件有所不同,但我不明白为什么这不起作用。

if (link.getRel().equalsIgnoreCase("approval_url")) 
{
req.setAttribute("redirectURL", link.getHref());
resp.sendRedirect(link.getHref());
}


由于payPal无法通过HTTP协议更改我的本地变量createdPayment的状态,因此我希望payPal页面重定向回我的returnURL页面,其中带有paymentID和可能附加在URL上的授权令牌。使用这两件事,我希望可以使用某种类型的静态函数调用从payPal服务器检索付款对象,例如:

String authToken=req.getParameter("token");
String paymentID=req.getParameter("paymentID");
Payment approvedPayment=Payment.getPaymentObject(authToken,paymentID);


但是,该URL没有附加任何paymentID。而是有一个payerID。此外,我所有从PayPal服务器检索状态为“已批准”或“已完成”的付款对象的尝试均失败了。基本上,我尝试了以下变化,但均无济于事:

String authToken=req.getParameter("token");
String paymentID=req.getParameter("payerID");
Payment approvedPayment=Payment.get(authToken,payerID);


如果有人可以提示我我的推理出了问题的地方,那绝对是很糟糕的。谢谢!这是我的主要servlet页面中的完整代码。注意,returnURL带您回到同一页面,在该页面中找到来自payPal的HTTP请求中包含的payerID,并正确输入主if-else语句的'if'块,这会生成一些完全无用的基本输出。还要注意,我已经将一些基本函数调用(如检索访问令牌和上下文)外包给了其他类,如AccessToken类。

public class PaymentInfoServlet2 extends HttpServlet {

private static final long serialVersionUID = 1L;

// private static final Logger LOGGER = Logger
// .getLogger(PaymentWithPayPalServlet.class);
Map<String, String> map = new HashMap<String, String>();

public void init(ServletConfig servletConfig) throws ServletException {
// ##Load Configuration
// Load SDK configuration for
// the resource. This intialization code can be
// done as Init Servlet.
InputStream is = PaymentInfoServlet2.class
.getResourceAsStream("/sdk_config.properties");
try {
PayPalResource.initConfig(is);
} catch (PayPalRESTException e) {
// LOGGER.fatal(e.getMessage());
}

}

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}

// ##Create
// Sample showing to create a Payment using PayPal
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// ###AccessToken
// Retrieve the access token from
// OAuthTokenCredential by passing in
// ClientID and ClientSecret
APIContext apiContext = null;
String accessToken = null;
try {
AccessToken access=new AccessToken(PublicUtils.getUser(),PublicUtils.getPass(),req,resp);

accessToken = access.getToken();

// ### Api Context
// Pass in a `ApiContext` object to authenticate
// the call and to send a unique request id
// (that ensures idempotency). The SDK generates
// a request id if you do not pass one explicitly.
apiContext = access.getContext();
// Use this variant if you want to pass in a request id
// that is meaningful in your application, ideally
// a order id.
/*
* String requestId = Long.toString(System.nanoTime(); APIContext
* apiContext = new APIContext(accessToken, requestId ));
*/
} catch (Exception e) {
req.setAttribute("error", e.getMessage());
}
if (req.getParameter("PayerID") != null) {
Payment payment = new Payment();
if (req.getParameter("guid") != null) {
payment.setId(map.get(req.getParameter("guid")));
}

PaymentExecution paymentExecution = new PaymentExecution();
paymentExecution.setPayerId(req.getParameter("PayerID"));
try {
payment.execute(apiContext, paymentExecution);
req.setAttribute("response", Payment.getLastResponse());
} catch (PayPalRESTException e) {
req.setAttribute("error", e.getMessage());
}
PrintWriter out=resp.getWriter();
out.println("This is the returnURL page.");
out.println("paymentID="+payment.getId());
out.println("pamentState="+payment.getState());
out.println("executedPayerID="+paymentExecution.getPayerId());
// out.println("executedTransaction: "+paymentExecution.getTransactions().get(0).toString());
} else {

// ###Details
// Let's you specify details of a payment amount.
Details details = new Details();
details.setShipping("1");
details.setSubtotal("5");
details.setTax("1");

// ###Amount
// Let's you specify a payment amount.
Amount amount = new Amount();
amount.setCurrency("USD");
// Total must be equal to sum of shipping, tax and subtotal.
amount.setTotal("7");
amount.setDetails(details);

// ###Transaction
// A transaction defines the contract of a
// payment - what is the payment for and who
// is fulfilling it. Transaction is created with
// a `Payee` and `Amount` types
Transaction transaction = new Transaction();
transaction.setAmount(amount);
transaction
.setDescription("This is the payment transaction description.");

// The Payment creation API requires a list of
// Transaction; add the created `Transaction`
// to a List
List<Transaction> transactions = new ArrayList<Transaction>();
transactions.add(transaction);

// ###Payer
// A resource representing a Payer that funds a payment
// Payment Method
// as 'paypal'
Payer payer = new Payer();
payer.setPaymentMethod("paypal");

// ###Payment
// A Payment Resource; create one using
// the above types and intent as 'sale'
Payment payment = new Payment();
payment.setIntent("sale");
payment.setPayer(payer);
payment.setTransactions(transactions);

// ###Redirect URLs
RedirectUrls redirectUrls = new RedirectUrls();
String guid = UUID.randomUUID().toString().replaceAll("-", "");
redirectUrls.setCancelUrl(req.getScheme() + "://"
+ req.getServerName() + ":" + req.getServerPort()
+ req.getContextPath() + "/CancelServlet?guid=" + guid);
redirectUrls.setReturnUrl(req.getScheme() + "://"
+ req.getServerName() + ":" + req.getServerPort()
+ req.getContextPath() + "/PaymentInfoServlet2?guid=" + guid);
payment.setRedirectUrls(redirectUrls);

// Create a payment by posting to the APIService
// using a valid AccessToken
// The return object contains the status;
try {
Payment createdPayment = payment.create(apiContext);
// LOGGER.info("Created payment with id = "
// + createdPayment.getId() + " and status = "
// + createdPayment.getState());
// ###Payment Approval Url
Iterator<Links> links = createdPayment.getLinks().iterator();
while (links.hasNext()) {
Links link = links.next();
if (link.getRel().equalsIgnoreCase("approval_url")) {
req.setAttribute("redirectURL", link.getHref());
resp.sendRedirect(link.getHref());
}
}
req.setAttribute("response", Payment.getLastResponse());
map.put(guid, createdPayment.getId());
} catch (PayPalRESTException e) {
req.setAttribute("error", e.getMessage());
}
}
req.setAttribute("request", Payment.getLastRequest());
//req.getRequestDispatcher("response.jsp").forward(req, resp);
}


}



为了回应我在下面的第一个评论者Yozha Karlov,我添加了以下内容:

好吧,我想我对此有几个反应。首先,谢谢。第二,我想也许我对我的问题还不够清楚。我对如何检索旧的付款对象(在上面名为“ createdPayment”)不感到困惑。在上面复制的完整代码中,我使用与您引用的完全相同的guid代码。这样做的一个问题是,除了将createdPayment对象的ID复制到新的空白Payment对象之外,它什么也不做。新对象的状态以及其他所有属性仍然为空白。它是一个具有ID的空白对象,仅此而已。几乎一文不值,所以我要么丢失了某些东西,要么示例servlet是完全错误的。

实际上,我的初始方法是创建一个带有静态映射的静态类,以将sessionID映射到HttpSession对象。我将为用户的浏览器会话生成一个sessionID,并将该sessID附加到payment.create()方法的redirectURLs中的cancelURL和returnURL中。然后,我将确保相关的Payment对象已附加到用户的HttpSession对象中,以便以后在returnURL servlet中进行检索。

public class SessionStore {
public static Map<String, HttpSession> map = new HashMap<String,HttpSession>();
}

and in my main servlet, called PaymentInfoServlet2, here is the relevant code that i execute before the servlet ends and the user is re-directed to the payPal pages:

HttpSession sess=req.getSession();
String sessID=sess.getId();
SessionStore.map.put(sessID, sess);

// append sessID to redirectURLs - the URLs that the payPal pages return back to
approveURL=req.getScheme() + "://"+ req.getServerName() + ":" +req.getServerPort()+ req.getContextPath() +"/ApproveServlet?sessID=" +sess.getId();
cancelURL=req.getScheme() + "://"+ req.getServerName() + ":" + req.getServerPort()+ req.getContextPath() +"/CancelServlet?sessID=" +sess.getId();
redirectUrls.setCancelUrl(cancelURL);
redirectUrls.setReturnUrl(approveURL);
payment.setRedirectUrls(redirectUrls);

// create the payment on the payPal server
Payment createdPayment = payment.create(access.getContext());

//add created Payment object to HttpSession object.
ArrayList<Payment> createdPayments=new ArrayList<Payment>();
createdPayments.add(createdPayment);
sess.setAttribute("createdPayments", createdPayments);

// redirect to payPal pages
Iterator<Links> links = createdPayment.getLinks().iterator();
while (links.hasNext())
{
Links link = links.next();
if (link.getRel().equalsIgnoreCase("approval_url"))
{
url=link.getHref();
resp.sendRedirect(url);
}
}


然后,当payPal页面将我返回到我以前的returnURL页面时,我将调用以下相关代码片段:

String sessID=req.getParameter("sessID");
HttpSession sess=SessionStore.map.get(sessID);
ArrayList<Payment> cPay=(ArrayList<Payment>)sess.getAttribute("createdPayments");
Payment payment=(Payment)cPay.get(0);


并且已检索到具有所有相同属性和所有内容的旧付款对象。这似乎比仅将旧付款ID复制到否则为空白的Payment对象中更为有用。但是,旧的“ createdPayment”状态仍为“已创建”,而不是“已批准”或“已完成”。我不知道如何从上面概述的对象创建到执行相同的Payment对象的过程。实际上,我什至不知道是否应该使用相同的付款对象创建并执行使用method ='paypal'的付款。正如我在原始帖子中所描述的那样,对我来说这应该没有意义。我创建了一个付款对象,payPal发回了一个roval_URL,其中包括我,用于将用户重定向到以进行批准。这会将用户带离我的Web应用程序,并进入Pay​​Pal服务器。由于payPal无法修改我的本地“ createdPayment”变量,因此payPal无法更改其状态。此外,似乎我需要状态为“已批准”的Payment对象才能执行付款。因此,我得出结论,贝宝(PayPal)必须发送给我一个新的付款对象,该对象应具有与我的“ createdPayment”对象相同的信息,但是要具有已批准状态的更新状态,并且可能需要一个特殊的令牌/密码来指示已批准状态,以防止他人只需将一大笔付款入侵已批准状态即可,这很容易做到。我看到我正在按预期方式获得令牌,但没有按预期方式获得PaymentID。我正在获取一个payerID。有没有一种方法可以将返回的令牌和payerID转换为状态为“已批准”的新Payment对象,或者我只是完全丢失了某些东西?

最佳答案

没错,从PayPal网站页面重定向后,“ payerId”将被附加为请求参数,而不是付款ID。但是您还需要付款ID才能执行它。这是来自payPal interactive tool的代码。

String accessToken = "Bearer Jfdd4h4VrmvLeATBNPsGOpp7pMosTppiy.Jq6xpwQ6E";
APIContext apiContext = new APIContext(accessToken);
apiContext.setConfigurationMap(sdkConfig);

Payment payment = new Payment("PAY-4AL22602580048540KKPBSNY");
PaymentExecution paymentExecute = new PaymentExecution();
paymentExecute.setPayerId("BKJ78SZZ8KJYY");
payment.execute(apiContext, paymentExecute);


因此,棘手的部分是如何保留请求之间的付款ID,因为众所周知,HTTP不保存任何状态。您可以在所引用的示例中查看其实现方式:

https://github.com/paypal/rest-api-sdk-java/blob/master/rest-api-sample/src/main/java/com/paypal/api/payments/servlet/PaymentWithPayPalServlet.java

因此它们生成uuid:

String guid = UUID.randomUUID().toString().replaceAll("-", "");


在重定向网址中添加guid参数:

redirectUrls.setReturnUrl(req.getScheme() + "://"
+ req.getServerName() + ":" + req.getServerPort()
+ req.getContextPath() + "/paymentwithpaypal?guid=" + guid);


并将此guid参数与创建的付款ID关联:

map.put(guid, createdPayment.getId());


为了以后使用

payment.setId(map.get(req.getParameter("guid")));


希望这会有所帮助

关于jakarta-ee - PayPal REST API未执行付款。无法将付款对象的状态从“已创建”更改为“已批准”或“已完成”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20358492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com