使用 Spring 控制器处理 Paypal IPN 请求?

Posted

技术标签:

【中文标题】使用 Spring 控制器处理 Paypal IPN 请求?【英文标题】:Paypal IPN Request handling with Spring controller? 【发布时间】:2016-07-19 22:48:16 【问题描述】:

我想扩展 Spring 应用程序的功能以包含 HTTP 端点以接收 Paypal 即时付款通知。

Paypal 在 HTTP 正文中发送这些信息,如下所示:

mc_gross = 19.95&presence_eligitibility =符合条件&address_status =确认和payer_id = lplwnmtbwmfay&tax = 0.00&address_street = 1 + main + st&payment_date = 20%3a12%3a59 + 18%+ 13%2c + 2009 + pst&payment_status = pstent&chinept_status = terminer&chinset = windows-1252&address_zip = 95131&first_name = test&mc_fee = 0.88 &address_country_code = US&ADDRESS_NAME =测试+用户和notify_version = 2.6&定制= payer_status =验证的&ADDRESS_COUNTRY =美+国&ADDRESS_CITY =圣+圣何塞和数量= 1&verify_sign = AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&PAYER_EMAIL = gpmac_1231902590_per%40paypal.com&txn_id = 61E67681CH3238416&payment_type =即时与姓氏=用户&ADDRESS_STATE = CA&RECEIVER_EMAIL = gpmac_1231902686_biz%40paypal.com&payment_fee =0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00

https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNIntro/

我是否需要定义一个具体的类来定义请求主体,例如

请求类

    public class PaypalIPNRequest 

    private static final long serialVersionUID = 1L;
    private String mc_gross;
    private String protection_eligibility;
    private String address_street;
    ...


    public PaypalIPNRequest() 
    

    //getters setters

控制器

@Override
@Auditable
@RequestMapping(value = "/ipnRequest.do", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void ipnRequest(@RequestBody final PaypalIPNRequest request) 

如此 SO 答案所述:@RequestBody and @ResponseBody annotations in Spring

如果 Paypal 将来更改他们的 IPN 请求会发生什么情况,这会中断吗?

有没有更好的方法来传递请求正文而不需要特定的类?

我可以使用 HttpServletRequest 吗?

【问题讨论】:

【参考方案1】:

我过去所做的是使用com.paypal.base.ipn.IPNMessage 来验证并从请求中检索(就像您建议的那样)只是对我很重要的字段,而不是将整个请求正文映射到具体的类,即:

private final static String PAYPAL_WEB_IPN_TXN_PARAM = "txn_id";
private final static String PAYPAL_WEB_IPN_AMOUNT_PARAM = "mc_gross";
private final static String PAYPAL_WEB_IPN_PAYMENT_STATUS_PARAM = "payment_status";
private final static String PAYPAL_WEB_IPN_PAYMENT_STATUS = "Completed";

@Resource(name = "payPalConfigurationMap")
private Map<String, String> configurationMap;

private OAuthTokenCredential oAuthTokenCredential;

@PostConstruct
public void init() 
    Properties properties = new Properties();
    properties.putAll(configurationMap);
    PayPalResource.initConfig(properties);

    oAuthTokenCredential = new OAuthTokenCredential(
            configurationMap.get(Constants.CLIENT_ID),
            configurationMap.get(Constants.CLIENT_SECRET),
            configurationMap
    );



public DonationDTO validateWebIPN(HttpServletRequest request) throws Exception 
    IPNMessage ipnlistener = new IPNMessage(request, configurationMap);
    boolean isIpnVerified = ipnlistener.validate();

    String paymentStatus = ipnlistener.getIpnValue(PAYPAL_WEB_IPN_PAYMENT_STATUS_PARAM);

    if (isIpnVerified && paymentStatus.equalsIgnoreCase(PAYPAL_WEB_IPN_PAYMENT_STATUS)) 
        String amount = ipnlistener.getIpnValue(PAYPAL_WEB_IPN_AMOUNT_PARAM);
        String tx = ipnlistener.getIpnValue(PAYPAL_WEB_IPN_TXN_PARAM);

        // irrelevant code

        return donationDTO;
    else
        String exceptionMessage = "Problem when requesting info from PayPal service";
        logger.error(exceptionMessage);
        throw new Exception(exceptionMessage);
    

这样,除非 Paypal 更改字段的名称(这不应该发生),否则您应该不会有任何问题。

【讨论】:

只是为了澄清一下,这是在 Spring 控制器中还是您自己创建的类? 这是我自己的课。我有一个用@RestController 注释的类,它接收来自Paypal 的IPN 请求并调用上面的这个方法,它在另一个类中用@Service 谢谢,有点跑题了,但是您使用什么内容类型来处理 IPN 请求。我从 Spring 收到 HTTP 415 错误 我用过MediaType.APPLICATION_FORM_URLENCODED

以上是关于使用 Spring 控制器处理 Paypal IPN 请求?的主要内容,如果未能解决你的问题,请参考以下文章

在 Braintree 控制面板中输入 paypal 凭据

如何保护我的 IP 免受欺骗或保护?

使用 Spring MVC 的 Paypal 支付

PayPal - Spring - HTTP 方法无效:PATCH

如何使用 Spring Ws marshall 调用 Paypal ws?

PayPal cookie 是不是与 IP 地址相关联?