Paypal 实现跨境支付
springboot实战电商项目mall4j (https://gitee.com/gz-yami/mall4j)
摘要 Paypal支付对接(V2)
1、商家注册Paypal账号
1.注册前准备
2.注册完成后验证
二、登录开发者中心
使用上一步注册好的账号,直接登录开发者中心. https://developer.paypal.com
1.点击右上角的按钮 “Dashboard”
点击完成后显示
2.在沙箱中,创建两个测试账号
1.在左边的导航栏中点击 Sandbox 下的 Accounts
2.进入Acccouts界面后,可以看到系统有两个已经生成好的测试账号,但是我们不要用系统给的测试账号,很卡的,自己创建两个
3.点击右上角的“Create Account”,创建测试用户
创建一个北美的Personal账户
创建一个China 的商家账号
商家和个人,创建,直接点击创建就自动创建完成了,默认商家/个人账号有 5000美元
再创建两个账号,分别是北美的商家、个人账号
4.登录创建好的沙箱账户
沙箱登录地址: https://www.sandbox.paypal.com
3.创建应用,先在沙盒中创建应用
还是在开发者中心. https://developer.paypal.com
在 My Apps & Credentials ----> Sandbox ------> Create App
App Name : 应用的名称
App Type:
// 商家 - 以商家(卖家)身份接受付款。
Merchant – Accept payments as a merchant (seller)
// 平台–以平台(市场、众筹或电商平台)的形式将款项转移给卖家
Platform – Move payments to sellers as a platform (marketplace, crowdfunding, or e-commerce platform)
Sandbox Business Account: 选择一个创建的沙盒商家账户
4.clientId 和 clientSecret 的获取
点击创建
Client ID 就是 clientId , Secret 就是 clientSecret
5.应用详情页下方创建WEBHOOKS
然后点击 Add Webhook
点击确定即可
三、Java支付对接
支付方式:
paypal提供了多种支付方式,如标准支付和快速支付,其中标准支付誉为最佳实践。
标准支付主要特点是只需要集成paypal按钮,所有的付款流程由paypal控制,接入方不需要关心支付细节。当用户完成支付后,paypal会通过同步PDT或者异步IPN机制来通知接入方,这种方式比较轻量级,对接难度最小,而且对借入方的入侵较小。
快速支付相对复杂,支付过程由接入方控制,通过调用3个接口来实现。从接入方网页跳转到paypal支付页面前,第一个接口触发,用于向paypal申请支付token。接着用户进入paypal支付页面,并进行支付授权,授权接口中会提交上一步获取的支付token,这个过程由paypal控制,并且没有进行实际支付,接着接入方调用第二个接口,用于获取用户的授权信息,包括支付金额,支付产品等信息,这些基础信息核对无误后,调用第三个接口,进行实际付费扣款,扣款成功后,paypal同样会进行同步PDT和异步IPN通知,这种方式很灵活,控制力强,但编码复杂度较高,入侵性较大。从实际情况考虑,我们选择了采标标准支付方式接入paypal支付。
通知方式:
paypal支付的IPN和PDT两种通知方式,IPN异步通知,可能会有时延,但可靠性高,当接入方主机不可达时,有重试机制保证IPN通知尽量抵达接入方服务器。接入方收到IPN通知后,需要对其确认。确认方法为,把接收到的IPN通知原封不动的作为请求体,调用IPN确认接口。PDT通知是是实时的,但可靠性不高,因为只会通知一次,没有重试机制,一旦接入方出现主机不可达,这样的消息将会被丢失。官方推荐,IPN通知和PDT通知最好混合使用,以满足时效性和可靠性的保证。我们采用了IPN和PDT两种通知机制。
Demo 网址:https://demo.paypal.com/c2/demo/home
V1 版本已过期,我们使用V2对接支付
v1文档:https://developer.paypal.com/docs/api/payments/v1/
V2文档: https://developer.paypal.com/docs/api/payments/v2/
四、直接上代码
系统使用创建的默认美元货币支付
不多说我们直接上代码
maven参数引入
<!--paypal-->
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>1.0.2</version>
</dependency>
PayPalConfig.class
package com.xxxx.config;
import cn.hutool.core.util.StrUtil;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;
import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;
import com.paypal.http.HttpResponse;
import com.paypal.orders.*;
import com.paypal.payments.CapturesGetRequest;
import com.paypal.payments.CapturesRefundRequest;
import com.paypal.payments