当前位置: 代码迷 >> 综合 >> PayPal----订单支付
  详细解决方案

PayPal----订单支付

热度:22   发布时间:2023-12-24 10:47:17.0

文章目录

  • 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

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

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、创建订单

@Overridepublic 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、捕获订单

@Overridepublic 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、查询订单

@Overridepublic 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、申请退款

@Overridepublic 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、支付成功回调通知

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

7、支付失败回调通知

  @Overridepublic 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,欢迎各位进来尬聊 (人不多, 进了就不要退了, 要不就不进, 跪求留一点人, 人多了就活跃了, 跪谢)
在这里插入图片描述