【问题标题】:Paypal IPN Request handling with Spring controller?使用 Spring 控制器处理 Paypal IPN 请求?
【发布时间】: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 吗?

【问题讨论】:

    标签: java spring spring-mvc paypal


    【解决方案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
    猜你喜欢
    • 2016-01-27
    • 1970-01-01
    • 2021-07-09
    • 2014-10-28
    • 2020-10-11
    • 2012-09-21
    • 2017-08-01
    • 1970-01-01
    • 2012-06-05
    相关资源
    最近更新 更多