使用 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 请求?的主要内容,如果未能解决你的问题,请参考以下文章
PayPal - Spring - HTTP 方法无效:PATCH