Skip to main content

เพิ่ม Proxy และ checkout

เพิ่ม config proxy

  • โดยปกติ เราจะมีการป้องกัน CORS เอาไว้่เพื่อไม่ให้ domain ใดๆยิงเข้ามาโดยตรงได้
  • เราจะทำแบบเดียวกัน โดยเราจะให้ proxy เข้า cloud function ในฐานะ host เดียวกันเพื่อไม่ติด CORS

ที่ vite.config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
server: {
proxy: {
'/api': { // เพิ่มตรงนี้เข้ามา
target: 'http://127.0.0.1:5010/<project_name>/us-central1/api',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
}
}
},
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

เมื่อ setup เรียบร้อย จากนี้เวลายิงเข้า

http://127.0.0.1:5010/<project_name>/us-central1/api/placeorder

จะมีค่าเทียบเท่ากับ path นี้ เมื่อยิงผ่าน /api ของ path vue

http://127.0.0.1:5173/api/placeorder

ลง axios และ ยิง API

  • ลง library axios สำหรับยิง API เข้า POST /api/placeorder ในฝั่ง Backend
  • ส่ง token ผ่าน header ของ axios และปั้น request body หน้าตาแบบที่ spec กำหนดเอาไว้
  • return มาเป็น success url (บทนี้เราจะแค่ console.log เอาไว้ก่อน เราจะมาเชื่อมให้ครบในบท omise)

ลง library axios โดย

npm install axios

ที่ stores/user/cart.js

  • เอา localstorage ทั้งหมดออกไป (ไม่ได้ใช้แล้วสำหรับเคส checkout)
  • ประกอบ checkout object ให้ถูกต้องก่อนส่งเข้า axios ตาม spec ที่กำหนดกันไว้
  • ยิง await axios.post('/api/placeorder') ด้วย object checkout และ access token ใน header (กรณีที่ login user)
import axios from 'axios'

export const useUserCartStore = defineStore('user-cart', {
state: () => ({
items: [],
checkout: {}
}),
getters: {
summaryPrice (state) {
return state.items.reduce((acc, item) => acc + (item.price * item.quantity), 0)
},
quantity (state) {
return state.items.reduce((acc, item) => acc + item.quantity, 0)
},
user (state) {
const accountStore = useAccountStore()
return accountStore.user
},
cartRef (state) {
return ref(realtimeDB, `carts/${this.user.uid}`)
}
},
actions: {
/* code เหมือนเดิม */
async checkout (checkoutData) {
try {
let checkout = {
...checkoutData,
products: this.items.map(product => ({
productId: product.productId,
quantity: product.quantity
}))
}

const response = await axios.post('/api/placeorder', {
source: 'test-source-id', // mock ไว้ก่อน เดี๋ยวเราจะมาปรับตอน omise
checkout
}, {
headers: {
'Authorization': this.user.accessToken // ดึง access token จาก Firebase Authentication
}
})
return response.data

// เอา localstorage ทั้งหมดออกไป
} catch (error) {
console.log('error', error.code)
throw new Error('out of stock')
}
}
}
})

ที่ CheckoutView

  • นำ url ที่ได้รับมา redirect ไปยังหน้า success
<script setup>
import UserLayout from '@/layouts/UserLayout.vue'

const checkout = async () => {
// submit checkout data
try {
// เพิ่ม validate
if (
!userCheckoutData.email ||
!userCheckoutData.name ||
!userCheckoutData.address
) {
throw new Error('Please add email, name, address')
}
// เพิ่ม ส่งข้อมูล
const result = await userCartStore.checkout(userCheckoutData)
// เพิ่ม redirect ไปยังหน้าที่รับมา
location.href = result.redirectUrl
} catch (error) {
alert(error.message)
}
}
</script>

เมื่อทุกอย่างถูกต้องเรียบร้อยจะต้องเกิด record ที่ Firestore ออกมา

placeorder-01