天天看點

PayPal----訂單支付

文章目錄

  • 1、前置
  • 2、準備工作
    • 1、MANEV包:
    • 2、擷取Client ID和Secret, 登入位址: https://developer.paypal.com
    • 3、擷取測試的賬号密碼:
    • 4、登入付款賬戶:登入:https://www.sandbox.paypal.com
    • 5、登入接受付款的商戶:登入:https://www.sandbox.paypal.com
  • 2、建立訂單
  • 3、捕獲訂單
  • 4、查詢訂單
  • 5、申請退款
  • 6、支付成功回調通知
  • 7、支付失敗回調通知
  • 8:雜談

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

PayPal----訂單支付
PayPal----訂單支付

3、擷取測試的賬号密碼:

PayPal----訂單支付

4、登入付款賬戶:登入:https://www.sandbox.paypal.com

第三步中擷取的賬号密碼, 賬戶錢不夠, 可以從第三步的編輯中為自己添加測試金額

PayPal----訂單支付

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無法自動收款.

建立訂單時和商戶配置的貨币機關一緻, 就可以直接完成訂單

PayPal----訂單支付

貨币機關配置:

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

繼續閱讀