java後端PayPal支付實現教程
首先引入 PayPal的sdk 這裡我引入的是1.0.4版本的
<!-- 貝寶支付 SDK --> <dependency> <groupId>com.paypal.sdk</groupId> <artifactId>checkout-sdk</artifactId> <paypal-sdk.version>1.0.4</paypal-sdk.version> </dependency>
yml文件引入公司在官網的相關配置
這裡我做瞭yml的文件環境隔離,限免的配置做瞭示例
# 貝寶支付的測試服 pay: paypal: clientId: AeEX1PNMNaP3RuV8JTBMznAhs_gOfFwloG6SG3TiQh1_MBj0 clientSecret: EMDda7g_Q7KmOiH08qJfg-dAb8d2THkYtzRR #測試的mode mode: sandbox #正式的mode mode: live
/** * @author majun * @email [email protected] * @date 2021/7/29 * @since 2.0.0 */ @Data @AllArgsConstructor @NoArgsConstructor @ApiModel public class PayPalVo extends RequestModel { /** 本站訂單號 */ @ApiModelProperty(value = "本站訂單號") private String orderNo; /** 三方訂單號 */ @ApiModelProperty(value = "本站訂單號") private String outOrderNo; /** 1 書幣充值 ; 2 plus會員充值;3 premium會員充值 */ @ApiModelProperty(value = "1 書幣充值 ; 2 plus會員充值;3 premium會員充值") private Integer orderType; }
PayPal支付
/** * 貝寶支付 * * @param payPalVo 請求對象 * @return 返回結果 */ @PostMapping("/payPalNotify") @ApiOperation(value = "貝寶支付二次驗證") @Deprecated public ResponseModel<PayOrderDto> payPalNotify(@RequestBody PayPalVo payPalVo){ if (ObjectUtils.isEmpty(payPalVo.getOrderNo()) || ObjectUtils.isEmpty(payPalVo.getOutOrderNo()) || ObjectUtils.isEmpty(payPalVo.getOrderType())){ return ResponseModel.error(appConfigStatusCodeService.getStatusCode(payPalVo.getLanguage(), ResponseCnSate.PARAM_EXCEPTION)); } // 根據paypal的訂單id,捕獲訂單付款 String outOrderNo = payPalVo.getOutOrderNo(); String orderNo = payPalVo.getOrderNo(); Integer orderType = payPalVo.getOrderType(); // 校驗該訂單是否處理 if (payOrderService.isDispose(orderNo) == PayConstants.ORDER_IS_DISPOSE) { return ResponseModel.error(appConfigStatusCodeService.getStatusCode(payPalVo.getLanguage(), ResponseCnSate.ORDER_PROCESSED)); } //進行二次驗證 Boolean pay = payPalUtils.verifyOrderInfo(outOrderNo); //如果成功則執行後面的邏輯 if (pay){ boolean b = orderService.finishOrder(orderNo, orderType,payPalVo.getLanguage()); if (!b){ return ResponseModel.error(appConfigStatusCodeService.getStatusCode(payPalVo.getLanguage(), ResponseCnSate.ORDER_HANDLER_FAIL)); } //保存訂單號返回訂單信息 PayOrderDto payOrderDto =orderService.saveAndGetOrderInfo(payPalVo.getUserId(),outOrderNo,orderNo); if (ObjectUtils.isNotEmpty(payOrderDto)){ return ResponseModel.success(payOrderDto); } return ResponseModel.error(appConfigStatusCodeService.getStatusCode(payPalVo.getLanguage(), ResponseCnSate.RETURN_ORDER_INFO_FAIL)); } //失敗返回提示 return ResponseModel.error(appConfigStatusCodeService.getStatusCode(payPalVo.getLanguage(), ResponseCnSate.AUTH_FAIL_TWO)); }
後面為瞭讓大傢都看的明白 我單獨抽取瞭一個工具,簡單的做瞭描述
package com.wyzz.global.untils.paypal; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.paypal.core.PayPalEnvironment; import com.paypal.core.PayPalHttpClient; import com.paypal.http.HttpResponse; import com.paypal.http.serializer.Json; import com.paypal.orders.*; import com.paypal.payments.CapturesGetRequest; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** * PayPal工具類 * * @author majun * @email [email protected] * @date 2021/7/29 * @since 2.0.0 */ @Service @Slf4j public class PayPalUtils { /** * paypal配置應用的客戶端ID */ @Value("${pay.paypal.clientId}") private String clientId; /** * paypal配置應用的客戶端密鑰 */ @Value("${pay.paypal.clientSecret}") private String clientSecret; /** * paypal連接環境:live表示生產,sandbox表示沙盒 */ @Value("${pay.paypal.mode}") private String mode; /** * paypal的http客戶端 * @param mode 環境信息 * @param clientId 客戶端ID * @param clientSecret 密鑰 * @return */ public PayPalHttpClient client(String mode, String clientId, String clientSecret) { log.info("mode={}, clientId={}, clientSecret={}", mode, clientId, clientSecret); PayPalEnvironment environment = mode.equals("live") ? new PayPalEnvironment.Live(clientId, clientSecret) : new PayPalEnvironment.Sandbox(clientId, clientSecret); return new PayPalHttpClient(environment); } /** * 構建訂單請求體 * @return */ public OrderRequest buildRequestBody() { return new OrderRequest(); } /** * 校驗訂單信息:先扣款,後查詢訂單詳情 * @param orderId 前端提供的palpay的訂單id * @return 訂單存在並已扣款成功返回true */ public Boolean verifyOrderInfo(String orderId) { Boolean f = false; try { // 1.用戶授權支付成功,進行扣款操作 this.captureOrder(orderId); } catch (Exception e) { e.printStackTrace(); } finally { // 2.扣款操作失敗時也要查詢訂單,確認是否已扣款 try { OrdersGetRequest request = new OrdersGetRequest(orderId); HttpResponse<Order> response = client(mode, clientId, clientSecret).execute(request); System.out.println("Status Code: " + response.statusCode()); System.out.println("Status: " + response.result().status()); System.out.println("Order id: " + response.result().id()); if(response.result().purchaseUnits().get(0).payments() != null) { List<Capture> captures = response.result().purchaseUnits().get(0).payments().captures(); if(captures != null) { for (Capture capture : captures) { if (capture.id() != null && capture.id().length() > 0) { f = true; } } } } } catch (Exception e2) { e2.printStackTrace(); } } return f; } /** * 用戶授權支付成功,進行扣款操作: * 用戶通過CreateOrder生成 approveUrl 跳轉paypal支付成功後,隻是授權,並沒有將用戶的錢打入我們的paypal賬戶,我們需要通過 CaptureOrder接口,將錢打入我的PayPal賬戶 * @param orderId 前端提供的palpay的訂單id */ public void captureOrder(String orderId){ OrdersCaptureRequest request = new OrdersCaptureRequest(orderId); request.requestBody(this.buildRequestBody()); HttpResponse<Order> response = null; try { response = client(mode, clientId, clientSecret).execute(request); } catch (IOException e1) { try { log.error("第1次調用paypal扣款失敗"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { try { log.error("第2次調用paypal扣款失敗"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e2) { log.error("第3次調用paypal扣款失敗,失敗原因 {}", e2.getMessage() ); } } } if (ObjectUtils.isNotEmpty(response)) { log.info("Status Code = {}, Status = {}, OrderID = {}", response.statusCode(), response.result().status(), response.result().id()); for (LinkDescription link : response.result().links()) { log.info("Links-{}: {} \tCall Type: {}", link.rel(), link.href(), link.method()); } for (PurchaseUnit purchaseUnit : response.result().purchaseUnits()) { for (Capture capture : purchaseUnit.payments().captures()) { log.info("Capture id: {}", capture.id()); log.info("status: {}", capture.status()); log.info("invoice_id: {}", capture.invoiceId()); if("COMPLETED".equals(capture.status())) { //進行數據庫操作,修改訂單狀態為已支付成功,盡快發貨(配合回調和CapturesGet查詢確定成功) log.info("支付成功,狀態為=COMPLETED"); } if("PENDING".equals(capture.status())) { log.info("status_details: {}", capture.captureStatusDetails().reason()); String reason = "PENDING"; if(capture.captureStatusDetails() != null && capture.captureStatusDetails().reason() != null) { reason = capture.captureStatusDetails().reason(); } //進行數據庫操作,修改訂單狀態為已支付成功,但觸發瞭人工審核,請審核通過後再發貨(配合回調和CapturesGet查詢確定成功) log.info("支付成功,狀態為=PENDING : {}", reason); } } } Payer buyer = response.result().payer(); log.info("Buyer Email Address: {}", buyer.email()); log.info("Buyer Name: {} {}", buyer.name().givenName(), buyer.name().surname()); } } /** * 查詢訂單詳情 * @param orderId 前端提供的palpay的訂單id * @throws IOException */ public void ordersGetRequest(String orderId) throws IOException { OrdersGetRequest request = new OrdersGetRequest(orderId); HttpResponse<Order> response = null; try { response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { try { System.out.println("調用paypal訂單查詢失敗,鏈接異常1"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e2) { try { System.out.println("調用paypal訂單查詢失敗,鏈接異常2"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e3) { System.out.println("調用paypal訂單查詢失敗,鏈接異常3"); System.out.println(e3.getMessage()); } } } System.out.println("Status Code: " + response.statusCode()); System.out.println("Status: " + response.result().status()); System.out.println("Order id: " + response.result().id()); if(response.result().purchaseUnits().get(0).payments() != null) { List<Capture> captures = response.result().purchaseUnits().get(0).payments().captures(); if(captures != null) { for (Capture capture : captures) { System.out.println("\t訂單編號= " + capture.invoiceId() + "\tCapture Id= " + capture.id() + "\tCapture status= " + capture.status() + "\tCapture amount= " + capture.amount().currencyCode() + ":" + capture.amount().value()); } } List<Refund> refunds = response.result().purchaseUnits().get(0).payments().refunds(); if(refunds != null) { for (Refund refund : refunds) { System.out.println("\t售後編號= " + refund.invoiceId() + "\tRefund Id= " + refund.id() + "\tRefund status= " + refund.status() + "\tRefund amount= " + refund.amount().currencyCode() + ":" + refund.amount().value()); } } } System.out.println("Links: "); for (LinkDescription link : response.result().links()) { System.out.println("\t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method()); } } /** * 查詢扣款詳情 * @param orderId 前端提供的palpay的訂單id * @throws IOException */ public void capturesGetRequest(String orderId) throws IOException { CapturesGetRequest request = new CapturesGetRequest(orderId); HttpResponse<com.paypal.payments.Capture> response = client(mode, clientId, clientSecret).execute(request); System.out.println("Status Code: " + response.statusCode()); System.out.println("Status: " + response.result().status()); System.out.println("Capture ids: " + response.result().id()); System.out.println("Links: "); for (com.paypal.payments.LinkDescription link : response.result().links()) { System.out.println("\t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method()); } } public Map<String,Object> createOrder(OrderRequest orderRequest) { OrdersCreateRequest request = new OrdersCreateRequest(); request.header("prefer","return=representation"); request.requestBody(orderRequest); // PayPalClient payPalClient = new PayPalClient(); HttpResponse<Order> response = null; try { response = client(mode, clientId, clientSecret).execute(request); } catch (IOException e1) { try { log.error("第1次調用paypal訂單創建失敗"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e) { try { log.error("第2次調用paypal訂單創建失敗"); response = client(mode, clientId, clientSecret).execute(request); } catch (Exception e2) { log.error("第3次調用paypal訂單創建失敗,失敗原因:{}", e2.getMessage()); } } } // String approve = ""; Map<String,Object> map = new HashMap(); if (response.statusCode() == 201) { log.info("Status Code = {}, Status = {}, OrderID = {}, Intent = {}", response.statusCode(), response.result().status(), response.result().id(), response.result().checkoutPaymentIntent()); map.put("Id",response.result().id()); for (LinkDescription link : response.result().links()) { log.info("Links-{}: {} \tCall Type: {}", link.rel(), link.href(), link.method()); if(link.rel().equals("approve")) { // approve = link.href(); map.put("outOrderNo",link.href()); } } String totalAmount = response.result().purchaseUnits().get(0).amountWithBreakdown().currencyCode() + ":" + response.result().purchaseUnits().get(0).amountWithBreakdown().value(); log.info("Total Amount: {}", totalAmount); // String json= new JSONObject(new Json().serialize(response.result())).toString(4); // log.info("createOrder response body: {}", json); } return map; } // public static void main(String[] args) throws Exception { // PayPalUtils payPalUtils = new PayPalUtils(); // payPalUtils.verifyOrderInfo("45S82276S8854414K"); // payPalUtils.ordersGetRequest("45S82276S8854414K"); // payPalUtils.captureOrder("18K07174PX6483500"); // payPalUtils.capturesGetRequest("31V65486WC667442G"); // // issue : ORDER_ALREADY_CAPTURED 訂單已被捕獲 // // intent=CAPTURE 每個訂單隻允許捕獲一次 // } }
不敢說描述的有多麼到位 隻希望給java將要對接paypal的同學一點兒參考
到此這篇關於java後端PayPal支付實現教程的文章就介紹到這瞭,更多相關java PayPal支付內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!