2

我正在使用 Play Framework 2.0 实现一个 PayPal IPN 控制器(目前使用 Java),它从 PayPal 服务器接收表单编码的 POST 请求。我正在改编Guillame Leone 的博客文章中的 Play 1.x 控制器以使用 Play 2.0。由于“参数”现在消失了,这个任务似乎有点棘手。

PayPal IPN 流程有两个步骤:

1) 将请求正文解析为文本,以便我可以向 PayPal 提交他们想要的确切响应。它必须是与他们提交给我的顺序相同的字符串。这目前有效:

 @BodyParser.Of(BodyParser.TolerantText.class)
 public static Result validation() throws Exception {
   Logger.info("Received IPN request");
    String str = "cmd=_notify-validate&" + request().body().asText();
    Logger.info("Validation string: " + str);

2) 向 PayPal 发送验证请求,当他们回复“已验证”响应时,我想解码表单编码的请求正文并将其作为地图访问。但由于我已经使用注释将请求正文解析为文本,因此以下返回 null 而不是映射:

Map<String,String[]> data = request().body().asFormUrlEncoded() //returns null

将此请求解析两次的最佳方法是什么,一次作为文本(忽略表单编码的 MIME 类型),第二次作为表单编码的数据?

(看来我可能想摆脱注释并直接调用 TolerantText 和 FormEncoded 解析器,但我不知道该怎么做!)

4

1 回答 1

1

由于 Java 和 Scala 集合之间的互操作性问题,使用 Play Java API 似乎没有直接的方法来执行此操作。

要使用 Java 集合访问表单数据,我必须编写一个 Scala 助手:

object BodyParserUtils {
  def parseTextAsFormUrlEncodedForJava(textBody: String) = {
    import collection.JavaConverters._
    val scalaMap = FormUrlEncodedParser.parse(textBody)
    scalaMap.mapValues(_.asJava).asJava
  }
}

然后我可以设置数据变量:

Map<String, List<String>> data = BodyParserUtils.
     parseTextAsFormUrlEncodedForJava(request().body().asText());

如果您想要一个裸露的(尚未完成的)Play 2.0 Java 控制器来开始接收 PayPal IPN 请求,这就是全部:

public class PaypalController extends Controller {

@BodyParser.Of(BodyParser.TolerantText.class)
public static Result validation() throws Exception {
    Logger.debug("Received IPN request");

    String str = "cmd=_notify-validate&" + request().body().asText();
    Logger.debug("Validation string: " + str);

    URL url = new URL("https://www.sandbox.paypal.com/cgi-bin/webscr");
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestProperty("Content-Type",
            "application/x-www-form-urlencoded");

    PrintWriter out = new PrintWriter(connection.getOutputStream());
    out.println(str);
    out.close();

    BufferedReader in = new BufferedReader(new InputStreamReader(
            connection.getInputStream()));
    String result = in.readLine();
    in.close();

    Logger.debug("IPN result: " + result);

    Map<String, List<String>> data = BodyParserUtils
            .parseTextAsFormUrlEncodedForJava(request().body().asText());
    Logger.debug("Form data: " + data);

    if (StringUtils.equals(result, "VERIFIED")) {
        return ok();
    } else {
        return badRequest();
    }

}

}
于 2012-10-05T14:35:37.267 回答