PayPal 即时支付通知(Instant Payment Notification, IPN)实践 ✨
1 分钟
如需使用 IPN 接口,开发者账户必须是企业账户。
对开发者而言,支付收款永远是绕不过去的问题。 网络收款基本两大类。
- 平台支持。移动平台开发者比较幸运,主流的App Store和Google Play都直接提供了支付服务,对于一次性付费购买问题,开发者无需考虑收款,平台代收然后进行结算(平台按比例抽成)。
- 自建收款渠道。这涉及的问题就复杂多了。由于地区政策的差异,不同地区需要区别对待,往往需要根据需求封装多种支付方式。中国大陆,微信支付宝都是非常成熟和便捷的方案,集成并不难。 如果是其他地区,则可以考虑使用 PayPal。PayPal不是费率最低的方案,但是考虑到国际金融的复杂性,PayPal无疑是小额收款的最佳方案。
什么是 IPN? #
IPN是 Instant Payment Notification(即时支付通知)的缩写。简而言之,如果我们在PayPal系统中配置了通知接口,用户转账后该接口将收到调用请求,之后程序需要做的是在接口中处理购买逻辑,发放购买权益。
IPNListener接口配置可以是全局的,也可以是针对单个按钮的。我并没有全局配置,而只是在 Buy Now 按钮中配置了回调方法。
SDK #
官方提供了多种语言的调用示例
一些需要特别注意的问题 #
接口超时问题 #
如果服务器在中国大陆,超时风险比较大。也许是因为中国大陆的国际出口信道非常拥堵或者是PayPal的服务SLA比较差,超时是家常便饭。
回调过来后的反向validate经常需要几百毫秒到几十秒不等。
这里建议在IPNListener中减少直接写表操作,而是把数据放到队列中,尽可能避免PayPal的回调超时。否则,就要补偿了,徒增烦恼。
编码问题 #
对于中国大陆的 PayPal 商户,默认的编码是gb2312,不清楚世界其他地区是否有差异。gb2312包含了足够丰富的字符集,适用简体中文、英语、西欧语言等。 缺少了繁体中文,如果有繁体中文用户那就是大问题,需要改成utf8。修改PayPal字符编码
注意这里可能存在与编程语言使用编码不匹配问题。
就Java而言,String类使用的具体是什么编码,和jvm的设置以及系统默认字符集有关。中国用户通常是utf8。如果我们不改PayPal字符集,发送给PayPal进行validate的字符串用的utf8,声明的是gb2312(默认),就会验证失败。
改完字符集后,我们还需要在validate的参数里声明我们用的是utf8。Java版本示例:
Map<String, String> configurationMap = new HashMap<>();
// Endpoints are varied depending on whether sandbox OR live is chosen for mode
configurationMap.put("mode", paypalMode);
//https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-language-encoding
//https://github.com/paypal/ipn-code-samples/issues/108
configurationMap.put("charset", "utf-8");
IPNMessage ipnListener = new IPNMessage(request, configurationMap);