【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!

一、接入paypal环境准备:

1、注册paypal账号

https://www.paypal.com
注册“商家账号”,完成验证

2、注册paypal开发者账号

用上一步创建好的账号登陆:https://developer.paypal.com

3、创建测试用户和商家账号
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
个人和商家账号都选中国就行
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!

那三个点里面可以设置账号的一些信息,还有余额之类的

4、创建应用,生成用于测试的clientID 和 密钥

当前页面创建应用
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
这里面有一个默认的还有一个我已经创建好的测试应用
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
点击按钮创建自己的应用,选择好我们之前创建的收款账号
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
这样我们的id和密匙都创建好了
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!

二、使用java(springboot)实现paypal支付:

下面是调接口的方式直接接入

使用基本的web项目即可
pom引入:

<dependency>
    <groupId>com.paypal.sdk</groupId>
    <artifactId>rest-api-sdk</artifactId>
    <version>1.4.2</version>
</dependency>

代码的基本流程:

接口调用→调用service→创建订单→重定向到paypal的页面(后面的支付流程交给了paypal,这个页面就是在那个for循环里面的那个条件甄别出来的那个url,看了下面的代码你才能明白我说的哦)→登录→支付

代码参考(我也是参考这篇文章,自己改造的):https://www.cnblogs.com/jpfss/p/9945845.html

其中的不足:

1、在创建订单的时候:其一在自己的业务系统中有一些必要的信息需要PayPal通知的时候回传,比如id等字段,这个可以放到custom这个字段里面;其二购物车的信息,可以自行理解下面的代码,item→items→itemsList→transaction→transactions

甚至一些收货地址,信息什么的,我都没看到,我这里也没用到,所以我也没关注,需要自己研究下,总之都在这一步,下面的代码是我自己的一些设置,供参考
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
2、没有集成通知:

在这里我简单提一下:

登录商家账号:https://www.sandbox.paypal.com/
右上角头像→Account Settings→左侧栏通知→即时通知付款→更新

填写自己的接口:这个接口需要域名哦,可以用内网穿透工具转发哦。
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
在代码中怎么做呢?

 @RequestMapping(value = "notify", method = RequestMethod.POST)
    public void notify(@RequestBody String body, final HttpServletResponse response) throws IOException {
    	//原始请求的body,kv,在回复paypal通知的有用,这里卡了我好久,在后面的问题模块也有提到
        var kv = URLEncodedUtils.parse(body, Charset.forName("utf-8"));
        //下面就是转换成我们自己的实体类,用来接收paypal通知的所有字段,如果不知道有什么字段。可以看看body里面具体的内容哦
        Map<String, String> map = kv.stream().collect(Collectors.toMap(NameValuePair::getName, NameValuePair::getValue));
        PostPayPalNotifyRequest postPayPalNotifyRequest = PostPayPalNotifyRequest.getInstanceFromMap(map);
        try {
        	//处理通知
            payPalPaymentService.handlePayPalPaymentSuccessNotification(postPayPalNotifyRequest, body);
            response.getWriter().write("success");
        } catch (DuplicateKeyException exception) {
            log.warn("payPal notify for order id " + postPayPalNotifyRequest.getTxnId() + " has been already received. ignored! ");
        }
    }

处理通知的时候要做什么呢?

参考:https://www.paypal.com/c2/cgi-bin/webscr?cmd=p/acc/ipn-info-outside

三、我遇到的问题

1、paypal通知(ipn)遇到:支付返回的状态为:Pending

解决:√
【PayPal接入(java)】【IPN通知问题】项目实战干货总结记录!
这个页面来源,参考,本文的“接入paypal”的第三步

2、回调通知的时候,得不到 VERIFIED

解决:√

主要需要的原始通知+cmd=_notify-validate这个kv来回调的哦
所以我们需要保留原始的body然后加&cmd=_notify-validate

代码参考:这个body前面我们是有拿到的哦

 /**
     * sandbox为:https://www.sandbox.paypal.com/cgi-bin/webscr
     * live为:https://www.paypal.com/cgi-bin/webscr
     * 将paypal发送过来的所有信息加上一个&cmd=_notify-validate参数,表示对这个信息进行验证,全部发送回paypal验证,如果信息确实存在,则返回VERIFIED字符串。
     *
     * @param request
     * @return
     */
    public boolean verifyNotify(final PostPayPalNotifyRequest request, final String body) {
        log.info("开始回调PayPal接口,验证通知...");
        String callBackBody = body + "&cmd=_notify-validate";
        try {
            String verifyRes = HttpUtils.doPost(verifyUrl, callBackBody, "utf-8");
            log.info("验证结果为:{}", verifyRes);
            return verifyRes.equals(VERIFIED);
        } catch (Exception e) {
            log.error("payPal验证通知异常" + e.getMessage());
        }
        return false;
    }

3、正式环境的切换:

解决:√

更换正式环境的id和密匙,
修改配置文件:
payPal.mode=sandbox为payPal.mode=live

其他

PayPal开发手册

部分PayPal通知的字段含义

上一篇:[连载型] Neutron 系列 (18): Neutron 分布式虚拟路由【下】


下一篇:布局数字市场大成功 支付巨头PayPal加密货币日交易量超2.42亿美元