mirror of
https://github.com/vercel/commerce.git
synced 2025-07-25 19:21:23 +00:00
Implements custom checkout along with ordercloud provider
This commit is contained in:
35
framework/ordercloud/api/endpoints/checkout/get-checkout.ts
Normal file
35
framework/ordercloud/api/endpoints/checkout/get-checkout.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { CheckoutEndpoint } from '.'
|
||||
|
||||
const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
||||
res,
|
||||
body: {cartId},
|
||||
config: { restFetch },
|
||||
}) => {
|
||||
// Return an error if no item is present
|
||||
if (!cartId) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Missing cookie' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Register credit card
|
||||
const payments = await restFetch('GET', `/orders/Outgoing/${cartId}/payments`).then(
|
||||
(response: {Items: unknown[]}) => response.Items
|
||||
)
|
||||
|
||||
const address = await restFetch('GET', `/orders/Outgoing/${cartId}`).then(
|
||||
(response: {ShippingAddressID: string}) => response.ShippingAddressID
|
||||
)
|
||||
|
||||
// Return cart and errors
|
||||
res.status(200).json({
|
||||
data: {
|
||||
hasPayment: payments.length > 0,
|
||||
hasShipping: Boolean(address)
|
||||
},
|
||||
errors: []
|
||||
})
|
||||
}
|
||||
|
||||
export default getCheckout
|
@@ -1 +1,23 @@
|
||||
export default function noopApi(...args: any[]): void {}
|
||||
import type { CheckoutSchema } from '../../../types/checkout'
|
||||
import type { OrdercloudAPI } from '../..'
|
||||
|
||||
import { GetAPISchema, createEndpoint } from '@commerce/api'
|
||||
import checkoutEndpoint from '@commerce/api/endpoints/checkout'
|
||||
|
||||
import getCheckout from './get-checkout'
|
||||
import submitCheckout from './submit-checkout'
|
||||
|
||||
export type CheckoutAPI = GetAPISchema<OrdercloudAPI, CheckoutSchema>
|
||||
export type CheckoutEndpoint = CheckoutAPI['endpoint']
|
||||
|
||||
export const handlers: CheckoutEndpoint['handlers'] = {
|
||||
getCheckout,
|
||||
submitCheckout,
|
||||
}
|
||||
|
||||
const checkoutApi = createEndpoint<CheckoutAPI>({
|
||||
handler: checkoutEndpoint,
|
||||
handlers,
|
||||
})
|
||||
|
||||
export default checkoutApi
|
||||
|
@@ -0,0 +1,23 @@
|
||||
import type { CheckoutEndpoint } from '.'
|
||||
|
||||
const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({
|
||||
res,
|
||||
body: { cartId },
|
||||
config: { restFetch },
|
||||
}) => {
|
||||
// Return an error if no item is present
|
||||
if (!cartId) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Missing item' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Submit order
|
||||
await restFetch('POST', `/orders/Outgoing/${cartId}/submit`, {})
|
||||
|
||||
// Return cart and errors
|
||||
res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default submitCheckout
|
@@ -0,0 +1,49 @@
|
||||
import type { CustomerAddressEndpoint } from '.'
|
||||
|
||||
const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
|
||||
res,
|
||||
body: { item, cartId },
|
||||
config: { restFetch },
|
||||
}) => {
|
||||
// Return an error if no item is present
|
||||
if (!item) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Missing item' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Return an error if no item is present
|
||||
if (!cartId) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Cookie not found' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Register address
|
||||
const address = await restFetch('POST', `/me/addresses`, {
|
||||
"AddressName": "main address",
|
||||
"CompanyName": item.company,
|
||||
"FirstName": item.firstName,
|
||||
"LastName": item.lastName,
|
||||
"Street1": item.streetNumber,
|
||||
"Street2": item.streetNumber,
|
||||
"City": item.city,
|
||||
"State": item.city,
|
||||
"Zip": item.zipCode,
|
||||
"Country": item.country.slice(0, 2).toLowerCase(),
|
||||
"Shipping": true
|
||||
}).then(
|
||||
(response: {ID: string}) => response.ID
|
||||
)
|
||||
|
||||
// Assign address to order
|
||||
await restFetch('PATCH', `/orders/Outgoing/${cartId}`, {
|
||||
ShippingAddressID: address
|
||||
})
|
||||
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default addItem
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerAddressEndpoint } from '.'
|
||||
|
||||
const getCards: CustomerAddressEndpoint['handlers']['getAddresses'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default getCards
|
27
framework/ordercloud/api/endpoints/customer/address/index.ts
Normal file
27
framework/ordercloud/api/endpoints/customer/address/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { CustomerAddressSchema } from '../../../../types/customer/address'
|
||||
import type { OrdercloudAPI } from '../../..'
|
||||
|
||||
import { GetAPISchema, createEndpoint } from '@commerce/api'
|
||||
import customerAddressEndpoint from '@commerce/api/endpoints/customer/address'
|
||||
|
||||
import getAddresses from './get-addresses'
|
||||
import addItem from './add-item'
|
||||
import updateItem from './update-item'
|
||||
import removeItem from './remove-item'
|
||||
|
||||
export type CustomerAddressAPI = GetAPISchema<OrdercloudAPI, CustomerAddressSchema>
|
||||
export type CustomerAddressEndpoint = CustomerAddressAPI['endpoint']
|
||||
|
||||
export const handlers: CustomerAddressEndpoint['handlers'] = {
|
||||
getAddresses,
|
||||
addItem,
|
||||
updateItem,
|
||||
removeItem,
|
||||
}
|
||||
|
||||
const customerAddressApi = createEndpoint<CustomerAddressAPI>({
|
||||
handler: customerAddressEndpoint,
|
||||
handlers,
|
||||
})
|
||||
|
||||
export default customerAddressApi
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerAddressEndpoint } from '.'
|
||||
|
||||
const removeItem: CustomerAddressEndpoint['handlers']['removeItem'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default removeItem
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerAddressEndpoint } from '.'
|
||||
|
||||
const updateItem: CustomerAddressEndpoint['handlers']['updateItem'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default updateItem
|
61
framework/ordercloud/api/endpoints/customer/card/add-item.ts
Normal file
61
framework/ordercloud/api/endpoints/customer/card/add-item.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type { CustomerCardEndpoint } from '.'
|
||||
import type { OredercloudCreditCard } from '../../../../types/customer/card'
|
||||
|
||||
import Stripe from "stripe"
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET as string, {
|
||||
apiVersion: "2020-08-27"
|
||||
})
|
||||
|
||||
const addItem: CustomerCardEndpoint['handlers']['addItem'] = async ({
|
||||
res,
|
||||
body: { item, cartId },
|
||||
config: { restFetch },
|
||||
}) => {
|
||||
// Return an error if no item is present
|
||||
if (!item) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Missing item' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Return an error if no item is present
|
||||
if (!cartId) {
|
||||
return res.status(400).json({
|
||||
data: null,
|
||||
errors: [{ message: 'Cookie not found' }],
|
||||
})
|
||||
}
|
||||
|
||||
// Get token
|
||||
const token = await stripe.tokens.create({
|
||||
card: {
|
||||
number: item.cardNumber,
|
||||
exp_month: item.cardExpireDate.split('/')[0],
|
||||
exp_year: item.cardExpireDate.split('/')[1],
|
||||
cvc: item.cardCvc
|
||||
}
|
||||
}).then((res: {id: string}) => res.id)
|
||||
|
||||
// Register credit card
|
||||
const creditCard = await restFetch('POST', `/me/creditcards`, {
|
||||
"Token": token,
|
||||
"CardType": "credit",
|
||||
"PartialAccountNumber": item.cardNumber.slice(-4),
|
||||
"CardholderName": item.cardHolder,
|
||||
"ExpirationDate": item.cardExpireDate
|
||||
}).then(
|
||||
(response: OredercloudCreditCard) => response.ID
|
||||
)
|
||||
|
||||
// Assign payment to order
|
||||
await restFetch('POST', `/orders/Outgoing/${cartId}/payments`, {
|
||||
"Type": "CreditCard",
|
||||
CreditCardID: creditCard
|
||||
})
|
||||
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default addItem
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerCardEndpoint } from '.'
|
||||
|
||||
const getCards: CustomerCardEndpoint['handlers']['getCards'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default getCards
|
27
framework/ordercloud/api/endpoints/customer/card/index.ts
Normal file
27
framework/ordercloud/api/endpoints/customer/card/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { CustomerCardSchema } from '../../../../types/customer/card'
|
||||
import type { OrdercloudAPI } from '../../..'
|
||||
|
||||
import { GetAPISchema, createEndpoint } from '@commerce/api'
|
||||
import customerCardEndpoint from '@commerce/api/endpoints/customer/card'
|
||||
|
||||
import getCards from './get-cards'
|
||||
import addItem from './add-item'
|
||||
import updateItem from './update-item'
|
||||
import removeItem from './remove-item'
|
||||
|
||||
export type CustomerCardAPI = GetAPISchema<OrdercloudAPI, CustomerCardSchema>
|
||||
export type CustomerCardEndpoint = CustomerCardAPI['endpoint']
|
||||
|
||||
export const handlers: CustomerCardEndpoint['handlers'] = {
|
||||
getCards,
|
||||
addItem,
|
||||
updateItem,
|
||||
removeItem,
|
||||
}
|
||||
|
||||
const customerCardApi = createEndpoint<CustomerCardAPI>({
|
||||
handler: customerCardEndpoint,
|
||||
handlers,
|
||||
})
|
||||
|
||||
export default customerCardApi
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerCardEndpoint } from '.'
|
||||
|
||||
const removeItem: CustomerCardEndpoint['handlers']['removeItem'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default removeItem
|
@@ -0,0 +1,9 @@
|
||||
import type { CustomerCardEndpoint } from '.'
|
||||
|
||||
const updateItem: CustomerCardEndpoint['handlers']['updateItem'] = async ({
|
||||
res,
|
||||
}) => {
|
||||
return res.status(200).json({ data: null, errors: [] })
|
||||
}
|
||||
|
||||
export default updateItem
|
Reference in New Issue
Block a user