天天看點

接入 PayPal iOS SDK

最近面試了一家公司,是做跨境電商的,剛拿到 offer。在面試的時候聊到過,因為是做跨境電商的,面向的使用者群體是美國歐洲的使用者,是以在支付環節不使用支付寶/微信支付等國内産品,使用的是 paypal,是以提前研究一下并且先記錄下來。

這裡是 paypal iOS SDK 的 github 位址:https://github.com/paypal/PayPal-iOS-SDK

其實隻要好好看這裡的内容,很容易就能懂。

簡介

在 paypal 的世界裡,他有多種支付方式:

  • 直接支付(single payment):類似國内支付産品,直接對一件或多件商品使用 paypal 餘額支付
  • 預支付(future payment):建立一個預支付訂單,可能以後進行支付
  • 信用卡支付(credit card):paypal SDK 提供了一套 card.io 的庫,可以掃描信用卡,并且使用信用卡直接支付

大多數情況下我們隻需要使用直接支付就好。以下也隻談直接支付,其他方式請自行檢視文檔。

當然,在支付之前,我們都需要去它的開發者網站進行開發者申請,建立 application 并擷取

CLIENT_ID_FOR_PRODUCTION

CLIENT_ID_FOR_SANDBOX

Client ID for Production & Sandbox

OK,其實 paypal 隻需要一個 client id 來确認你的 App,那麼為什麼有 production 和 sandbox 兩個呢?

  • production:所謂的正式環境,使用者需要輸入自己的 paypal 賬戶名和密碼來進行支付。
  • sandbox:所謂的測試環境,在你注冊好賬戶并且生成 application 之後,paypal 會給你建立一個測試環境和賬戶,你需要在支付的時候輸入這個賬戶名和密碼就可以進行測試了。

支付流程

在 iOS 下,paypal 的支付流程可謂是簡單,比起支付寶的等,開發者不需要很多複雜的操作,比如密鑰什麼的,這個最讨厭。你隻需要使用 paypal SDK 建立好支付的内容,然後跳轉到 paypal SDK 提供的 PayPalPaymentViewController,然後使用者去完成支付就 OK 了,也不需要使用者安裝 paypal。接着你用代理來監控使用者是不是支付成功,或者失敗,并且及時通知你的伺服器。

添加 paypal SDK 到你的項目

如果你用 cocoapods 來管理你的三方庫,那麼你隻需要以下兩行代碼:

platform :ios, '6.0'
pod 'PayPal-iOS-SDK'
           

如果你不使用 cocoapods,那麼請看這裡。

下面不管你有沒有使用 cocoapods,都需要給 URL Scheme 裡面加以下幾行:

com.paypal.ppclient.touch.v1
com.paypal.ppclient.touch.v2
org-appextension-feature-password-management
           

在文檔裡面還說了,要添加開源的允許證書,不過怎麼弄還沒研究過,看了一下,好像不太影響使用,後面研究明白了再加上來

?????????

在這裡标記一下。

怎樣支付?

首先這裡是直接支付 (single payment) 的文檔。

paypal 做什麼?

  1. 推出 paypal 支付視圖展示支付資訊
  2. 和 paypal 合作完成支付
  3. 傳回支付結果給你的 App

你做什麼?

  1. 接收 paypal 的支付結果
  2. 發送支付結果給你的背景伺服器
  3. 給使用者提供貨物或者服務

當然你還以選擇提供給 paypal 一個郵寄位址,paypal 會儲存下來這個位址。

示例代碼

  1. 初始化 SDK,需要你提供 client ID,這個過程在 AppDelegate.m 裡面實作。
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      // ...
      [PayPalMobile initializeWithClientIdsForEnvironments:@{PayPalEnvironmentProduction : @"YOUR_CLIENT_ID_FOR_PRODUCTION",
                                                             PayPalEnvironmentSandbox : @"YOUR_CLIENT_ID_FOR_SANDBOX"}];
      // ...
      return YES;
    }
               
  2. 在你的結算頁面添加代理
    // SomeViewController.h
    #import "PayPalMobile.h"
    
    @interface SomeViewController : UIViewController<PayPalPaymentDelegate>
    // ...
    @end
               
  3. 建立一個

    PayPalConfiguration

    對象,這個對象将表示在這個頁面的支付類型、展示語言、是否可用信用卡、商戶名稱等。
    // SomeViewController.m
    
    @interface SomeViewController ()
    // ...
    @property (nonatomic, strong, readwrite) PayPalConfiguration *payPalConfiguration;
    // ...
    @end
    
    @implementation SomeViewController
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
      self = [super initWithCoder:aDecoder];
      if (self) {
        _payPalConfiguration = [[PayPalConfiguration alloc] init];
    
        // See PayPalConfiguration.h for details and default values.
        // Should you wish to change any of the values, you can do so here.
        // For example, if you wish to accept PayPal but not payment card payments, then add:
        _payPalConfiguration.acceptCreditCards = NO;
        // Or if you wish to have the user choose a Shipping Address from those already
        // associated with the user's PayPal account, then add:
        _payPalConfiguration.payPalShippingAddressOption = PayPalShippingAddressOptionPayPal;
      }
      return self;
    } 
               
  4. 建立支付環境,然後和 paypal 伺服器進行預連接配接。建議是在這個頁面初始化的時候就建立預連接配接,但是最好不要直接建立連接配接,因為這個連接配接是有時間限制的。
    // SomeViewController.m
    
    - (void)viewWillAppear:(BOOL)animated {
      [super viewWillAppear:animated];
    
      // Start out working with the test environment! When you are ready, switch to PayPalEnvironmentProduction.
      [PayPalMobile preconnectWithEnvironment:PayPalEnvironmentNoNetwork];
    }
               
  5. 建立

    PayPalPayment

    對象,它必須要設定:價格、匯率代碼、簡介、交易意圖(sale、order、authorize),當然包括可選屬性:發票号和郵寄位址。
    // SomeViewController.m
    
    - (IBAction)pay {
    
      // Create a PayPalPayment
      PayPalPayment *payment = [[PayPalPayment alloc] init];
    
      // Amount, currency, and description
      payment.amount = [[NSDecimalNumber alloc] initWithString:@"39.95"];
      payment.currencyCode = @"USD";
      payment.shortDescription = @"Awesome saws";
    
      // Use the intent property to indicate that this is a "sale" payment,
      // meaning combined Authorization + Capture.
      // To perform Authorization only, and defer Capture to your server,
      // use PayPalPaymentIntentAuthorize.
      // To place an Order, and defer both Authorization and Capture to
      // your server, use PayPalPaymentIntentOrder.
      // (PayPalPaymentIntentOrder is valid only for PayPal payments, not credit card payments.)
      payment.intent = PayPalPaymentIntentSale;
    
      // If your app collects Shipping Address information from the customer,
      // or already stores that information on your server, you may provide it here.
      payment.shippingAddress = address; // a previously-created PayPalShippingAddress object
    
      // Several other optional fields that you can set here are documented in PayPalPayment.h,
      // including paymentDetails, items, invoiceNumber, custom, softDescriptor, etc.
    
      // Check whether payment is processable.
      if (!payment.processable) {
        // If, for example, the amount was negative or the shortDescription was empty, then
        // this payment would not be processable. You would want to handle that here.
      }
    
      // continued below... 
               
  6. 建立然後展示

    PayPalPaymentViewController

    頁面,使用之前建立好的

    PayPalPayment

    PayPalConfiguration

    // Create a PayPalPaymentViewController.
      PayPalPaymentViewController *paymentViewController;
      paymentViewController = [[PayPalPaymentViewController alloc] initWithPayment:payment
                                                                     configuration:self.payPalConfiguration
                                                                          delegate:self];
    
      // Present the PayPalPaymentViewController.
      [self presentViewController:paymentViewController animated:YES completion:nil];
               
  7. 當然不要少了代理方法的監聽。
    // SomeViewController.m
    
    #pragma mark - PayPalPaymentDelegate methods
    
    - (void)payPalPaymentViewController:(PayPalPaymentViewController *)paymentViewController
                     didCompletePayment:(PayPalPayment *)completedPayment {
      // Payment was processed successfully; send to server for verification and fulfillment.
      [self verifyCompletedPayment:completedPayment];
    
      // Dismiss the PayPalPaymentViewController.
      [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    - (void)payPalPaymentDidCancel:(PayPalPaymentViewController *)paymentViewController {
      // The payment was canceled; dismiss the PayPalPaymentViewController.
      [self dismissViewControllerAnimated:YES completion:nil];
    }
               
  8. 給你的伺服器發送支付成功、支付失敗等資訊請求。
    // SomeViewController.m
    
    - (void)verifyCompletedPayment:(PayPalPayment *)completedPayment {
      // Send the entire confirmation dictionary
      NSData *confirmation = [NSJSONSerialization dataWithJSONObject:completedPayment.confirmation
                                                             options:0
                                                               error:nil];
    
      // Send confirmation to your server; your server should verify the proof of payment
      // and give the user their goods or services. If the server is not reachable, save
      // the confirmation and try again later.
    }
               

最後

别被騙了,如果是直接支付,一定要确認一下支付的證明。這一步驟應該是伺服器來确定。伺服器需要将你收到的支付 id 給 paypal 進行驗證。