PayPal----订单支付


1、前置

1、案列采用java编写

2、介绍PayPal订单整合:
      https://developer.paypal.com/docs/integration/direct/payments/orders/
      https://developer.paypal.com/docs/api/orders/v2/

3、会对一些可能出现的坑,或者说我碰到的坑进行标记

5、介最后贴图验证以及做好后的样子

6、创建订单 → 捕获订单 → 查询订单 → 申请退款

7、代码已上传码云,如果起到帮助还请star一下地址:https://gitee.com/xmaxm/payments_hodgepodge

2、准备工作

1、MANEV包:

<!-- paypal -->
        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>checkout-sdk</artifactId>
            <version>1.0.2</version>
        </dependency>

2、获取Client ID和Secret, 登录地址: https://developer.paypal.com

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

3、获取测试的账号密码:

在这里插入图片描述

4、登录付款账户:登录:https://www.sandbox.paypal.com

第三步中获取的账号密码, 账户钱不够, 可以从第三步的编辑中为自己添加测试金额
在这里插入图片描述

5、登录接受付款的商户:登录:https://www.sandbox.paypal.com

Unclaimed:这个状态的原因如下:

https://www.paypal.com/c2/smarthelp/article/why-is-my-paypal-payment-unclaimed-faq1490
无人认领/待处理:如果您的付款尚待处理,则表示收件人尚未接受。有几种原因可能导致您的付款待处理。
付款可能有待处理,原因是:
• 收件人尚未注册PayPal帐户。
• 您将款项汇入了收件人尚未添加到其PayPal帐户的电子邮件地址或电话号码。一旦他们将此信息添加到他们的帐户中,钱就会显示在他们的余额中。
• 收件人仍在决定是否要接受您的付款。
• 收款人尚未确认其银行帐户。
如果您的付款在30天内无人认领/待处理,或者您的付款被拒绝或退款,那么您将获得退款

我的原因是:币单位不一致问题, 因为有汇率的存在, 所以PayPal无法自动收款.
创建订单时和商户配置的货币单位一致, 就可以直接完成订单
在这里插入图片描述


货币单位配置:
在这里插入图片描述

2、创建订单

@Override
    public CommonResult createOrder(String amount) {
    
    
        PayPalHttpClient client;
        // 设置环境沙盒或生产
        if (true) {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Sandbox(clientId, secret));
        } else {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Live(clientId, secret));
        }

        // 配置请求参数
        OrderRequest orderRequest = new OrderRequest();
        orderRequest.checkoutPaymentIntent("CAPTURE");
        List<PurchaseUnitRequest> purchaseUnits = new ArrayList<>();
        purchaseUnits.add(new PurchaseUnitRequest().amountWithBreakdown(new AmountWithBreakdown().currencyCode(currency).value(amount)));
        orderRequest.purchaseUnits(purchaseUnits);
        orderRequest.applicationContext(new ApplicationContext().returnUrl(notifyURLSuccess).cancelUrl(notifyURLFail));
        OrdersCreateRequest request = new OrdersCreateRequest().requestBody(orderRequest);

        HttpResponse<Order> response;
        try {
    
    
            response = client.execute(request);
            Order order = response.result();
            String token = order.id();
            log.debug("payPal 支付操作返回结果: " + order);

            String payHref = null;
            String status = order.status();
            if (status.equals("CREATED")) {
    
    
                List<LinkDescription> links = order.links();
                for (LinkDescription linkDescription : links) {
    
    
                    if (linkDescription.rel().equals("approve")) {
    
    
                        payHref = linkDescription.href();
                    }
                }
            }
            Map<String, String> resultMap = new HashMap<String, String>();
            resultMap.put("token", token);
            resultMap.put("payHref", payHref);

            return CommonResult.success("SUCCESS", resultMap);
        } catch (IOException ioe) {
    
    
            if (ioe instanceof HttpException) {
    
    
                HttpException he = (HttpException) ioe;
                log.error("payPal 下单异常: " + ioe);
                return CommonResult.failMessage(500, "PayPal支付失败", he.getMessage());
            }
            log.error("payPal 下单异常: " + ioe);
            return CommonResult.fail(500, "NetworkTimeout");
        }
    }

请求上面会得到如下结果, 我们请求一下这个链接, 输入测试账号密码进行支付

{
    
    
    "code": 200,
    "message": "SUCCESS",
    "data": {
    
    
        "payHref": "https://www.sandbox.paypal.com/checkoutnow?token=96R506274J980111X",
        "token": "96R506274J980111X"
    }
}

3、捕获订单

@Override
    public CommonResult captureOrder(String token) {
    
    
        PayPalHttpClient client;
        // 设置环境沙盒或生产
        if (true) {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Sandbox(clientId, secret));
        } else {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Live(clientId, secret));
        }
        OrdersCaptureRequest request = new OrdersCaptureRequest(token);

        try {
    
    
            HttpResponse<Order> response = client.execute(request);
            Order order = response.result();
            String status = order.status();
            if (status.equals("COMPLETED")) {
    
    
                return CommonResult.success("SUCCESS");
            }
            return CommonResult.success("SUCCESS");
        } catch (IOException ioe) {
    
    
            if (ioe instanceof HttpException) {
    
    
                HttpException he = (HttpException) ioe;
                log.error("payPal 捕获订单异常: " + ioe);
                return CommonResult.failMessage(500, "PayPal支付捕获失败", he.getMessage());
            }
            log.error("payPal 捕获订单异常: " + ioe);
            return CommonResult.fail(500, "NetworkTimeout");
        }
    }

这里捕获失败是因为我已经捕获了订单(一个订单只能捕获一次), 在哪里捕获的请往下看, 支付成功回调

{
    
    
    "code": 500,
    "message": "PayPal支付捕获失败",
    "data": "{\"name\":\"UNPROCESSABLE_ENTITY\",\"details\":[{\"issue\":\"ORDER_ALREADY_CAPTURED\",\"description\":\"Order already captured.If 'intent=CAPTURE' only one capture per order is allowed.\"}],\"message\":\"The requested action could not be performed, semantically incorrect, or failed business validation.\",\"debug_id\":\"8c7d935811111\",\"links\":[{\"href\":\"https://developer.paypal.com/docs/api/orders/v2/#error-ORDER_ALREADY_CAPTURED\",\"rel\":\"information_link\",\"method\":\"GET\"}]}"
}

4、查询订单

@Override
    public CommonResult queryOrder(String token) {
    
    
        PayPalHttpClient client;
        // 设置环境沙盒或生产
        if (true) {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Sandbox(clientId, secret));
        } else {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Live(clientId, secret));
        }

        OrdersGetRequest request = new OrdersGetRequest(token);

        try {
    
    
            HttpResponse<Order> response = client.execute(request);
            Order order = response.result();
            return CommonResult.success("SUCCESS", order.status());
        } catch (IOException ioe) {
    
    
            if (ioe instanceof HttpException) {
    
    
                HttpException he = (HttpException) ioe;
                log.error("payPal 查询订单异常: " + he.getMessage());
                return CommonResult.failMessage(500, "PayPal支付查询失败", he.getMessage());
            }
            log.error("payPal 查询订单异常: " + ioe);
            return CommonResult.fail(500, "NetworkTimeout");
        }
    }

状态码请参考最后

{
    
    
    "code": 200,
    "message": "SUCCESS",
    "data": "COMPLETED"
}

5、申请退款

@Override
    public CommonResult refundOrder(String token) {
    
    
        PayPalHttpClient client;
        // 设置环境沙盒或生产
        if (true) {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Sandbox(clientId, secret));
        } else {
    
    
            client = new PayPalHttpClient(new PayPalEnvironment.Live(clientId, secret));
        }

        // 查询支付订单, 拿到退款订单号
        OrdersGetRequest ordersGetRequest = new OrdersGetRequest(token);
        try {
    
    
            HttpResponse<Order> orderResponse = client.execute(ordersGetRequest);
            Order order = orderResponse.result();
            String captureId = null;
            for (PurchaseUnit purchaseUnit : order.purchaseUnits()) {
    
    
                for (Capture capture : purchaseUnit.payments().captures()) {
    
    
                    captureId = capture.id();
                }
            }
            if (captureId == null) {
    
    
                return CommonResult.fail(500, "PayPal申请退款失败");
            }
            // 申请退款
            CapturesRefundRequest request = new CapturesRefundRequest(captureId);
            HttpResponse<com.paypal.payments.Refund> response = client.execute(request);
            com.paypal.payments.Refund refund = response.result();
            if ("COMPLETED".equals(refund.status())) {
    
    
                return CommonResult.success("SUCCESS", captureId);
            }
            return CommonResult.fail(500, "PayPal申请退款失败");
        } catch (IOException ioe) {
    
    
            if (ioe instanceof HttpException) {
    
    
                HttpException he = (HttpException) ioe;
                log.error("payPal 申请退款异常: " + he.getMessage());
                return CommonResult.failMessage(500, "PayPal支付查询失败", he.getMessage());
            }
            log.error("payPal申请退款异常: " + ioe);
            return CommonResult.fail(500, "NetworkTimeout");
        }
    }

状态码请参考最后

{
    
    
    "code": 200,
    "message": "SUCCESS",
    "data": "0LX49400YH7782525"
}

6、支付成功回调通知

@Override
    public CommonResult paypalSuccess(HttpServletRequest request) {
    
    
        // 通过 token 查询到订单记录
        String token = request.getParameter("token");
        // 拿到订单记录对订单进行捕获操作
        // 目前测试订单没有保存起来, 就手动填写进来
        return captureOrder(token);
    }

7、支付失败回调通知

  @Override
    public CommonResult paypalFail(HttpServletRequest request) {
    
    
        return CommonResult.fail(500, "FAIL");
    }

8:杂谈

1、前期有点繁琐, 碰到问题不是太好找到解决方法, 后期感觉也还好

2、货币单位这个很重要, 不然订单不能自动结账, 需要手动处理, 因为汇率问题

3、然后打开网页的这个网速, 确实有点说不过去, 太慢了, 唉

4、代码上传码云地址:https://gitee.com/xmaxm/payments_hodgepodge

5、捕获订单操作, 一般是直接由回调进行触发, 而不是单独的去调用这个接口

6、订单状态码: 跳转地址:https://developer.paypal.com/docs/api/orders/v2/#definition-order_status
在这里插入图片描述
8、退款状态码:跳转地址:https://developer.paypal.com/docs/api/orders/v2/#definition-refund_status在这里插入图片描述




提供一个群:807770565,欢迎各位进来尬聊 (人不多, 进了就不要退了, 要不就不进, 跪求留一点人, 人多了就活跃了, 跪谢)
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38637558/article/details/109454657