前言
因业务需要,需要集成PayPal支付,故一边研究并顺便分享一下集成步骤。附上相关文档:
PayPal集成官方文档
老版本PayPal Android SDK(已停止维护,不推荐使用)
新版本PayPal Android SDK(推荐使用)
PayPal集成方式有以下几种:
1. Client-Side Integration(特点:订单在所接入的App端创建、支付以及捕获)
该方式是使用PayPal自带的支付按钮
PayPalButton
,调用payPalButton.setup()
方法创建订单、支付并捕获订单
2. Server-Side Integration(特点:订单的实际创建和捕获是在服务端,只有支付在App端)
- 该方式创建订单流程:
App需从服务端获取到orderId
,然后在payPalButton.setup()
中CreateOrder()
回调方法的create(@NotNull CreateOrderActions createOrderActions)
方法中调用createOrderActions.set(orderId)
- 捕获订单流程:
在payPalButton.setup()
中OnApprove()
回调的onApprove(@NotNull Approval approval)
方法中先retrieve order details first(yourAppsCheckoutRepository.getEC(approval.getData().getOrderId()))
,再Send the order ID to your own endpoint to capture or authorize the order(yourAppsCheckoutRepository.captureOrder(approval.getData().getOrderId()))
3. Programmatically start the SDK(特点:同Client-Side Integration)
该方式和Client-Side集成方式大致相同,只是不在使用PayPal自带的
PayPalButton
,在拉起支付面板是通过调用PayPalCheckout.start()
方法
说明:本文是使用新版PayPal SDK集成分享,集成方式为第3种。不过个人建议使用第2种方式结合服务端集成更安全可靠。
集成后的效果
注:::若第一次拉起支付时,个人付款账号未登录,会先跳转到一个登录页面,登录成功后会执行一下操作
开始集成前准备
1.登录/注册PayPal账号:登录注册
2.注册登录成功后,创建应用:demo,点击demo查看Client ID和Sandbox account(沙箱测试邮箱账号)
3.创建沙箱账户
4.应用中 minSdkVersion必须大于等于21
开始集成
一. 启用SDK
一、填写Return URL,两种方式:
1、使用 Android App Link
2、直接使用包名+“://paypalpay”。例如你的包名是com.paypal.app,此处就填写com.paypal.app://paypalpay
如下图所示:
二、配置App feature options(注意:这里一定要配置,不然无法拉起支付页面,起初我这里对接的时候,未配置,结果在代码集成完后怎么都无法拉起支付,之后尝试配置了这些值后,拉起支付页面成功)
如上图所示,Log in with PayPal这一项一定要选中,并点击Advanced options展开其中的选项,我这里配置如下图所示,Privacy policy URL和User agreement URL必填项,沙箱环境随便填一个满足URL格式的地址就行,如:https://www.example.com;其余选项暂未知作用,故未勾选。
二. 集成SDK到应用中
1. 清单文件中配置网络权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
2. gradle配置
- 在project root的build.gradle中
allprojects {
repositories {
mavenCentral()
// This private repository is required to resolve the Cardinal SDK transitive dependency.
maven {
url "https://cardinalcommerceprod.jfrog.io/artifactory/android"
credentials {
// Be sure to add these non-sensitive credentials in order to retrieve dependencies from
// the private repository.
username paypal_sgerritz
password AKCp8jQ8tAahqpT5JjZ4FRP2mW7GMoFZ674kGqHmupTesKeAY2G8NcmPKLuTxTGkKjDLRzDUQ
}
}
}
}
或:直接在App module中配置
android {
...
}
dependencies {
...
}
repositories {
mavenCentral()
maven {
url "https://cardinalcommerceprod.jfrog.io/artifactory/android"
credentials {
// Be sure to add these non-sensitive credentials in order to retrieve dependencies from
// the private repository.
username 'paypal_sgerritz'
password 'AKCp8jQ8tAahqpT5JjZ4FRP2mW7GMoFZ674kGqHmupTesKeAY2G8NcmPKLuTxTGkKjDLRzDUQ'
}
}
}
- 在App module的build.gradle中
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
- 添加SDK依赖到App module的build.gradle中,PayPal SDK因是kotlin版本,故需添加core-ktx和kotlin-stdlib-jdk7:version(version需要和Android studio中的kotlin版本一致)支持
dependencies {
implementation('com.paypal.checkout:android-sdk:0.5.1')
implementation "androidx.core:core-ktx:1.6.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10"
}
3. 初始化PayPal SDK
在Application中做如下初始化操作,其中YOUR_CLIENT_ID需要替换为自已应用的clientId
public class YourApp extends Application {
@Override
public void onCreate() {
super.onCreate();
CheckoutConfig config = new CheckoutConfig(
this,
YOUR_CLIENT_ID,//替换为自已应用的clientId
Environment.SANDBOX,//正式上线后,改为Environment.LIVE
String.format("%s://paypalpay", BuildConfig.APPLICATION_ID),//创建应用时填的RETURN_URL
CurrencyCode.USD,//货币种类:CNY-人民币;HKD-港币;TWD-新台币;USD-美元...
UserAction.PAY_NOW,
PaymentButtonIntent.CAPTURE,
new SettingsConfig(
true,
false
)
);
PayPalCheckout.setConfig(config);
}
}
4.创建并捕获订单
直接上代码
@RequiresApi(api = Build.VERSION_CODES.M)
public void invokePayPalPay() {
PayPalCheckout.start(new CreateOrder() {
@Override
public void create(CreateOrderActions createOrderActions) {
//所订购商品详情列表
List<Items> itemsList = new ArrayList<>();
Items items = new Items.Builder().name("演唱会门票")//商品名称
.category(ItemCategory.DIGITAL_GOODS)//商品类型
.description("这是一张演唱会门票的订单")//商品描述
.quantity("1")//商品数量
.sku("sku是什么?")//TODO 待更新
.unitAmount(
new UnitAmount.Builder().value("9.00").currencyCode(CurrencyCode.USD).build())//商品单价
.tax(new UnitAmount.Builder().value("1.00").currencyCode(CurrencyCode.USD).build())//税
.build();
itemsList.add(items);
ArrayList<PurchaseUnit> purchaseUnits = new ArrayList<>();
PurchaseUnit purchaseUnit =
new PurchaseUnit.Builder().referenceId(UUID.randomUUID().toString())
.amount(new Amount.Builder().currencyCode(CurrencyCode.USD)
.value("12.00")//订单总价=itemTotalAmount + taxTotalAmount + handleTotalAmount + shippingTotalAmount - shippingDiscount - discount
.breakdown(new BreakDown.Builder().itemTotal(
new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("9.00")
.build())//商品总价=商品单价(unitAmount) * 商品数量(quantity)
.taxTotal(new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("1.00")
.build())//税总费用
.handling(new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("1.00")
.build())//手续费
.shipping(new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("1.00")
.build())//运费
.shippingDiscount(new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("0")
.build())//运费折扣价格
.discount(new UnitAmount.Builder().currencyCode(CurrencyCode.USD)
.value("0")
.build())//商品折扣价格
.build())
.build())
.description("这里是订单的描述")
.invoiceId("invoiceId是什么?")
.customId("customId是什么?")
.softDescriptor("softDescriptor是什么?")
.items(itemsList)
.payee(new Payee("sb-vbvol6893948@business.example.com", "25FYB5AYNYZHA"))//收款人信息:收款人邮箱和账户id
.build();
purchaseUnits.add(purchaseUnit);
Order order = new Order(OrderIntent.CAPTURE,
new AppContext.Builder().userAction(UserAction.PAY_NOW).build(), purchaseUnits,
ProcessingInstruction.NO_INSTRUCTION);
//创建订单
createOrderActions.create(order, (CreateOrderActions.OnOrderCreated) null);
}
}, new OnApprove() {
@Override
public void onApprove(Approval approval) {
//捕获订单
approval.getOrderActions().capture(new OnCaptureComplete() {
@Override
public void onCaptureComplete(CaptureOrderResult captureOrderResult) {
Log.e(TAG, String.format("CaptureOrderResult: %s", captureOrderResult));
if (captureOrderResult instanceof CaptureOrderResult.Success) {
//TODO 订单捕获成功
} else if (captureOrderResult instanceof CaptureOrderResult.Error) {
//TODO 订单处理失败
}
}
});
}
}, new OnShippingChange() {
@Override
public void onShippingChanged(ShippingChangeData shippingChangeData,
ShippingChangeActions shippingChangeActions) {
Log.e(TAG, "onShippingChanged");
}
}, new OnCancel() {
@Override
public void onCancel() {
//TODO 取消支付
Log.e(TAG, "onCancel:::Buyer cancelled the PayPal experience.");
}
}, new OnError() {
@Override
public void onError(ErrorInfo errorInfo) {
//TODO 支付出错
Log.e(TAG, "OnError:::" + String.format("Error: %s", errorInfo));
}
});
}
至此,PayPal支付SDK已经集成完成。