Android接入PayPal支付

前言

因业务需要,需要集成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种方式结合服务端集成更安全可靠。

集成后的效果

注:::若第一次拉起支付时,个人付款账号未登录,会先跳转到一个登录页面,登录成功后会执行一下操作

PayPal支付.gif

开始集成前准备

1.登录/注册PayPal账号:登录注册
2.注册登录成功后,创建应用:demo,点击demo查看Client ID和Sandbox account(沙箱测试邮箱账号)

创建应用

3.创建沙箱账户
沙箱账户创建.png

4.应用中 minSdkVersion必须大于等于21

开始集成

一. 启用SDK

一、填写Return URL,两种方式:
1、使用 Android App Link
2、直接使用包名+“://paypalpay”。例如你的包名是com.paypal.app,此处就填写com.paypal.app://paypalpay
如下图所示:

输入返回URL

二、配置App feature options(注意:这里一定要配置,不然无法拉起支付页面,起初我这里对接的时候,未配置,结果在代码集成完后怎么都无法拉起支付,之后尝试配置了这些值后,拉起支付页面成功)
App feature options1.png

如上图所示,Log in with PayPal这一项一定要选中,并点击Advanced options展开其中的选项,我这里配置如下图所示,Privacy policy URLUser agreement URL必填项,沙箱环境随便填一个满足URL格式的地址就行,如:https://www.example.com;其余选项暂未知作用,故未勾选。
App feature options2.png

二. 集成SDK到应用中

1. 清单文件中配置网络权限


      
      ...

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 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 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("[email protected]", "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已经集成完成。

你可能感兴趣的:(Android接入PayPal支付)