提醒一下,題主是在快速標准支付做到一半的時候換成了標准支付,所以該文檔的快速支付大家做個參考就可以了.
一、兩種支付方式
-
標准支付
- 優點:純前端對接,簡單方便,適用於非技術開發人員.個人即可用,不用花一個月時間進行商家認證(需要營業執照)
- 缺點:對接簡單也就意味着無法執行復雜的工作,無法進行回調(因為本身就是給非技術開發人員使用的,如果這里有人發現可以回調請記得回來打我的臉!)
使用
-
快速支付
- 優點:可以進行回調,對接較為復雜的業務
- 缺點:開發難度大,需要相關的營業資質
二、沙盒使用
地址:https://developer.paypal.com/developer/applications/
為什么要使用沙盒環境:
- 快速支付的開通需要對應有國內相關的營業執照,但是通過沙盒環境我們可以直接獲得一個僅在沙盒環境下可用的商家app
- paypal作為國外的支付手段是無法直接使用國內的銀行卡支付的,需要使用visa等卡
使用:
- 創建相關賬號
- 點擊
Sandbox -> account
,進入主頁的account下,分別創建一個商家賬號和買家賬號 - (標准支付)登陸https://www.sandbox.paypal.com/,創建按鈕
- (快速支付)點擊
Dashboard -> My Account
,以商家賬號為基礎創建一個app,在開發快速支付時使用
三、標准支付
-
創建賬號
-
創建相關的按鈕,即生成對應的html代碼
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> <input type="hidden" name="cmd" value="_s-xclick"> <input type="hidden" name="hosted_button_id" value="D7U8ME8UVW5MG"> <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif" border="0" name="submit" alt="PayPal——最安全便捷的在線支付方式!"> <img alt="" border="0" src="https://www.paypalobjects.com/zh_XC/i/scr/pixel.gif" width="1" height="1"> </form>
-
將代碼嵌入到對應的頁面即可(這里不放相關的代碼了,因為都是和業務深度內嵌的)
-
補充:
- 按鈕的代碼可以定制不同的規格選項
- 看清楚按鈕的本質:將相關的cmd,hosted_button_id等參數以post形式傳送到https://www.paypal.com/cgi-bin/webscr,返回一個對應的支付頁面
- 如果按鈕的排版布局無法滿足你的要求,比如你需要將不同的支付手段(如微信支付)集成到同一個按鈕,可以設置一個能選擇不同支付手段的按鈕選項,根據這個選項間接地用js調用paypal支付按鈕
- paypal不支持國內的支付手段,支付需要使用VISA
四、快速支付
注:
- 本代碼主要參考了這篇博客.遺憾的是,這篇博客距今已經有三年歷史了,所以其實本人還使用了其它的博客進行參考,由於篇幅所限就不一一列舉了.
- 由於本人沒有visa的卡+該方案最終沒有被采納(因為相關資質的審核需要30天),實際本代碼的可用性僅到訂單生成為止,還無法確定回調是否可行
-
創建相關賬號
-
獲得app(這里具體的地址應該和沙盒一樣,遺憾的是我個人並沒有實際使用過)
-
sdk下載:
-
開發
public Payment createPayment(Map<String,String> paraMap) throws PayPalRESTException { Transaction transaction = new Transaction(); transaction.setDescription("icwlRegister"); // 將我們的訂單ID保存到支付信息中,用於后面支付回傳 if (null != paraMap.get("user_id")) { transaction.setCustom(paraMap.get("user_id")); } /** * 訂單價格 * 注意兩個公式: * 1. total = subtotal(商品總額) + tax(稅) + shopping(郵費) + other * 2. subtotal = product1*num1+... * 注意:如果有優化活動的話要坑 */ Amount amount = new Amount(); // 設置各種費用 amount.setCurrency("USD"); //其實在paypal的返回值有說什么是哪個類哪個字段的問題 // 商品總價 amount.setTotal(paraMap.get("order_amount")); Details details = new Details(); details.setSubtotal(paraMap.get("order_amount")); // 稅費 details.setTax("0"); amount.setDetails(details); transaction.setAmount(amount); ItemList itemList = new ItemList(); //收獲地址不設置 /** * 商品明細 */ List<Item> items = new ArrayList<>(); Item item = new Item(); item.setSku("PRODUCT0000001"); item.setName("register"); item.setPrice(paraMap.get("order_amount")); item.setQuantity("1"); item.setCurrency("USD"); //貨幣種類,注意應該不支持人民幣 items.add(item); itemList.setItems(items); transaction.setItemList(itemList); List<Transaction> transactions = new ArrayList<>(); transactions.add(transaction); /** * 支付信息 */ Payer payer = new Payer(); payer.setPaymentMethod(PaypalPaymentMethod.paypal.toString()); Payment payment = new Payment(); payment.setIntent(PaypalPaymentIntent.sale.toString()); payment.setPayer(payer); payment.setTransactions(transactions); /** * 回調地址 */ RedirectUrls redirectUrls = new RedirectUrls(); redirectUrls.setReturnUrl("http://..."); //成功支付后的回調地址 redirectUrls.setCancelUrl("www.baidu.com"); //支付失敗后的回調地址 payment.setRedirectUrls(redirectUrls); System.out.println("調用之前:" + payment); // 創建paypal API對象 APIContext apiContext = new APIContext(paypalConfigBean.getClientId(), paypalConfigBean.getClientSecret(), paypalConfigBean.getMode()); return payment.create(apiContext); } @Override public String paypalService(Map map) throws PayPalRESTException { HashMap<String, Object> resMap = new HashMap<>(); //paypal Payment payment = createPayment( map ); //訂單成功的回調地址 System.out.println("調用之后:" + payment); for(Links links : payment.getLinks()){ if(links.getRel().equals("approval_url")){ resMap.put("url",links.getHref()); } } //數據庫操作 map.put("payment_id",payment.getId()); //獲得paypal的唯一識別id System.out.println(map.get("payment_id")); Integer maxUserId = userMapper.getMaxUserId(); Integer id = maxUserId==null?1:maxUserId+1; System.out.println("id:" +id); map.put("user_id",id.toString()); userMapper.addUser(map); resMap.put("id",id); return JsonUtil.toJsonString(resMap); } @Override public void paypalNotify(String paymentId) { Integer userId = userMapper.getUserIdByPaymentId(paymentId); if(userId != null){ String dateFormat = "yyyy-MM-dd HH:mm:ss"; SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); userMapper.updateUserById(userId,sdf.format(new Date())); }else{ System.out.println("Wrong!"); } } @Override public String getUserId(Map map) { Integer maxUserId = userMapper.getMaxUserId(); Integer id = maxUserId==null?1:maxUserId+1; map.put("user_id",id); userMapper.addUser(map); //結果集 Map<String, Object> resMap = new HashMap<String, Object>(); resMap.put("userId",id); return JsonUtil.toJsonString(resMap); }
注:
-
這里的代碼參考意義更強一些,因為沒有完工,很爛(留着給自己做個記錄吧)
-
訂單價格的兩個公式(如果不正確也是會報錯的):
1. total = subtotal(商品總額) + tax(稅) + shopping(郵費) + other 2. subtotal = product1*num1+..
-
-
總結一下
- paypal支付的對接過程在我看來是非常糟心的,因為缺少相關的中文文檔(自己這方面的能力的確還不足)
- 相關的api設置還不夠完善,曾經的微信支付的api也是亂七八糟的,但現在都有了比較統一的接口.就比如關於價格的嚴格規則,其實就可以做成api調用,即總價格由計算得出,當然可能paypal本身的考慮也可能是為了使開發者避免單價價格和稅率,總價的不一致性,那么我只能說這波paypal是在大氣層!