最近面試了一家公司,是做跨境電商的,剛拿到 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 做什麼?
- 推出 paypal 支付視圖展示支付資訊
- 和 paypal 合作完成支付
- 傳回支付結果給你的 App
你做什麼?
- 接收 paypal 的支付結果
- 發送支付結果給你的背景伺服器
- 給使用者提供貨物或者服務
當然你還以選擇提供給 paypal 一個郵寄位址,paypal 會儲存下來這個位址。
示例代碼
- 初始化 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; }
- 在你的結算頁面添加代理
// SomeViewController.h #import "PayPalMobile.h" @interface SomeViewController : UIViewController<PayPalPaymentDelegate> // ... @end
- 建立一個
對象,這個對象将表示在這個頁面的支付類型、展示語言、是否可用信用卡、商戶名稱等。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; }
- 建立支付環境,然後和 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]; }
- 建立
對象,它必須要設定:價格、匯率代碼、簡介、交易意圖(sale、order、authorize),當然包括可選屬性:發票号和郵寄位址。PayPalPayment
// 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...
- 建立然後展示
頁面,使用之前建立好的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];
- 當然不要少了代理方法的監聽。
// 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]; }
- 給你的伺服器發送支付成功、支付失敗等資訊請求。
// 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 進行驗證。