前情提要
之前用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方法(或者有別的只是我沒找到),之後可以實踐或者關注社群看看...