ನಮಸ್ಕಾರ,我是Charlie!
在Day19當中我們完成了Paypal的註冊並且試著發了request,在今天我們將看paypal的發送request規則,並且實際使用python checkout sdk試試看。
================================◉‿◉=================================
首先是paypal request的格式的部分,先看一下我們上次打create order api的資料:
{
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {
"currency_code": "USD",
"value": "100.00"
}
}
]
}
這裡面有兩個參數:intent跟purchase_unit。
首先是intent,intent是這個request最終的目的,有兩種參數可以傳入:
Capture: 當order要在payment成立後capture時傳入的參數,通常create order會使用此intent。
Authorize:授權,如果沒有要在payment成立後立即capture,使用此參數。
再來是purchase_unit的部分,purchase_unit指的是購買的單位,裡面的amount又分為currency_code跟value的部分:
currency_code:貨幣,詳細的貨幣單位可以參考此網站:https://developer.paypal.com/docs/api/reference/currency-codes/,遵守three-character ISO-4217規範。
value:價格,item要支付的所有價格。
以上是最小規格的order request body,像amount的話會有breakdown,可以分成像是tax、shipping等等的。
但是在應用程式使用paypal sdk當中,還需要另外一個參數:application_context。這裏面裝了一些應用程式所需的資訊跟動作,我們可以直接到python paypal sdk的github page,看到capture order裡面的build_request_body的資料格式:
{
"intent": "CAPTURE",
"application_context": {
"return_url": "https://www.example.com",
"cancel_url": "https://www.example.com",
"brand_name": "EXAMPLE INC",
"landing_page": "BILLING",
"shipping_preference": "SET_PROVIDED_ADDRESS",
"user_action": "CONTINUE"
}, .....
裡面有一些比較重要的參數,像是:
return_url:payment成功後,需要前往的url
cancel_url:payment取消後,需要前往的url
這兩個是最需要設定的部分,在使用者進行付款後,轉回我們自己原本的頁面。
所以這裡的流程會是:
使用者點擊結帳按鈕 => 前端呼叫後端create order api => 後端create order api利用paypal checkout sdk打paypal api => 後端取得連結傳回前端 => 前端將使用者導入付款頁面 => 使用者付款 or 取消 => 返回各自頁面
而capture的話就是使用url中帶order_id來做capture,一樣需要Authorization的部分。
而Python checkout sdk就是直接幫我們帶了Authorization,讓我們只要使用createOrder跟captureOrder就可以了。
接下來是Python checkout sdk,先使用pip install來安裝:
$ pip install paypal-checkout-serversdk
安裝完後,到我們的後端專案,在payaplTools裡面建立三個py檔:
createOrderClient.py
captureOrderClient.py
paypalClient.py
接著到manage.py,設定環境變數:
os.environ.setdefault('PAYPAL_CLIENT_ID','Your default client id')
os.environ.setdefault('PAYPAL_CLIENT_SECRET','Your default client secret')
然後到tools\paypalClient中,建立paypalClient class:
import os
from paypalcheckoutsdk.core import PayPalHttpClient,SandboxEnvironment
import sys
class PaypalClient:
def __init__(self):
self.client_id = os.environ["PAYPAL_CLIENT_ID"] if 'PAYPAL_CLIENT_ID' in os.environ else ""
self.client_secret = os.environ["PAYPAL_CLIENT_SECRET"] if 'PAYPAL_CLIENT_SECRET' in os.environ else ""
self.environment = SandboxEnvironment(
client_id = self.client_id,
client_secret = self.client_secret
)
self.client = PayPalHttpClient(self.environment)
接著先建立createOrderClient:
from paypalTools.paypalClient import PaypalClient
from paypalcheckoutsdk.orders import OrdersCreateRequest
RETURN_URL = "http://localhost:8000/#/orderCreated"
CANCEL_URL = "http://localhost:8000/#/orderCanceled"
class CreateOrder(PaypalClient):
@staticmethod
def build_request_body(currency_code,value):
print("currency_code is:",currency_code)
return \
{
"intent":"CAPTURE",
"application_context":{
"return_url":RETURN_URL,
"cancel_url":CANCEL_URL,
"brand_name":"鍵盤貿易",
"landing_page":"BILLING",
},
"purchase_units":[
{
"amount":{
"currency_code":currency_code,
"value":value
}
}
]
}
def create_order(self,currency_code,value,debug = False):
request = OrdersCreateRequest()
request.headers['prefer'] = 'return=representation'
request.request_body(self.build_request_body(currency_code,value))
response = self.client.execute(request)
if debug:
print(response.result)
return response
然後使用python manage.py shell進入django環境,並且引入createOrderClient進行請求:
from paypalTools.createOrderClient import CreateOrder
CreateOrder().create_order("TWD",100,debug=True)
如果印出HttpResponseObject即代表發送成功:
接著我們美化一下output:
def create_order(self,currency_code,value,debug = False):
request = OrdersCreateRequest()
request.headers['prefer'] = 'return=representation'
request.request_body(self.build_request_body(currency_code,value))
response = self.client.execute(request)
if debug:
print("Status code:",response.status_code)
print("Status:",response.result.status)
print("Order ID:",response.result.id)
print("intent:",response.result.intent)
print("links:")
for link in response.result.links:
print("\t{}: {}\tCall Type: {}".format(link.rel,link.href,link.method))
print("total Amount: {} {}".format(response.result.purchase_units[0].amount.currency_code,
response.result.purchase_units[0].amount.value))
return response
在此先筆記下order_id,然後前往apporve url用測試帳號付款:
再來是capture order的部分,這裡我們需要order id傳入:
from paypalTools.paypalClient import PaypalClient
from paypalcheckoutsdk.orders import OrdersCaptureRequest
class CaptureOrder(PaypalClient):
def capture_order(self,order_id,debug = False):
request = OrdersCaptureRequest(order_id)
response = self.client.execute(request)
if debug:
print("Status code:",response.status_code)
print("Status:",response.result.status)
print("Order ID:",response.result.id)
print("links:")
for link in response.result.links:
print("\t{}: {}\tCall Type: {}".format(link.rel,link.href,link.method))
for purchase_unit in response.result.purchase_units:
for capture in purchase_units.payments.captures:
print('\t',capture.id)
return response
測試:
接著到餘額處看,可以看到餘額有變動:
接著到API呼叫紀錄中,可以看到已經呼叫過的紀錄:
如此我們就先完成了Client的部分。
================================◉‿◉=================================
Day20結束了!在今天我們講到了Paypal checkout sdk,還有如何使用,而明天我們將把Client跟結帳結合在一起,See ya next day!