iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
Modern Web

30天肝出購物網站系列 第 20

Day20:20 - 結帳服務(4) - PayPal Python Checkout SDK(2)

  • 分享至 

  • xImage
  •  

ನಮಸ್ಕಾರ,我是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的資料格式:

https://github.com/paypal/Checkout-Python-SDK/blob/develop/sample/CaptureIntentExamples/create_order.py

{
     "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即代表發送成功:
https://ithelp.ithome.com.tw/upload/images/20211004/20141666O9YvUGZ7vX.png

接著我們美化一下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

https://ithelp.ithome.com.tw/upload/images/20211004/20141666wLwqeqEXzk.png

在此先筆記下order_id,然後前往apporve url用測試帳號付款:
https://ithelp.ithome.com.tw/upload/images/20211004/20141666lzYInoNNOD.png

https://ithelp.ithome.com.tw/upload/images/20211004/20141666sc7p5Wc6cZ.png

https://ithelp.ithome.com.tw/upload/images/20211004/20141666QMNNoPHlUy.png

再來是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

測試:
https://ithelp.ithome.com.tw/upload/images/20211004/20141666WZnzpnOW68.png

接著到餘額處看,可以看到餘額有變動:
https://ithelp.ithome.com.tw/upload/images/20211004/20141666xyHTUk6dMk.png

接著到API呼叫紀錄中,可以看到已經呼叫過的紀錄:
https://ithelp.ithome.com.tw/upload/images/20211004/20141666F1M4MW48vo.png

如此我們就先完成了Client的部分。

================================◉‿◉=================================

Day20結束了!在今天我們講到了Paypal checkout sdk,還有如何使用,而明天我們將把Client跟結帳結合在一起,See ya next day!


上一篇
Day19:19 - 結帳服務(3) - PayPal Python Checkout SDK(1)
下一篇
Day21:21 - 結帳服務(5) - 後端 - 結帳 X PayPal Python Checkout SDK
系列文
30天肝出購物網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言