サーブレットを使用して、新しい REST API を使用して PayPal 支払いを実行するように設計された HTML ページを生成しています。ステータスが承認済みまたは作成済みの支払いをまだ生成できません。私は 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 オブジェクトのステータスは「作成済み」になりました。コードの最後で、実行前にペイパルが支払いを承認すると想定したペイパル ページにユーザーをリダイレクトします。これはサンプル ファイルからの逸脱ですが、これが機能しない理由がわかりません。
if (link.getRel().equalsIgnoreCase("approval_url"))
{
req.setAttribute("redirectURL", link.getHref());
resp.sendRedirect(link.getHref());
}
payPal は HTTP プロトコルを介してローカル変数 createdPayment の状態を変更できないため、payPal ページが、PaymentID と、場合によっては URL に追加された認証トークンを使用して、returnURL ページにリダイレクトされることを期待していました。これら 2 つのことを使用して、次のような静的関数呼び出しを使用して、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);
誰かが私の推論がどこで間違っているかを教えてくれたら、それは絶対にうまくいきます. ありがとう!メインのサーブレット ページの完全なコードを次に示します。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」という名前の古い Payment オブジェクトを取得する方法について、私は混乱していません。上記でコピーした完全なコードでは、参照したのとまったく同じ GUID コードを使用しています。これに関する 1 つの問題は、createdPayment オブジェクトの ID を新しい空白の Payment オブジェクトにコピーする以外に何もしないことです。新しいオブジェクトの状態は、他のすべての属性と同様にまだ空白です。これは ID を持つ空白のオブジェクトであり、それだけです。ほとんど役に立たないので、何かが欠けているか、サーブレットの例が完全に間違っています。
実際、私の最初の方法は、セッション ID を HttpSession オブジェクトにマップする静的マッピングを含む静的クラスを作成することでした。ユーザーのブラウザー セッションの sessionID を生成し、その sessID を payment.create() メソッドの redirectURL の cancelURL と returnURL に追加します。次に、returnURL サーブレットで後で取得できるように、関連する Payment オブジェクトがユーザーの HttpSession オブジェクトに追加されていることを確認します。
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 は、承認のためにユーザーをリダイレクトするために、とりわけ approval_URL を返信します。これにより、ユーザーは Web アプリケーションから payPal サーバーに移動します。PayPal はローカルの「createdPayment」変数を変更できないため、payPal はその状態を変更できません。さらに、支払いを実行するには、「承認済み」の状態の Payment オブジェクトが必要なようです。したがって、payPal は、「createdPayment」オブジェクトと同じ情報を多く含む新しい Payment オブジェクトを返送する必要があると結論付けますが、承認済みの更新された状態と、承認済みステータスを示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするだけです。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? PayPal はその状態を変更できません。さらに、支払いを実行するには、「承認済み」の状態の Payment オブジェクトが必要なようです。したがって、payPal は、「createdPayment」オブジェクトと同じ情報を多く含む新しい Payment オブジェクトを返送する必要があると結論付けますが、承認済みの更新された状態と、承認済みステータスを示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするだけです。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? PayPal はその状態を変更できません。さらに、支払いを実行するには、「承認済み」の状態の Payment オブジェクトが必要なようです。したがって、payPal は、「createdPayment」オブジェクトと同じ情報を多く含む新しい Payment オブジェクトを返送する必要があると結論付けますが、承認済みの更新された状態と、承認済みステータスを示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするだけです。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? 支払いを実行するには、「承認済み」の状態の Payment オブジェクトが必要なようです。したがって、payPal は、「createdPayment」オブジェクトと同じ情報を多く含む新しい Payment オブジェクトを返送する必要があると結論付けますが、承認済みの更新された状態と、承認済みステータスを示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするだけです。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? 支払いを実行するには、「承認済み」の状態の Payment オブジェクトが必要なようです。したがって、payPal は、「createdPayment」オブジェクトと同じ情報を多く含む新しい Payment オブジェクトを返送する必要があると結論付けますが、承認済みの更新された状態と、承認済みステータスを示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするだけです。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? 私は、payPal が、私の「createdPayment」オブジェクトと同じ多くの情報を含む新しい Payment オブジェクトを返送する必要があると結論付けましたが、承認済みの更新された状態と、誰かがハッキングするのを防ぐために承認済みステータスを示す特別なトークン/パスワードが含まれている可能性があります。承認済みの状態への一連の支払い。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? 私は、payPal が、私の「createdPayment」オブジェクトと同じ多くの情報を含む新しい Payment オブジェクトを返送する必要があると結論付けましたが、承認済みの更新された状態と、誰かがハッキングするのを防ぐために承認済みステータスを示す特別なトークン/パスワードが含まれている可能性があります。承認済みの状態への一連の支払い。これは簡単に実行できます。期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? ただし、承認済みの更新された状態と、おそらく承認済みの状態を示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするのを防ぐことができます。これは簡単に行うことができます. 期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか? ただし、承認済みの更新された状態と、おそらく承認済みの状態を示す特別なトークン/パスワードを使用して、誰かが大量の支払いを承認済みの状態にハッキングするのを防ぐことができます。これは簡単に行うことができます. 期待どおりにトークンを取得していることがわかりますが、期待どおりに paymentID を取得していません。payerID を取得しています。返されたトークンと payerID を「承認済み」ステータスの新しい Payment オブジェクトに変換する方法はありますか、それとも何かが完全に欠けているだけですか?