Paypal+java 支付接入

本文详细介绍了如何在APP中接入Paypal支付系统,包括注册获取账号、创建沙盒环境、编写支付流程及设置IPN回调等步骤,并分享了在开发过程中遇到的问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景说明 :业务需求,需要联合APP完成Paypal的支付接入,于是开始爬坑
第一步:注册获取到paypal的商家账号(注册流程我也不知道)
第二步:登录Paypal开发者中心,创建APP应用获取到clientId和secret

在这里插入图片描述
在这里插入图片描述

第三步:创建沙盒环境下的商户及消费者账号并给消费账号设置余额 9999.99

在这里插入图片描述
!! 我没有使用paypal默认的商家及消费者账号,如果账号有问题建议自己创建对应账号

第四步:编写代码完成支付流程

1.安卓端拿到第二步中创建的 clientId 及商户账号就可以唤起Paypal的支付页面了,所以需要为支付回调做准备
2.安卓端完成商品信息展示,用户点击付款按钮后向后端申请订单,后端生成预付订单信息并返回商品对应信息及订单号
3.安卓端SDK有"customer"字段,这个字段在支付回调时Paypal会返回至回调接口,所以可以用来完成业务逻辑,本人只传了订单号

第五步:设置IPN回调地址并编写回调接口(以下皆以沙盒环境为说明)

沙盒:https://www.sandbox.paypal.com/businessmanage/account/notifications
正式环境:https://www.paypal.com/mep/dashboard

1.设置回调地址,沙盒环境是允许http的,但是正式环境得是https
在这里插入图片描述分割符--------
在这里插入图片描述

3.编写支付回调的代码

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;
    /**
     * Paypal IPN异步回调接口
     *
     * @param request
     * @param response
     * @Atuthor yixiu
     * @since 2020/9/25
     * @throws Exception
     */
 public void receivePaypalStatus(HttpServletRequest request, HttpServletResponse response) throws Exception {
        LOGGER.info("receivePaypalStatus >>>>>>>>>> 进入paypal后台支付通知");
        PrintWriter out = response.getWriter();
        try {
            /**
             * 获取paypal请求参数,并拼接验证参数
             */
            Enumeration<String> en = request.getParameterNames();
            String str = "cmd=_notify-validate";
            while (en.hasMoreElements()) {
                String paramName = en.nextElement();
                String paramValue = request.getParameter(paramName);
                //此处的编码一定要和自己的网站编码一致,不然会出现乱码,paypal回复的通知为‘INVALID’
                str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue, "utf-8");
            }
            //建议在此将接受到的信息 str 记录到日志文件中以确认是否收到 IPN 信息
            LOGGER.info("paypal后台支付通知:" + str);
            /**
             * 将信息 POST 回给 PayPal 进行验证,确认回调信息的安全性
             */
            String webSrc="https://www.sandbox.paypal.com/cgi-bin/webscr";// 沙盒环境
//            String webSrc="https://www.paypal.com/cgi-bin/webscr";// 正式环境(本人是配置文件注入)
            URL u = new URL(webSrc);
            HttpURLConnection uc = (HttpURLConnection) u.openConnection();
            uc.setRequestMethod("POST");
            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setUseCaches(false);
            //设置 HTTP 的头信息
            uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            PrintWriter pw = new PrintWriter(uc.getOutputStream());
            pw.println(str);
            pw.close();

            /**
             * 接受 PayPal 对 IPN 回发的回复信息
             */
            BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
            String res = in.readLine();
            in.close();

            /**
             * 将 POST 信息分配给本地变量,可以根据您的需要添加
             */
            // 交易状态 Completed 代表交易成功
            String paymentStatus = URLEncoder.encode(request.getParameter("payment_status"), "utf-8");
            // 交易时间
            String paymentDate = request.getParameter("payment_date");
            // 交易id
            String txnId = request.getParameter("txn_id");
            // 父交易id
            String parentTxnId = request.getParameter("parent_txn_id");
            // 收款人email, 对你自己的商户
            String receiverEmail = request.getParameter("receiver_email");
            // 收款人id
            String receiverId = request.getParameter("receiver_id");
            // 付款人email
            String payerEmail = request.getParameter("payer_email");
            // 付款人id
            String payerId = request.getParameter("payer_id");
            // 交易金额
            String mcGross = request.getParameter("mc_gross");
            // 手续费
            String paymentFee = request.getParameter("payment_fee");
            // 自定义字段,我存放的订单号
            String custom = request.getParameter("custom");
            LOGGER.info("自定义参数 = " + custom);
            if (StringUtil.isBlank(res)) {
                res = "0";
            }
            LOGGER.info("paypal支付回调:  回调校验结果为  "+res);
            /**
             * 获取 PayPal 对回发信息的回复信息,判断刚才的通知是否为 PayPal 发出的
             * paymentStatus:Refunded 退款回调,Completed 支付完成回调
             */
            if ("VERIFIED".equalsIgnoreCase(res)) {
                //  订单交易成功
                if (paymentStatus.equalsIgnoreCase("Completed")) {
                    LOGGER.info("paypal支付回调:校验通过,准备介入自己业务");
                    try {
                        System.out.println("paypal支付回调:这是支付完成的回调");
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                } else {
                    LOGGER.info("paypal支付回调:回调类型是 -- " + paymentStatus);
                }
            } else if ("INVALID".equalsIgnoreCase(res)) {
                //非法信息,可以将此记录到您的日志文件中以备调查
                LOGGER.info("paypal完成支付发送IPN通知返回状态非法,请联系管理员" + str);
                out.println("confirmError");
            } else {
                //处理其他错误
                LOGGER.info("paypal完成支付发送IPN通知发生其他异常,请联系管理员,请求参数:" + str);
                out.println("confirmError");
            }
        } catch (Exception e) {
            LOGGER.info("确认付款信息发生IO异常   " + e.getMessage());
            out.println("confirmError");
        }
        out.flush();
        out.close();
    }

爬坑重点:完成上诉类容以后,支付完成并且回调进来了,但是在" if (“VERIFIED”.equalsIgnoreCase(res)) {" 时Paypal一直返回校验不成功,后来提交工单联系Paypal的技术人员得知是因为编码格式的原因,虽然上面进行了UTF-8转码,但是在Paypal端解析时是按照设置的编码格式解码,所以需要去Paypal端设置编码格式(本人设置的UTF-8):
正式环境 https://www.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-language-encoding
沙箱环境:https://www.sandbox.paypal.com/cgi-bin/customerprofileweb?cmd=_profile-language-encoding
更多编码选项中找到IPN

Paypal还有个webhook回调什么的,百度了一下,网上大多数说法是这种回调不太好用,加上业务紧急的原因,便没有深究,有使用心得的可以评论或者私信我
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值