结账流程细节附录

本文是 checkout-flows.md细节层:落库字段对照、排障。主流程与四形态关系请先读主文档。

分形态逐步链路(含每步 API、MySQL/Redis、调用示例,风格对齐 COD 单页文档)

优惠计算规则见 promotion-discount-checkout.md

目录


1. 标准结账(standard)逐步明细

Controllerapp/home/controller/Order.php::checkout
路由GET|POST /{store_random}/checkouts/{checkout_token}step 由 query 或 POST 指定。

1.1 GET 渲染(每步共用)

checkCheckoutPermission
→ CartService::_checkCheckoutCart
→ CartService::getList(customerId, checkout_token)   // 计价 + 可能有订单 reconcile
→ OrderService::getCheckoutStep → 决定当前 step
→ 加载物流/支付/积分规则等
→ fetch Liquid 模板

1.2 POST 各步写库

step主要 Service 调用写入/更新
contact_informationOrderService::saveContactInformation无单:createOrdercheckout_type 默认 standard)→ savePreCouponsaveProducts → 地址 → UTM → tag → OrderCreate 事件;有单:更新地址 + savePreCoupon
shipping_methodsaveShippingMethod + saveOtherInformation + OrderDiyOfferHandleService::saveDiyOffercurrent_shipping_priceo_order_shipping_zone_plan、insurance/tip/note、o_order_diy_offer
payment_methodsavePaymentMethod + billing addresspayment_id/method/typecurrent_payment_price
payment_gateway支付 Script / orderZeroPayment第三方回调、financial_status

shipping_method POST 关键字段shipping_idoffer_from_name(JSON)、tip_priceinsurance 等。

代码锚点:Order.php 139–280(POST switch)、232 行 saveDiyOffer

1.3 优惠券(标准)

动作路由说明
用券GET /coupon/use/{checkout_token}?code=&email=CouponHandlerService::useCouponHandler
验券GET /coupon/check/{checkout_token}只校验不写库
取消DELETE /coupon/cancel/{checkout_token}cancelCouponHandler
预存 CookiePOST /coupons无 token 购物车阶段

创单时 OrderService::savePreCoupon 从 Cookie/Cache 正式绑定到 o_order

1.4 步骤守卫

OrderService::getCheckoutStep() 依据 order 上:

  • has_contact_information
  • has_shipping_method
  • has_payment_method

缺前置条件时 getCheckoutUrl 重定向到对应 step。


2. 单页结账(one_page)逐步明细

Controllerapp/homeapi/controller/OrderOnePage.php
ServiceCheckoutOnePageService
路由组/:store_random/one-page-checkouts/:checkout_token/*

2.1 API 一览

方法路径Service 方法落库
POSTpresavepreSave()创/更新 order、地址、coupon、products(锁:OnePageCheckoutPresaveLockKey
POSTpricegetCart()
POSTshippingsgetShippingMethods()
POSTpaymentsgetPaymentList()
POSTinsurancegetInsuranceSetting()
POSTaddongetShippingInfoAddon()
POSTprecompletepreComplete()是(不触发完整事件)
POSTcompletecomplete()是 + 事件 + 支付
POSTpaymentformgetPaymentForm()否(读最新 order 金额)

2.2 complete() 落盘顺序

CheckoutOnePageService::complete()(181–267 行):

1. saveOrder(orderPreData + order_info)
2. checkFirstOrder
3. savePreCoupon(getCart())
4. saveOrderProducts()
5. eventHandler()                    // OrderCreate 等
6. saveOrderShippingAddress / Billing
7. saveShippingMethod(trans_info.shipping_id)
8. saveCustomerInfo / savePropertyTag / handlerAdditionalInfo / handlerOrderAdminId
9. handlerOtherInfo()                // 券首单校验等
10. handlerOrderDiyOffer()           // trans_info.offer_from_name ← 积分/Seel
11. savePaymentMethod(trans_info.payment_id)
12. orderInfo->save()
13. orderZeroPayment 或 refreshToken + 支付表单

preComplete 与 complete 类似但 shouldTriggerEvents = false(277 行起)。

2.3 getCart() 计价顺序

getCart()(722 行起):

CartService::getList
→ setCartDefaultValue / generateCartCustomerId
→ calCartCouponPrice      // CouponHandlerService::useCouponHandler
→ calCartTaxPrice
→ calCartShippingPrice
→ calCartInsurancePrice
→ calCartTipPrice
→ calCartPaymentPrice
→ calCartTotalPrice

orderPreData()(939 行)字段映射见优惠文档 §8.6。

2.4 请求体结构(概念)

  • order_info:邮箱、顾客信息
  • shipping_address / bill_address
  • trans_infoshipping_idpayment_idcoupon_codeoffer_from_name
  • checkoutinfo:附加表单(CheckoutInfoService)

3. 渐进式结账(single_page)逐步明细

Controllerapp/homeapi/controller/OrderSinglePage.php
ServiceCheckoutSinglePageService
路由组/:store_random/single-page-checkouts/:checkout_token/*(注释:渐进式结账)

3.1 API 一览

方法路径Service落库
POSTemailsaveEmail创单 checkout_type=single_page
POSTcontact-informationsaveContactInformation地址等
POSTshipping-methodsaveShippingMethod运费 + other + saveDiyOffer
POSTpayment-methodsavePaymentMethod支付 + billing
POSTgatewaygetGatewayUrl支付跳转 URL
POSTuse-couponuseCouponCouponHandlerService券 + saveProducts
POSTcancel-couponcancelCouponHandler清券
GETshippings / payments / diy-offer / …各 get*
GETorderCartService::getList否(调试/展示)

3.2 saveEmail 创单

CheckoutSinglePageService::saveEmail(44 行):

  • 校验邮箱、黑名单、自动注册顾客
  • 无 order 时 insert o_ordercheckout_type = CHECKOUT_PROCESS_SINGLE_PAGE(152 行)
  • preData 含各 current_* 初值(来自当前 cartData)

3.3 saveShippingMethod

262–280 行,与标准 shipping 步 等价

OrderService::saveShippingMethod
→ saveOtherInformation
→ OrderDiyOfferHandleService::saveDiyOffer(checkout_token, offer_from_name)

3.4 与单页的关键差异

渐进式单页
创单email 一步presave 邮箱失焦
diy_offershipping-methodcomplete 最后
用券 APIPOST use-couponcomplete 内 trans_info 或 presave 后 getCart
分步感多 POST,前端控进度单屏一次 complete

4. COD 结账(cod)逐步明细

4.1 页面与 API

类型路径说明
GET 页面/{store}/cod-checkouts/{token}OrderCodPage::index,CodCartService 渲染
POST 下单/{store}/cod-checkouts/{token}OrderCodPage::saveOrderCodOrderHandlerService
GET 物流.../shippings物流列表
GET 税费.../tax税费试算
POST 用券.../use-couponCodCouponService
POST 取消券.../cancel-coupon

4.2 CodCartService 计价顺序

CodCartService::getCartList()(20–61 行):

codCartDataComposition
→ defaultDiyOffer(minmaxoffer)
→ if !has_minmaxoffer: cartDiyOffers(promotion, bundlesale, skubundlesale, gift)  // 一轮
→ PromotionHandlerService::getCartPromotion
→ CodCouponService::calPreCouponPrice
→ cartBuildEnding

差异于 CartService

  • 不读 o_order
  • gift 与 bundlesale 同轮(标准 Cart gift 单独第二轮)
  • updateDiyOfferInfo、无税费 reconcile 写库

4.3 saveOrder

CodOrderHandlerService::saveOrderCOD 订单表checkout_type=codcurrent_offer_price 来自 DTO 内 cart 级 diy 折扣,不写 o_order_diy_offer


5. 各折扣/费用持久化时机(全形态)

数据标准单页渐进式COD
o_order / COD 单contact POSTpresave / completeemail POSTsaveOrder POST
o_order_productcreateOrder / getList refreshcomplete saveProductsemail 后各步 refreshCOD saveOrder
current_promotion_pricegetList / saveProductscomplete / getCartgetListDTO 内
coupon_code/pricesavePreCoupon / useCouponcomplete savePreCouponuse-coupon / savePreCouponCodCoupon
o_order_diy_offershipping POSTcomplete handlerOrderDiyOffershipping-method POST
current_shipping_priceshipping POSTcomplete saveShippingMethodshipping-method POSTsaveOrder
current_tax_pricegetList reconcilecalCartTax + saveOrdergetList / savegetTaxPrice API
current_payment_pricepayment POSTcomplete savePaymentMethodpayment-method POSTN/A

5.1 CartService::getList 有订单时的 reconcile

706–708 行:

orderModel->save(order_price_update)   // coupon/tax/promotion 字段
→ saveProducts(refresh)
→ OrderDiyOfferService::updateDiyOfferInfo   // 积分等 reconcile

在线三种已有 checkout 订单 时执行。


6. checkout_type 与 URL 锁定规则

阶段URL 由谁决定
未创单storeConfig.checkout_process(+ smart Cookie)→ generateCheckoutUrlByConfig
已创单order.checkout_typegenerateCheckoutUrlByOrder
CODcod_checkout_type + 固定 /cod-checkouts/ 路径
支付回调 failUrlorder.checkout_type 拼 one-page / single-page / standard 路径

例外payment_gateway step 在部分场景强制标准 URL(generateCheckoutUrlByOrder 513–515 行)。


7. Service / Controller 索引

形态Home 页面Homeapi API核心 Service
标准Order.phpCoupon.phpOrderService, CartService
单页(主题 JS)OrderOnePage.phpCheckoutOnePageService
渐进式(主题 JS)OrderSinglePage.phpCheckoutSinglePageService
CODOrderCodPage.phpOrderCodPage.phpCodCartService, CodOrderHandlerService
共用Cart.phpCheckoutService, OrderDiyOfferHandleService

8. 排障清单(按形态)

现象标准单页渐进式COD
积分未扣查 shipping POST offer_from_name查 complete 是否传 trans_info.offer_from_name查 shipping-method POST不支持 order_diy_offer
券未绑定Cookie / savePreCouponcomplete savePreCouponemail 后 use-couponCodCoupon
价格与下单不一致getList reconcilecomplete 前调 price vs complete 落盘同标准仅内存 DTO
替换型券仍带满减查 checkCouponUseWithPromotionStatus同左同左已知:可能双计
跳错结账页checkout_process / smart Cookieorder.checkout_type 是否 one_page是否 single_pagecod_checkout_type

9. 与优惠文档的交叉引用

主题文档位置
promotion_price 计算顺序promotion-discount-checkout §2
order_diy_offer 类型promotion-discount-checkout §3
券 REPLACE 全路径promotion-discount-checkout §6.7
diy_offer 各 typepromotion-discount-checkout §4.3
COD 单页着陆cod-one-page-checkout.md

细节附录;主流程见 checkout-flows.md。FAQ 见 faq.md