Thiết lập quy trình thanh toán

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 hai đầu của bạn. Dịch vụ web của bạn 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 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 nội dung yêu cầu JSON dưới dạng CheckoutRequestMessage chứa thông tin chi tiết về Cart của khách hàng. Dịch vụ web này sẽ gửi nội dung yêu cầu hai đầu này đến khách hàng. Sau đó, dịch vụ web của bạn sẽ phản hồi bằng CheckoutResponseMessage. Sơ đồ dưới đây minh hoạ quy trình.

CheckoutResponseMessage trả về giỏ hàng chưa được sửa đổi hoặc lỗi của khách hàng.

Khi nhận được yêu cầu thanh toán, dịch vụ web Đặt hàng hai đầu của bạn 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 trả lờ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 một 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 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 yêu cầu đến dịch vụ web của bạn bằng nội dung JSON ở dạng CheckoutRequestMessage. Đơn đặt hàng của khách hàng không được gửi cho đến lúc sau trong quy trình Đặt hàng đầu-cuối.

Dữ liệu 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ỗi actions.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ượng Cart đại diện cho giỏ hàng của khách hàng.
  • Phân phối hoặc trích xuất: Trường mở rộng của đối tượng Cart chứa đối tượng FoodCartExtension chỉ định các thuộc tính để phân phối hoặc trích xuất:
    • Đối với các đơn đặt hàng giao hàng, đối tượng FoodCartExtension bao gồm địa chỉ giao hàng.
    • Đối với các đơn đặt hàng tự đến lấy hoặc mang đi, đối tượng FoodCartExtension không chứa thông tin vị trí nào.
  • Hộp cát: Trường isInSandbox của yêu cầu thanh toán chứa giá trị boolean cho biết giao dịch có sử dụng 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à một 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 về quy trình thanh toán

Sau khi nhận được yêu cầu từ dịch vụ Đặt hàng hai đầu, 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 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 ProposedOrderPaymentOptions:

  • ProposedOrder

    • cart: Đối tượng cart giống hệt với giỏ hàng được cung cấp trong CheckoutRequestMessage. Nếu cần thay đổi bất kỳ nội dung nào trong giỏ hàng, CheckoutResponseMessage phải bao gồm FoodErrorExtension với ProposedOrder đã sửa.
    • otherItems: Các mục do nhà cung cấp thêm vào, chẳng hạn như phí giao hàng, thuế và các loại phí khác. Cũng có thể bao gồm tiền thưởng 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

    • Bạn có thể tìm hiểu về quy trình thiết lập quy trình thanh toán ở phần sau trong bài viết 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 tuỳ chọn 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 cổng thanh toán mẫu cho PaymentOptions.

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, 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ắc 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 cần thực hiện các bước sau đây 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 tìm thấy. Những lỗi này không thể khôi phục được, vì vậy, hệ thống sẽ trả về lỗi đầu tiên gặp phải. Hãy xem phần Xử lý lỗi để biết nội dung mô tả về lỗi có thể khôi phục.

  1. Hãy đọ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 dành cho delivery hay pickup.
  2. Trả về các loại lỗi sau 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 không hợp lệ.
    NOT_FOUND Không tìm thấy loại phương thức thực hiện.
    ĐÓNG
    • Không có khoảng thời gian OperationHours của đơn đặt hàng này.
    • Đây là đơn đặt hàng sớm nhất có thể và hiện không có ServiceHours sớm nhất có thể.
    • Hiện tại đang đóng cửa trong trường hợp khẩn cấp hoặc dịch vụ isDisabled đã hoạt động đúng cách.
    Xin lưu ý rằng Khoảng thời gian đặc biệt được ưu tiên so với thời lượng thông thường. Hãy xem ví dụ trong phần sắp xếp thứ tự xác thực khoảng thời giantạm thời xoá các thực thể dịch vụ.
    UNAVAILABLE_SLOT Không thể thực hiện đơn đặt hàng trước.
    NO_CAPACITY Nhà hàng hiện đang bậ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 vì số lượng nhân viên giao hàng có hạn.

Xác thực và định giá giỏ hàng

  1. Tra cứu từng Giỏ hàng.lineItems rồi 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 FoodOrderError cho từng 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 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 lựa chọn nào đều không hợp lệ. Không
    NOT_FOUND Không tìm thấy mục đó hoặc bất kỳ lựa 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 xem là có thể khắc phục.
    AVAILABILITY_CHANGED Không có số tiền được yêu cầu cho các mục hàng hoặc bất kỳ tùy chọn nào.
    REQUIREMENTS_NOT_MET Không đạt giá trị đặt hàng tối thiểu hoặc giá trị tối đa của đơn đặt hàng. Bạn có thể xác định khoản phí này bằng cách kiểm tra xem giá của giỏ hàng có thấp hơn Phí.eligibleTransactionVolumeMin hay cao hơn Phí không.eligibleTransactionVolumeMax. Xem ví dụ trong bài viết xác thực giá trị đơn đặt hàng tối thiểu. Không
  2. Trả về danh sách mục hàng đã xác thực với LineItemType REGULAR. Tổng của tất cả mức giá của mục hàng trong giỏ hàng là giá giỏ hàng hoặc SUBTOTAL.

Xem ví dụ trong phần xác thực mục trong giỏ hàng.

Tính phí dịch vụ

  1. Tìm thực thể Phí chính xác cho dịch vụ dựa trên eligibleRegion, validFrom, validThroughpriority.
  2. 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 hay pricePerMeter.
  3. Trả về phí dịch vụ giao hàng hoặc trích xuất dưới dạng LineItem tương ứng với LineItemType DELIVERY hoặc FEE. Thêm phí vào danh sách Giỏ hàng.otherItems.

Áp dụng chương trình khuyến mãi

  1. Tìm thực thể Deal (Giao dịch) dựa trên việc so khớp giá trị Chương trình khuyến mãi.coupon với giá trị Deal.dealCode.
  2. Xác thực giao dịch và trả về FoodOrderError nếu cần. Những lỗi này có thể được xem là có thể khôi phục. Trả về các loại lỗi sau 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 Hiệu lực của thoả thuận đã hết hạn.
    PROMO_ORDER_INELIGIBLE Đơn đặt hàng không đủ điều kiện nhận phiếu giảm giá.
    PROMO_NOT_APPLICABLE Lý do khác.
  3. Tính giá tiền giao dịch dựa trên Giao dịch.discount hoặc Giao dịch.discountPercentage.

  4. Áp dụng giá giao dịch bằng cách sử dụng tổng chi phí giỏ hàng hoặc tổng phí tuỳ thuộc vào Giao dịch.dealType.

  5. Trả lại Giỏ hàng.promotions có áp dụng chương trình khuyến mãi.

  6. Trả về chương trình khuyến mãi dưới dạng LineItemLineItemType DISCOUNT. Thêm ưu đãi giảm giá vào danh sách Giỏ hàng.otherItems kèm theo giá âm.

Trả lời

  1. Tạo ProposedOrder (Đơn đặt hàng đề xuất).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 nào trong quá trình xác thực.
  2. Trả về danh sách ProposedOrder.otherItems bao gồm thuế, phí, tiền thưởng và chiết khấu nếu có. Hãy xem phần Miễn phí để biết thêm thông tin về cách định cấu hình mục tiền thưởng.
  3. Thêm ProposedOrder.totalPrice bằng cách thêm giá giỏ hàng, phí, chiết khấu, thuế và tiền thưởng.
  4. Trả về FoodOrderExtension.availableFulfillmentOptions bằng FulfillmentOption tương ứng. Hãy cập nhật thời gian đến lấy hàng hoặc thời gian giao hàng dự kiến thành thời gian dự kiến.
  5. Nếu có FoodOrderErrors được tạo từ các lần kiểm tra xác thực trước đó:
    • Bao gồm StructuredResponse.error và danh sách các lỗi trong FoodErrorExtension.foodOrderErrors.
    • Trả về ProposedOrder (Đơn đặt hàng đề xuất) trong trường correctedProposedOrder nếu bạn có thể khôi phục tất cả lỗi.
    • Trả về PaymentOptions trong trường paymentOptions nếu bạn có thể khôi phục tất cả lỗi.
    • Nếu muốn, hãy thêm additionalPaymentOptions nếu có các tuỳ chọn thanh toán khác và tất cả lỗi đều có thể khôi phục.
  6. Nếu không có lỗi xác thực, hãy trả về proposedOrder, paymentOptions trong đối tượng CheckoutResponse. Thêm additionalPaymentOptions nếu có các tuỳ chọn thanh toán khác (không bắt buộc).