Quy trình thanh toán được gọi khi người dùng tạo giỏ hàng. Nội dung trong giỏ hàng của người dùng và thông tin chi tiết về đơn đặt hàng sẽ được gửi đến dịch vụ web Đặt hàng toàn diện của bạn. Dịch vụ web của bạn sẽ xác thực thông tin này, sau đó bạn có thể tiếp tục hoặc điều chỉnh giỏ hàng của họ nếu cần.
Trình xử lý thanh toán cho dịch vụ web của bạn phải phản hồi các yêu cầu POST. Khi khách hàng chọn thanh toán, Google sẽ gửi cho dịch vụ web Toàn diện về việc đặt hàng một nội dung yêu cầu JSON ở dạng CheckoutRequestMessage
. Nội dung này chứa thông tin chi tiết về Cart
của khách hàng. Sau đó, dịch vụ web của bạn sẽ phản hồi bằng một CheckoutResponseMessage
. Sơ đồ sau đây minh hoạ quy trình này.
Sau khi nhận được yêu cầu thanh toán, dịch vụ web Toàn diện về việc đặt hàng phải thực hiện những việc sau:
- Kiểm tra tính hợp lệ của giỏ hàng dựa trên giá hiện tại của mặt hàng, tình trạng còn hàng và dịch vụ của nhà cung cấp.
- Tính tổng giá (bao gồm mọi khoản chiết khấu, thuế và phí giao hàng).
- Nếu thành công, hãy phản hồi bằng một giỏ hàng chưa sửa đổi.
- Nếu không thành công, hãy phản hồi bằng thông báo lỗi và một đơn đặt hàng mới được đề xuất.
Trước khi bắt đầu triển khai quy trình thanh toán, bạn nên xem lại tài liệu Tổng quan về việc thực hiện đơn hàng.
Thông báo yêu cầu thanh toán
Để xác thực giỏ hàng của khách hàng, khi khách hàng chọn thanh toán, Google sẽ gửi một yêu cầu đến dịch vụ web của bạn với nội dung JSON ở dạng CheckoutRequestMessage
. Đơn đặt hàng của khách hàng sẽ không được gửi cho đến sau trong quy trình Đặt hàng hoàn chỉnh.
Dữ liệu có trong CheckoutRequestMessage
bao gồm:
- Ý định: Trường
inputs[0].intent
của mọi nội dung yêu cầu thanh toán chứa giá trị chuỗiactions.foodordering.intent.CHECKOUT
. - Giỏ hàng: Trường
inputs[0].arguments[0].extension
của yêu cầu thanh toán chứa đối tượngCart
đại diện cho giỏ hàng của khách hàng. - Giao hàng hoặc mang đi: Trường mở rộng của đối tượng
Cart
chứa một đối tượngFoodCartExtension
chỉ định các thuộc tính cho dịch vụ giao hàng hoặc mang đi:- Đối với đơn đặt hàng giao tận nơi, đối tượng
FoodCartExtension
bao gồm cả địa chỉ giao hàng. - Đối với đơn đặt hàng mang đi hoặc đến lấy hàng, đối tượng
FoodCartExtension
không chứa bất kỳ thông tin vị trí nào.
- Đối với đơn đặt hàng giao tận nơi, đối tượng
- Hộp cát: Trường
isInSandbox
của yêu cầu thanh toán chứa một giá trị boolean cho biết giao dịch có sử dụng phương thức thanh toán trong hộp cát hay không.
Ví dụ về yêu cầu thanh toán
Dưới đây là ví dụ về CheckoutRequestMessage
:
{
"user": {},
"conversation": {
"conversationId": "CTZbZfUlHCybEdcz_5PB3Ttf"
},
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.Cart",
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
}
}
]
}
],
"directActionOnly": true,
"isInSandbox": true
}
Thông báo phản hồi quy trình thanh toán
Sau khi nhận được yêu cầu từ dịch vụ Đặt hàng toàn diện, dịch vụ web thanh toán của bạn phải xử lý yêu cầu đó và phản hồi bằng CheckoutResponseMessage
. CheckoutResponseMessage
cần bao gồm một yêu cầu thành công hoặc không thành công.
Yêu cầu thành công
Nếu yêu cầu thanh toán thành công, CheckoutResponseMessage
cần bao gồm ProposedOrder
và PaymentOptions
:
ProposedOrder
cart
: Một đối tượngcart
giống với giỏ hàng được cung cấp trongCheckoutRequestMessage
. Nếu cần thay đổi bất kỳ nội dung nào trong giỏ hàng,CheckoutResponseMessage
phải bao gồmFoodErrorExtension
cóProposedOrder
đã sửa.otherItems
: Các mục do nhà cung cấp thêm, chẳng hạn như phí giao hàng, thuế và các khoản phí khác. Cũng có thể chứa tiền boa do người dùng thêm.totalPrice
: Tổng giá của đơn đặt hàng.extension
:FoodOrderExtension
xác định thông tin thực hiện đơn đặt hàng, chẳng hạn như thời gian giao hàng.
PaymentOptions
- Phần sau sẽ trình bày cách thiết lập quy trình xử lý thanh toán trong phần Thiết lập Google Pay.
Bạn có thể sử dụng JSON phần giữ chỗ trong
CheckoutResponseMessage
cho đến khi sẵn sàng triển khai quy trình xử lý thanh toán. - Để thêm các phương thức thanh toán giữ chỗ trong
CheckoutResponseMessage
, hãy tham khảo ví dụ bên dưới. Ví dụ này sử dụng một cổng thanh toán mẫu choPaymentOptions
.
- Phần sau sẽ trình bày cách thiết lập quy trình xử lý thanh toán trong phần Thiết lập Google Pay.
Bạn có thể sử dụng JSON phần giữ chỗ trong
Ví dụ về phản hồi thành công
{
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"cart": {
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "43",
"nanos": 100000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
{
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
}
]
},
"otherItems": [
{
"name": "Delivery fee",
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "3",
"nanos": 500000000
}
},
"type": "DELIVERY"
}
]
},
"paymentOptions": {
"googleProvidedOptions": {
"facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"AUD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"43.1\"}} "
}
},
"additionalPaymentOptions": [
{
"actionProvidedOptions": {
"paymentType": "ON_FULFILLMENT",
"displayName": "Pay when you get your food.",
"onFulfillmentPaymentData": {
"supportedPaymentOptions": []
}
}
}
]
}
}
}
]
}
}
}
Yêu cầu không thành công
Nếu yêu cầu thanh toán không thành công, CheckoutResponseMessage
cần bao gồm FoodErrorExtension
. FoodErrorExtension
chứa danh sách các mục FoodOrderError
mô tả mọi lỗi đã xảy ra. Nếu có bất kỳ lỗi nào có thể khôi phục đối với đơn đặt hàng, chẳng hạn như thay đổi giá của một mặt hàng trong giỏ hàng, thì FoodErrorExtension
phải bao gồm correctedProposedOrder
.
Ví dụ về phản hồi không thành công
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
Triển khai quy trình thanh toán
Bạn nên thực hiện các bước sau khi triển khai quy trình thanh toán.
Xác thực dịch vụ
Trả về FoodOrderError cho điều kiện lỗi dịch vụ đầu tiên được tìm thấy. Bạn không thể khôi phục các lỗi này, vì vậy, lỗi đầu tiên gặp phải sẽ được trả về. Hãy xem phần Xử lý lỗi để biết nội dung mô tả về các lỗi có thể khôi phục.
- Đọc thuộc tính FulfillmentOptionInfo trong yêu cầu để xác định xem loại phương thức thực hiện là dành cho
delivery
haypickup
. Trả về các loại lỗi sau đây nếu cần:
Loại lỗi Trường hợp sử dụng INVALID Loại phương thức thực hiện là không hợp lệ. NOT_FOUND Không tìm thấy loại phương thức thực hiện. ĐÃ ĐÓNG - Đơn đặt hàng không có khung giờ OperationHours.
- Đơn đặt hàng này là đơn đặt hàng cần giao hàng ngay và hiện không có ServiceHours nào cho đơn đặt hàng cần giao hàng ngay tại thời điểm hiện tại.
- Có trường hợp đóng khẩn cấp hoặc dịch vụ
isDisabled
là đúng.
UNAVAILABLE_SLOT Không thể thực hiện đơn đặt hàng trước. NO_CAPACITY Nhà hàng đang bận và hiện không nhận đơn đặt hàng. OUT_OF_SERVICE_AREA Không thể giao đơn đặt hàng đến địa chỉ của người dùng. Hãy xem phần Xác thực địa chỉ giao hàng để biết ví dụ. NO_COURIER_AVAILABLE Không thể giao đơn đặt hàng do thiếu nhân viên giao hàng.
Xác thực và định giá giỏ hàng
Tìm mỗi Giỏ hàng.
lineItems
và xác thực bằng dữ liệu hiện tại trong hệ thống của bạn hoặc trong hệ thống của người bán. Giá trị MenuItemOffer.sku
từ thực thể nguồn cấp dữ liệu được đưa vào dưới dạng LineItem.offerId
. Tạo một FoodOrderError cho mỗi mục hàng nếu cần. Tạo tối đa một lỗi cho mỗi mục. Trả về các loại lỗi sau đây nếu cần:Loại lỗi Trường hợp sử dụng Có thể khôi phục INVALID Dữ liệu mặt hàng hoặc bất kỳ dữ liệu tuỳ chọn nào đều không hợp lệ. Không NOT_FOUND Không tìm thấy mặt hàng hoặc bất kỳ tuỳ chọn nào. Không PRICE_CHANGED Giá của một mặt hàng hoặc tổ hợp tiện ích bổ sung đã thay đổi. Lỗi này có thể được coi là có thể khôi phục. Có AVAILABILITY_CHANGED Số tiền bạn yêu cầu cho mục hàng hoặc bất kỳ lựa chọn nào không có sẵn. Có REQUIREMENTS_NOT_MET Chưa đạt số lượng đơn đặt hàng tối thiểu hoặc tối đa. Bạn có thể xác định điều này bằng cách kiểm tra xem giá giỏ hàng có thấp hơn Phí. eligibleTransactionVolumeMin
hay cao hơn Phí.eligibleTransactionVolumeMax
hay không. Xem ví dụ trong phần xác thực giá trị đơn đặt hàng tối thiểu.Không Trả về danh sách lineItems đã xác thực bằng LineItemType
REGULAR
. Tổng giá của tất cả các mục hàng trong giỏ hàng là giá giỏ hàng hoặcSUBTOTAL
.
Xem ví dụ trong phần xác thực mặt hàng trong giỏ hàng.
Tính phí dịch vụ
- Tìm thực thể Phí chính xác cho dịch vụ dựa trên
eligibleRegion
,validFrom
,validThrough
vàpriority
. - Tính số tiền phí dựa trên việc thực thể được xác định bằng thuộc tính
price
,percentageOfCart
hoặcpricePerMeter
. - Trả về phí dịch vụ giao hàng hoặc mang đi dưới dạng LineItem với LineItemType tương ứng là
DELIVERY
hoặcFEE
. Thêm phí vào danh sách Giỏ hàng.otherItems
.
Áp dụng chương trình khuyến mãi
- Tìm thực thể Thoả thuận dựa trên việc so khớp giá trị Khuyến mãi.
coupon
với Thoả thuận.dealCode
. Xác thực ưu đãi và trả về FoodOrderError nếu cần. Những lỗi này có thể được coi là có thể khôi phục. Trả về các loại lỗi sau đây nếu cần:
Loại lỗi Trường hợp sử dụng PROMO_NOT_RECOGNIZED Không nhận dạng được mã giảm giá. PROMO_EXPIRED Thời hạn hiệu lực của thoả thuận đã hết. PROMO_ORDER_INELIGIBLE Đơn đặt hàng không đủ điều kiện sử dụng phiếu giảm giá. PROMO_NOT_APPLICABLE Lý do khác. Tính số tiền của giá ưu đãi dựa trên Deal.
discount
hoặc Deal.discountPercentage
.Áp dụng số tiền ưu đãi bằng cách sử dụng tổng giá trị giỏ hàng hoặc tổng phí, tuỳ thuộc vào Ưu đãi.
dealType
.Trả về Giỏ hàng.
promotions
đã áp dụng chương trình khuyến mãi.Trả về chương trình khuyến mãi dưới dạng LineItem với LineItemType
DISCOUNT
. Thêm khoản chiết khấu vào danh sách Giỏ hàng.otherItems
có giá âm.
Trả về phản hồi
- Tạo ProposedOrder.
cart
, giỏ hàng phản hồi giống với giỏ hàng yêu cầu nếu không gặp lỗi trong quá trình xác thực. - Trả về danh sách ProposedOrder.
otherItems
bao gồm thuế, phí, tiền boa và chiết khấu nếu áp dụng. Hãy xem phần Tiền boa để biết thêm thông tin chi tiết về cách định cấu hình mặt hàng tiền boa. - Thêm ProposedOrder.
totalPrice
bằng cách thêm giá, phí, chiết khấu, thuế và tiền boa vào giỏ hàng. - Trả về FoodOrderExtension.
availableFulfillmentOptions
với FulfillmentOption tương ứng. Cập nhật thời gian lấy hàng hoặc giao hàng dự kiến thành thời gian dự kiến. - Nếu có FoodOrderErrors được tạo từ các lần kiểm tra xác thực trước đó:
- Thêm StructuredResponse.
error
và danh sách lỗi vào FoodErrorExtension.foodOrderErrors
. - Trả về ProposedOrder trong trường
correctedProposedOrder
nếu tất cả lỗi đều có thể khôi phục. - Trả về PaymentOptions trong trường
paymentOptions
nếu tất cả lỗi đều có thể khôi phục. - Bạn có thể thêm
additionalPaymentOptions
nếu có các phương thức thanh toán khác và tất cả lỗi đều có thể khôi phục.
- Thêm StructuredResponse.
- Nếu không có lỗi xác thực, hãy trả về
proposedOrder
,paymentOptions
trong đối tượng CheckoutResponse. Bạn có thể đưaadditionalPaymentOptions
vào nếu có các phương thức thanh toán khác.