文章目录
- 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,欢迎各位进来尬聊 (人不多, 进了就不要退了, 要不就不进, 跪求留一点人, 人多了就活跃了, 跪谢)