本文章僅作爲個人筆記
paypal開發者首頁
paypal首頁
paypalAndroidsdk項目地址
參考文章一(Android)
參考文章二(Android)
參考文章三(IOS)
paypal支付開發過程是漫長的,開始是各種paypal文檔閱讀,折騰了半天說clientid錯誤,弄了好久才發現github上面告知paypalsdk不再支持新商戶,推薦使用 Braintree,然而再折騰半天,註冊時發現Braintree只只是海外公司或香港公司,大陸公司根本無法註冊,這就gg了。但肯定不能這麼放棄啊,好在還是有大神的,經過幾篇文章的合併,最後改出自己想要的方案。另外需要注意,如果想要開發收款則必須註冊公司商務賬號,並且保證對公賬戶paypal可用,註冊時會看到相應的支持銀行,這裏由於前期開發過程過長,且註冊過程什麼的網上文章還是挺多的,就重造輪子了,這裏主要貼自己的封裝工具。
-
部分信息獲取方式截圖
- 進入Dashboard界面
- 進入app界面
- 查看clientId及secret,後面服務器及客戶端均可用到,可根據個人需求決定sendbox用戶或live用戶。
- 進入Dashboard界面
-
Android端
-
導入方式官方demo已經說得非常清楚了,這裏說個大概吧。
-
添加jar包導入
dependencies { api "com.paypal.sdk:paypal-android-sdk:2.16.0" }
-
主要封裝代碼(因爲樓主的商品都是一個一個購買的,所以封裝的時候直接傳入了一個商品,如果有多個商品同時購買並且包含稅費、運費什麼的可以自己修改此類):
import android.app.Activity; import android.content.Intent; import android.util.Log; import com.paypal.android.sdk.payments.PayPalConfiguration; import com.paypal.android.sdk.payments.PayPalItem; import com.paypal.android.sdk.payments.PayPalPayment; import com.paypal.android.sdk.payments.PayPalPaymentDetails; import com.paypal.android.sdk.payments.PayPalService; import com.paypal.android.sdk.payments.PaymentActivity; import com.paypal.android.sdk.payments.PaymentConfirmation; import java.math.BigDecimal; public class PayPalUtils { // private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX; private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION; private static PayPalConfiguration config; private static final int REQUEST_CODE_PAY_PAL = 1008611; private static final PayPalUtils PAY_PAL_UTILS = new PayPalUtils(); private static Activity activity; private static Back back; private PayPalUtils() { } public static PayPalUtils newInstance(Activity mActivity, String clientId, Back mBack) { activity = mActivity; back = mBack; Intent intent = new Intent(activity, PayPalService.class); config = new PayPalConfiguration() .environment(CONFIG_ENVIRONMENT) .clientId(clientId); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); activity.startService(intent); return PAY_PAL_UTILS; } //價格,貨幣碼(如:USD),商品名 public void startPay(BigDecimal price, String currentcy, String goodsName, String orderNumber) { PayPalItem[] items = {new PayPalItem(goodsName, 1, price, currentcy, orderNumber)}; PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails( new BigDecimal(0), price, new BigDecimal(0)); PayPalPayment payment = new PayPalPayment(price, currentcy , goodsName, PayPalPayment.PAYMENT_INTENT_SALE); payment.items(items).paymentDetails(paymentDetails); Intent intent = new Intent(activity, PaymentActivity.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment); activity.startActivityForResult(intent, REQUEST_CODE_PAY_PAL); } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_PAY_PAL && back != null) { if (resultCode == Activity.RESULT_OK) { PaymentConfirmation paymentResult = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION); back.onResult(paymentResult, paymentResult == null ? "payment result is null." : null); } else if (resultCode == Activity.RESULT_CANCELED) { back.onResult(null, "user canceled."); } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) { back.onResult(null, "An invalid Payment or PayPalConfiguration was submitted"); } else { back.onResult(null, "unknow error."); } } } public void onDestroy() { if (activity != null) { activity.stopService(new Intent(activity, PayPalService.class)); } activity = null; back = null; } public interface Back { public void onResult(PaymentConfirmation paymentResult, String errorMsg); } }
-
封裝代碼使用方法:
-
先實例化對象PayPalUtils.newInstance(),傳入3個參數,第一個參數爲activity本身,第二個參數爲clientid(可從paypal後臺獲取),最後是支付回調方法,當errorMsg爲空且paymentid不爲空說明回調成功,否則支付失敗。這裏貼出示例:
PayPalUtils payPalUtils = PayPalUtils.newInstance(this , getString(R.string.paypal_client_id)//此處爲paypalclientid , new PayPalUtils.Back() { @Override public void onResult(PaymentConfirmation paymentResult, String errorMsg) { if (errorMsg != null) { finishPay(errorMsg); } else if (paymentResult != null && paymentResult.getProofOfPayment() != null && paymentResult.getProofOfPayment().getPaymentId() != null) { //訂單號,上傳至服務器校驗 String paymentId = paymentResult.getProofOfPayment().getPaymentId(); } else { finishPay(getString(R.string.a_l_pay_pay_field)); } } });
-
PayPalUtils對象建議放成員變量位,方便其他地方使用。獲取好實例後記得在activity的onDestroy方法裏調用payPalUtils.onDestroy();以及在onActivityResult方法調用payPalUtils.onActivityResult(requestCode, resultCode, data);
-
最後最關鍵的調起支付方法(傳入3個參數,第一個參數爲價格,第二個參數爲幣碼,如美元爲USD,最後一個爲商戶訂單號,即自己的訂單號,當然這裏的訂單號也可以由服務器端生成或者用時間戳,自己抉擇就好。):,客戶端使用這個方法調起paypal支付後結果由之前的獲取實例對象的回調完成支付結果回調。
payPalUtils.startPay(new BigDecimal(currentItem.price), "USD", “OrderNumber”);
-
-
-
IOS端
-
首先是導入第三方jar,在Podfile內加入如下代碼,最後別忘了運行 pod install
pod 'PayPal-iOS-SDK'
-
導入完需要在頭文件加入如下代碼,同時如果發現報錯,需要按照下面截圖手動加入一些文件。
#import <AlipaySDK/AlipaySDK.h>
-
-
爲了方便以後直接使用,直接創建了一個工具類,方便直接調用,下面貼出代碼:
class PayPalUtils { static func initUtils(_ paypalLive: String, _ paypalSendBox: String, _ isSendBox: Bool) { PayPalMobile.initializeWithClientIds(forEnvironments: [ PayPalEnvironmentProduction: paypalLive , PayPalEnvironmentSandbox: paypalSendBox]) PayPalMobile.preconnect(withEnvironment: (isSendBox ? PayPalEnvironmentSandbox : PayPalEnvironmentProduction)) } static func startPay(viewController: UIViewController, payPalPaymentDelegate: PayPalPaymentDelegate , payAmount: Double, currencyCode: String, shortDescription: String) { let payPalConfiguration = PayPalConfiguration() payPalConfiguration.acceptCreditCards = true payPalConfiguration.payPalShippingAddressOption = PayPalShippingAddressOption.payPal payPalConfiguration.merchantName = NSLocalizedString("appName", comment: "") payPalConfiguration.languageOrLocale = NSLocale.preferredLanguages.first var payment = PayPalPayment() payment.amount = NSDecimalNumber.init(string: String(format: "%.2f", arguments: [payAmount])) payment.currencyCode = currencyCode payment.shortDescription = shortDescription payment.intent = PayPalPaymentIntent.sale if !payment.processable { print("訂單信息錯誤") return } let paymentViewController = PayPalPaymentViewController(payment: payment , configuration: payPalConfiguration, delegate: payPalPaymentDelegate) if paymentViewController != nil { viewController.present(paymentViewController! , animated: true) } else { print("paymentViewController init error.") } } }
-
完成這些步驟之後就是初始化paypal服務了,在AppDelegate.swift中初始化,下面貼核心代碼部分(代碼中用到了NSLocalizedString,也就是在Localizable.strings內賦值paypalLive和paypalSendBox,分別填入相應的ClientID,上面的截圖有說明):
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { PayPalUtils.initUtils(NSLocalizedString("paypalLive", comment: ""), NSLocalizedString("paypalSendBox", comment: ""), false) return true }
-
初始化完成之後在需要調起支付的ViewController下實現paypal的支付回調:
extension PlanCV: PayPalPaymentDelegate { func payPalPaymentDidCancel(_ paymentViewController: PayPalPaymentViewController) { //運行到這裏說明支付被取消 dismiss(animated: false) } func payPalPaymentViewController(_ paymentViewController: PayPalPaymentViewController , didComplete completedPayment: PayPalPayment) { do { let paymentId = try ((completedPayment.confirmation as NSDictionary).object(forKey: "response") as! [String: String])["id"] //可以將獲取的paymentId直接上傳至服務器處理,相關代碼後面服務器部分已經說明 } catch { //獲取失敗說明支付可能失敗,做失敗處理即可。 } dismiss(animated: false) } }
-
寫好回調相應處理之後就可以直接在需要的地方直接調起支付了,需要傳入5個參數,第一個參數爲viewController本身,所以這裏直接用了self,第二個爲回調實現,因爲也是基於ViewController實現的回調方法,這裏也直接用了self,第三個參數爲價格,寫商品價格即可,Double類型,第4個參數爲貨幣碼,如美元是USD,第5個參數爲商品名稱,最後貼上調用代碼:
PayPalUtils.startPay(viewController: self, payPalPaymentDelegate: self, payAmount: price , currencyCode: "USD", shortDescription: name)
-
服務器端
-
先貼一個http請求封裝工具
import javax.net.ssl.HttpsURLConnection; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.Proxy; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by marking on 2016/11/26. * 用於模擬http及https的got/post請求 * <uses-permission android:name="android.permission.INTERNET" /> */ public class HttpUtils { private String HTTPS = "https"; private String GET = "GET"; private String POST = "POST"; private static HttpUtils httpUtils; private HttpUtils() { } public static HttpUtils getInstance() { if (httpUtils == null) { httpUtils = new HttpUtils(); } return httpUtils; } public interface IWebCallback { void onCallback(int status, String message, Map<String, List<String>> heard, byte[] data); void onFail(int status, String message); } public byte[] getURLResponse(String urlString, HashMap<String, String> heads) { byte[] result = null; if (urlString != null) { HttpURLConnection conn = null; //連接對象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL對象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(GET); if (heads != null) { for (String key : heads.keySet()) { conn.addRequestProperty(key, heads.get(key)); } } is = conn.getInputStream(); //獲取輸入流,此時才真正建立鏈接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } result = baos.toByteArray(); } catch (Exception e) { } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } return result; } public void getURLResponse(String urlString, HashMap<String, String> heads, IWebCallback iWebCallback) { getURLResponse(urlString, heads, null, iWebCallback); } public void getURLResponse(String urlString, HashMap<String, String> heads, Proxy proxy, IWebCallback iWebCallback) { if (urlString != null) { HttpURLConnection conn = null; //連接對象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL對象 if (proxy == null) { if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } } else { if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(proxy); } else { conn = (HttpURLConnection) url.openConnection(proxy); } } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(GET); if (heads != null) { for (String key : heads.keySet()) { conn.addRequestProperty(key, heads.get(key)); } } is = conn.getInputStream(); //獲取輸入流,此時才真正建立鏈接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } if (iWebCallback != null) { iWebCallback.onCallback(conn.getResponseCode(), conn.getResponseMessage(), conn.getHeaderFields(), baos.toByteArray()); } } catch (Exception e) { int code = 600; try { code = conn == null ? 600 : conn.getResponseCode(); } catch (Exception e1) { } if (iWebCallback != null) { iWebCallback.onFail(code, e.toString()); } } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } } public byte[] postURLResponse(String urlString, HashMap<String, String> headers, byte[] postData) { byte[] result = null; if (urlString != null) { HttpURLConnection conn = null; //連接對象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL對象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(POST); //使用post請求 conn.setRequestProperty("Charsert", "UTF-8"); if (headers != null) { for (Map.Entry<String, String> temp : headers.entrySet()) { conn.setRequestProperty(temp.getKey(), temp.getValue()); } } conn.getOutputStream().write(postData); is = conn.getInputStream(); //獲取輸入流,此時才真正建立鏈接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } result = baos.toByteArray(); } catch (Exception e) { } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } return result; } public void postURLResponse(String urlString, HashMap<String, String> headers, byte[] postData, IWebCallback iWebCallback) { if (urlString != null) { HttpURLConnection conn = null; //連接對象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL對象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(POST); //使用post請求 conn.setRequestProperty("Charsert", "UTF-8"); if (headers != null) { for (Map.Entry<String, String> temp : headers.entrySet()) { conn.setRequestProperty(temp.getKey(), temp.getValue()); } } conn.getOutputStream().write(postData); is = conn.getInputStream(); //獲取輸入流,此時才真正建立鏈接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } if (iWebCallback != null) { iWebCallback.onCallback(conn.getResponseCode(), conn.getResponseMessage(), conn.getHeaderFields(), baos.toByteArray()); } } catch (Exception e) { int code = 600; try { code = conn == null ? 600 : conn.getResponseCode(); } catch (Exception e1) { } if (iWebCallback != null) { iWebCallback.onFail(code, e.toString()); } } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } } }
-
主要工具類,爲了方便使用,全放一個類裏邊了,另外由於返回的數據結構實在複雜,所以後面的對象代碼偏多,主要看前面幾個方法便好。
import com.alibaba.fastjson.JSON; import org.apache.tomcat.util.codec.binary.Base64; import java.util.ArrayList; import java.util.HashMap; public class PayPalUtils { // private static final String TOKEN_URL = "https://api.sandbox.paypal.com/v1/oauth2/token";//沙箱鏈接 // private static final String PAYMENT_DETAIL = "https://api.sandbox.paypal.com/v1/payments/payment/";//沙箱鏈接 private static final String TOKEN_URL = "https://api.paypal.com/v1/oauth2/token"; private static final String PAYMENT_DETAIL = "https://api.paypal.com/v1/payments/payment/"; private static final String clientId = "";//這兩個參數應該很容易在paypal開發者頁面找到,文中會貼出截圖 private static final String secret = ""; private static String getAccessToken() { byte[] resultBytes = HttpUtils.getInstance().postURLResponse(TOKEN_URL, new HashMap<String, String>() {{ put("Accept", "application/json"); put("Accept-Language", "en_US"); put("Authorization", "Basic " + Base64.encodeBase64String((clientId + ":" + secret).getBytes())); }}, "grant_type=client_credentials".getBytes()); ResponseToken result = resultBytes == null ? null : JSON.parseObject(new String(resultBytes), ResponseToken.class); return result == null ? null : result.accessToken; } private static ResponsePayPayl getResponsePayPayl(String paymentId) { String token = getAccessToken(); if (token == null) { System.out.println("verify paypal payment get token error."); return null; } byte[] resultBytes = HttpUtils.getInstance().getURLResponse(PAYMENT_DETAIL + paymentId , new HashMap<String, String>() {{ put("Accept", "application/json"); put("Authorization", "Bearer " + token); }}); return resultBytes == null ? null : JSON.parseObject(new String(resultBytes), ResponsePayPayl.class); } public static boolean isSuccess(String paymentId) { ResponsePayPayl responsePayPayl = getResponsePayPayl(paymentId); System.out.println("paypal.state=" + (responsePayPayl == null ? "null" : responsePayPayl.state)); return responsePayPayl != null && "approved".equals(responsePayPayl.state); } public static String getOrderNumber(String paymentId) { ResponsePayPayl responsePayPayl = getResponsePayPayl(paymentId); if (responsePayPayl != null && responsePayPayl.transactions != null && responsePayPayl.transactions.size() > 0 && responsePayPayl.transactions.get(0).itemList != null && responsePayPayl.transactions.get(0).itemList.items != null && responsePayPayl.transactions.get(0).itemList.items.size() > 0) { return responsePayPayl.transactions.get(0).itemList.items.get(0).sku; } return null; } public static class ResponsePayPayl { private String id; private String intent; private String state; private String cart; private Payer payer; private ArrayList<Transaction> transactions; private String createTime; private ArrayList<Link> links; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getIntent() { return intent; } public void setIntent(String intent) { this.intent = intent; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getCart() { return cart; } public void setCart(String cart) { this.cart = cart; } public Payer getPayer() { return payer; } public void setPayer(Payer payer) { this.payer = payer; } public ArrayList<Transaction> getTransactions() { return transactions; } public void setTransactions(ArrayList<Transaction> transactions) { this.transactions = transactions; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public ArrayList<Link> getLinks() { return links; } public void setLinks(ArrayList<Link> links) { this.links = links; } @Override public String toString() { return "ResponsePayPayl{" + "id='" + id + '\'' + ", intent='" + intent + '\'' + ", state='" + state + '\'' + ", cart='" + cart + '\'' + ", payer=" + payer + ", transactions=" + transactions + ", createTime='" + createTime + '\'' + ", links=" + links + '}'; } } public static class Transaction { private Amount amount; private Payee payee; private String description; private ItemList itemList; private ArrayList<RelatedResource> relatedResources; public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public Payee getPayee() { return payee; } public void setPayee(Payee payee) { this.payee = payee; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public ItemList getItemList() { return itemList; } public void setItemList(ItemList itemList) { this.itemList = itemList; } public ArrayList<RelatedResource> getRelatedResources() { return relatedResources; } public void setRelatedResources(ArrayList<RelatedResource> relatedResources) { this.relatedResources = relatedResources; } @Override public String toString() { return "Transaction{" + "amount=" + amount + ", payee=" + payee + ", description='" + description + '\'' + ", itemList=" + itemList + ", relatedResources=" + relatedResources + '}'; } } public static class RelatedResource { private Sale sale; public Sale getSale() { return sale; } public void setSale(Sale sale) { this.sale = sale; } @Override public String toString() { return "RelatedResource{" + "sale=" + sale + '}'; } } public static class Sale { private String id; private String state; private Amount amount; private String paymentMode; private String protectionEligibility; private String protectionEligibilityType; private TransactionFee transactionFee; private String parentPayment; private String createTime; private String updateTime; private ArrayList<Link> links; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getState() { return state; } public void setState(String state) { this.state = state; } public Amount getAmount() { return amount; } public void setAmount(Amount amount) { this.amount = amount; } public String getPaymentMode() { return paymentMode; } public void setPaymentMode(String paymentMode) { this.paymentMode = paymentMode; } public String getProtectionEligibility() { return protectionEligibility; } public void setProtectionEligibility(String protectionEligibility) { this.protectionEligibility = protectionEligibility; } public String getProtectionEligibilityType() { return protectionEligibilityType; } public void setProtectionEligibilityType(String protectionEligibilityType) { this.protectionEligibilityType = protectionEligibilityType; } public TransactionFee getTransactionFee() { return transactionFee; } public void setTransactionFee(TransactionFee transactionFee) { this.transactionFee = transactionFee; } public String getParentPayment() { return parentPayment; } public void setParentPayment(String parentPayment) { this.parentPayment = parentPayment; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getUpdateTime() { return updateTime; } public void setUpdateTime(String updateTime) { this.updateTime = updateTime; } public ArrayList<Link> getLinks() { return links; } public void setLinks(ArrayList<Link> links) { this.links = links; } @Override public String toString() { return "Sale{" + "id='" + id + '\'' + ", state='" + state + '\'' + ", amount=" + amount + ", paymentMode='" + paymentMode + '\'' + ", protectionEligibility='" + protectionEligibility + '\'' + ", protectionEligibilityType='" + protectionEligibilityType + '\'' + ", transactionFee=" + transactionFee + ", parentPayment='" + parentPayment + '\'' + ", createTime='" + createTime + '\'' + ", updateTime='" + updateTime + '\'' + ", links=" + links + '}'; } } public static class TransactionFee { private String value; private String currency; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } @Override public String toString() { return "TransactionFee{" + "value='" + value + '\'' + ", currency='" + currency + '\'' + '}'; } } public static class ItemList { private ArrayList<Item> items; private ShippingAddress shippingAddress; public ArrayList<Item> getItems() { return items; } public void setItems(ArrayList<Item> items) { this.items = items; } public ShippingAddress getShippingAddress() { return shippingAddress; } public void setShippingAddress(ShippingAddress shippingAddress) { this.shippingAddress = shippingAddress; } @Override public String toString() { return "ItemList{" + "items=" + items + ", shippingAddress=" + shippingAddress + '}'; } } public static class Item { private String name; private String sku; private String price; private String currency; private String tax; private int quantity; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSku() { return sku; } public void setSku(String sku) { this.sku = sku; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public String getTax() { return tax; } public void setTax(String tax) { this.tax = tax; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } @Override public String toString() { return "Item{" + "name='" + name + '\'' + ", sku='" + sku + '\'' + ", price='" + price + '\'' + ", currency='" + currency + '\'' + ", tax='" + tax + '\'' + ", quantity=" + quantity + '}'; } } public static class Payee { private String merchantId; public String getMerchantId() { return merchantId; } public void setMerchantId(String merchantId) { this.merchantId = merchantId; } @Override public String toString() { return "Payee{" + "merchantId='" + merchantId + '\'' + '}'; } } public static class Amount { private String total; private String currency; private Details details; public String getTotal() { return total; } public void setTotal(String total) { this.total = total; } public String getCurrency() { return currency; } public void setCurrency(String currency) { this.currency = currency; } public Details getDetails() { return details; } public void setDetails(Details details) { this.details = details; } @Override public String toString() { return "Amount{" + "total='" + total + '\'' + ", currency='" + currency + '\'' + ", details=" + details + '}'; } } public static class Details { private String subtotal; public String getSubtotal() { return subtotal; } public void setSubtotal(String subtotal) { this.subtotal = subtotal; } @Override public String toString() { return "Details{" + "subtotal='" + subtotal + '\'' + '}'; } } public static class Link { private String links; private String rel; private String method; public String getLinks() { return links; } public void setLinks(String links) { this.links = links; } public String getRel() { return rel; } public void setRel(String rel) { this.rel = rel; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } @Override public String toString() { return "Link{" + "links='" + links + '\'' + ", rel='" + rel + '\'' + ", method='" + method + '\'' + '}'; } } public static class Payer { private String paymentMethod; private String status; private PayerInfo payerInfo; public String getPaymentMethod() { return paymentMethod; } public void setPaymentMethod(String paymentMethod) { this.paymentMethod = paymentMethod; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public PayerInfo getPayerInfo() { return payerInfo; } public void setPayerInfo(PayerInfo payerInfo) { this.payerInfo = payerInfo; } @Override public String toString() { return "Payer{" + "paymentMethod='" + paymentMethod + '\'' + ", status='" + status + '\'' + ", payerInfo=" + payerInfo + '}'; } } public static class PayerInfo { private String email; private String firstName; private String lastName; private String payerId; private ShippingAddress shippingAddress; private String phone; private String countryCode; public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getPayerId() { return payerId; } public void setPayerId(String payerId) { this.payerId = payerId; } public ShippingAddress getShippingAddress() { return shippingAddress; } public void setShippingAddress(ShippingAddress shippingAddress) { this.shippingAddress = shippingAddress; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } @Override public String toString() { return "PayerInfo{" + "email='" + email + '\'' + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", payerId='" + payerId + '\'' + ", shippingAddress=" + shippingAddress + ", phone='" + phone + '\'' + ", countryCode='" + countryCode + '\'' + '}'; } } public static class ShippingAddress { private String recipientName; public String getRecipientName() { return recipientName; } public void setRecipientName(String recipientName) { this.recipientName = recipientName; } @Override public String toString() { return "ShippingAddress{" + "recipientName='" + recipientName + '\'' + '}'; } } public static class ResponseToken { private String scope; private String nonce; private String accessToken; private String tokenType; private String appId; private int expiresIn; public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } public String getNonce() { return nonce; } public void setNonce(String nonce) { this.nonce = nonce; } public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public String getTokenType() { return tokenType; } public void setTokenType(String tokenType) { this.tokenType = tokenType; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } @Override public String toString() { return "ResponseToken{" + "scope='" + scope + '\'' + ", nonce='" + nonce + '\'' + ", accessToken='" + accessToken + '\'' + ", tokenType='" + tokenType + '\'' + ", appId='" + appId + '\'' + ", expiresIn=" + expiresIn + '}'; } } }
-
最後是工具類PayPalUtils的使用方法,主要分2種,一種是直接判斷是否支付成功的isSuccess(),一種是獲取客戶端生成的訂單號(可能包含產品信息等)getOrderNumber(),兩者都是傳入一個參數,即客戶端上傳的paymentId,當然也可以根據自己的喜好改動,裏邊的getResponsePayPayl()方法可以獲取返回的所有信息。樓主使用的是getOrderNumber(),另外爲了給paypal足夠的處理時間,建議如果一次獲取不到訂單號或者判斷支付失敗的可進行多次間隔校驗。
-