本文章仅作为个人笔记
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足够的处理时间,建议如果一次获取不到订单号或者判断支付失败的可进行多次间隔校验。
-