前情提要
之前用React框架做過一個網站的開發,客戶是國外的公司,所以為迎合受眾,支付模塊添加了我國不常用但國外常用的Paypal。最近在整理文檔,就把當時寫的這篇經驗總結再整合以下發布。
總結
- 簡單做一個開發准備總結:
申請一個PayPal商家賬號。
使用賬號登錄paypal,找到`sandbox`,可以看到默認的app和創建。
可以創建一個用於本項目的app,獲取`client_id`。至此,基本就可以開始着手開發了。
-
依賴。
項目使用的是React框架開發,在項目中安裝了`
react-paypal-js`
sdk
- 配置。
由於裝了react-paypal-js,以下總結全是基於此依賴的配置及使用。
在我們的支付賬單頁面,從依賴中引入PayPalScriptProvider
,以標簽的形式使用。標簽的options
屬性,就是我們進行配置的位置。實例為:
import { PayPalScriptProvider } from "@paypal/react-paypal-js" export default function PayPalPaymentElement() { return ( <PayPalScriptProvider options={{ "client_id": "開發准備中在sandbox拿到的client_id或者后端傳過來的" "currency": "收取的貨幣,如果不設置默認為USD" }}> /**這里為PayPalButtons載入的位置,PayPalButtons只能在此環境中執行*/ </PayPalScriptProvider> ) }
注意:options屬性,client_id
是必須的。項目上線前將此換為真實商家賬戶client_id。
如果貨幣不是美元,必須為其添加`currency`並指定幣種。
-
PayPalButtons
paypal.Buttons,實現點擊打開paypal支付頁面,以及集成支付。
在
paypal-react-js
提供了PayPalButtons
快速集成。關於PayPalButtons的樣式等可參考官方地址根據需求修改。說一下幾個常用屬性。
1.
createOrder
創建paypal支付訂單時的方法,常用於支付集成。包括地址、總價等訂單詳情。
const createOrder = (data: any, actions: any) => {
return actions.order.create({ purchasee_units: [{ amount: { value: 12,//總價金額 currency_code: "USD",//貨幣 breakdown: { item_total: {...},//商品總價 shipping: {...},//運費 discount: {...},//折扣 }, shipping: { name: { full_name: "John Doe",//只支持full_name }, type: "SHIPPING",//郵寄方式,可選值還有"PICKUP_IN_PERSON" address: {...}//地址 } } }], application_context: { brand_name: "Sale",//品牌名 shipping_prefrence: "SET_PROVIDED_ADDRESS",//地址欄顯示 }, payer: {...},//消費者信息 }).then((orderID: any) => {}); }; <PayPalButtons style={{ layout: "horizontal", shape: "rect", }} createOrder={createOrder} />
`action.order.create({})`有四個options分別為`intent`、`payer`、`purchase_units`、`application_context`, createOrder官方文檔地址
注1:purchase_unit對象定義1 、purchase_unit對象定義2
注2:application_context對象定義,實際開發中,這個對象的`brand_name`以及`shipping_perfrence`都是使用頻率較高的。
當有這樣一個需求:配送地址由用戶在網站上選擇,paypal上僅展示地址不可更改,這時`shipping_perfence`是最好的實現方式(至少在我做的這個項目時是如此),要完成這個需求,我們僅需要進行以下集成:
application_context: { shipping_prefrence: "SET_PROVIDED_ADDRESS"//由網站提供,用戶可查看但無法更改 //"NO_SHIPPING": 一般用於售賣的數字等無實物產品,支付頁面不顯示地址欄 //"GET_FROM_FILE": 來源於用戶在當前支付頁面地址欄選中的地址 }
注3:payer對象定義
2.onApprove
當訂單確認之后的回調
const onApprove = (data: any, actions: any) => { return actions.order.capture().then(funtions (details: any) {}) } <PayPalButtons style={{ layout: "horizontal", shape: "rect", }} createOrder={createOrder} onApprove={onApprove} />
3.onCancel
當關閉paypal支付頁面,取消支付時的回調
const onCancel = (data: any) => {} <PayPalButtons style={{ layout: "horizontal", shape: "rect", }} createOrder={createOrder} onCancel={onCancel} />
4.onError
當執行出錯時的回調
const onError = (err: any) => {} <PayPalButtons style={{ layout: "horizontal", shape: "rect", }} createOrder={createOrder} onError={onError} />
5.其他...
關於使用PayPalButtons踩過的坑(或者說因缺乏經驗而走的彎路),在這里單獨列出來
問題描述:
在支付頁面,點擊以西paypal支付按鈕,再取消支付。
在頁面不刷新、路由不跳轉的前提下更改商品數量(或者郵寄方式/地址,目的為與上次點擊的支付詳情區別開)。
點擊paypal支付按鈕,此時paypal支付金額/地址與上一次點擊的沒有區別,也就是說訂單詳情沒有更新。
檢索問題&解決:
一開始發現這個問題,第一反應是組件沒有從新渲染,或者數據沒有動態更新。順着這個思路開始測試,結果發現組件及數據都有更新。啊這...
會不會是PayPal的問題?發現有`onInit/onClick`方法,借助這個方法測試一下每次點擊的時候打印傳入的數據。結果居然每次點擊的時候傳入的數據都沒有更新!!!我不理解啊組件和數據都更新了,為什么傳入的數據沒更新????
會不會PayPalButtons沒有重渲?在官方文檔找了半天只找到一個render方法,但是我用sdk根本不用自己手寫這個方法啊喂!!!
嘗試換一個文檔在react-paypal-js里看看,可惡,居然一進來就看到一個`forceReRender`
文檔源地址 看看描述:用於重新重新渲染組件。當更改這個prop時,會銷毀當前按鈕並且以當前props的值重渲!!!這不就正是我要找的嗎!用起來
<PayPalButtons style={{ layout: "horizontal", shape: "rect", }} createOrder={createOrder} forceReRender={[ totalprice, shippingAddress, shippingPrice, ... ]} />
再執行一次剛剛發現問題的步驟,問題解決!!
果然,用什么東西就應該先看什么文檔。
總結來說,這個問題出現的原因是:支付頁面不是分步執行,即沒有一步一更新,這導致數據更新時,PayPalButtons未重渲。不清楚使用原生方法編寫有沒有這個問題,畢竟官方好像只有render方法(或者有別的只是我沒找到),之后可以實踐或者關注社區看看...