iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Modern Web

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

Day21:21 - 結帳服務(5) - 後端 - 結帳 X PayPal Python Checkout SDK

Salom,我是Charlie!

在Day20的時候我們完成了createOrder跟CaptureOrder的Client,今天我們將把後端的結帳跟兩個Client結合在一起。

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

首先是創立訂單的部分,先在userorder當中建立在創立訂單時,使用createOrderClient建立paypal金流的部分:

try:
	paypalresponse = CreateOrder().create_order(CURRENCY_CODE,totalvalue)
except Exception as e:
	return R.internalServerError(str(e))
else:
	data = fromPaypalResponse(paypalresponse)
	return R.ok(data)

因為paypalResponse不是json data所接受的格式,所以在下面建立fromPaypalResponse的方法:

def fromPaypalResponse(response):
	data = {}
	data["code"] = response.status_code
	data["status"] = response.result.status
	data["orderid"] = response.result.id
	data["intent"] = response.result.intent
	data["links"] = {}
	for link in response.result.links:
		data["links"][link.rel] = link.href
	data["total_Amount"] = response.result.purchase_units[0].amount.value
	return data

接著使用POSTMAN測試:
https://ithelp.ithome.com.tw/upload/images/20211005/20141666JMW8BLIPCU.png

再來是captureOrder的部分,先建立url的部分:

url(r'/capture/(?P<orderID>[\w+]{1,55})$',views.captureOrder),

接著在views當中建立captureOrder方法,使用CaptureOrderClient來收款:

@logincheck('POST')
def captureOrder(request,orderID = None):
	if not orderID:
		return R.badRequest("order id does not exist")
	if request.method == "POST":
		try:
			response = CaptureOrder().capture_order(orderID)
		except Exception as e:
			return R.internalServerError(str(e))
		else:
			return R.ok(fromCaptureResponse(response))
	else:
		return R.methodNotAllowed("method not allowed")

接著建立fromCaptureResponse方法,把capture傳回的結果化為json:

def fromCaptureResponse(response):
	data = {}
	data["code"] = response.status_code
	data["status"] = response.result.status
	data["orderid"] = response.result.id
	data["links"] = {}
	for link in response.result.links:
		data["links"][link.rel] = link.href
	data["capture"] = []
	for purchase_unit in response.result.purchase_units:
		for capture in purchase_unit.payments.captures:
			data["capture"].append(capture.id)
	return data

測試,如果已經capture過的話會出現錯誤,如果第一次capture則會正常:
https://ithelp.ithome.com.tw/upload/images/20211005/20141666SVRgg42j7c.png

接著我們還要做一件事情:將paypal order id加入我們的資料庫。

如果用戶尚未付款的話,在訂單詳情頁面一樣能按下付款,同時,如果capture過了,必須要記錄訂單狀態為paid。

所以我們先在models裡面建立新欄位:

class Order(models.Model):
	id = models.AutoField(primary_key = True)
	orderno = models.CharField(max_length = 255,verbose_name = "訂單編號")
	product = models.ForeignKey(Product,on_delete = models.CASCADE)
	user = models.ForeignKey(User,on_delete = models.CASCADE)
	amount = models.IntegerField(verbose_name = "商品數量")
	status = models.IntegerField(verbose_name = "狀態")
	paypal_id = models.CharField(max_length = 255,verbose_name = "paypal訂單編號")
	created_time = models.DateTimeField(auto_now = True)
	modified_time = models.DateTimeField(auto_now = True)

	class Meta:
		db_table = "orders"

並且執行遷移:

$ python manage.py makemigrations userorder
$ python manage.py migrate userorder

接著我們修改createOrder的程式碼,創建paypal訂單後把cart狀態設為deactivate,並且儲存order item:

totalvalue = 0
for cart in usercart:
	totalvalue += cart.amount * cart.product.price
try:
	paypalresponse = CreateOrder().create_order(CURRENCY_CODE,totalvalue)
except Exception as e:
	return R.internalServerError(str(e))
else:
	data = fromPaypalResponse(paypalresponse)
	paypal_id = data["orderid"]
	for cart in usercart:
		cart.status = CartStatus.deactivate.value
		cart.save()
		userorder = Order.objects.create(
			orderno = orderno,
			product = cart.product,
			user = cart.user,
			amount = cart.amount,
			status = OrderStatus.notPaid.value,
			paypal_id = paypal_id
		)		
	return R.ok(data)

https://ithelp.ithome.com.tw/upload/images/20211005/20141666kWTH1Q2y8Y.png
https://ithelp.ithome.com.tw/upload/images/20211005/20141666u7hiLYgLS8.png

接著到captureOrder,加上改變訂單狀態的程式碼:

if request.method == "POST":
	try:
		response = CaptureOrder().capture_order(orderID)
	except Exception as e:
		return R.internalServerError(str(e))
	else:
		orders = Order.objects.filter(paypal_id = orderID)
		for order in orders:
			order.status = OrderStatus.paid.value
			order.save()
		return R.ok(fromCaptureResponse(response))

測試:
https://ithelp.ithome.com.tw/upload/images/20211005/20141666hRv8TDRPc0.png
https://ithelp.ithome.com.tw/upload/images/20211005/20141666KqczKtcMNI.png

如此,我們就先完成了後端的結帳部分。

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

Day21結束了!在今天我們完成了paypal跟後端交互的部分,而明天我們將完成前端的結帳結合Paypal的部分,See ya next day!


上一篇
Day20:20 - 結帳服務(4) - PayPal Python Checkout SDK(2)
下一篇
Day22:22 - 結帳服務(6) - 前端 - 結帳 X PayPal付款
系列文
30天肝出購物網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言