结账流程细节附录
本文是 checkout-flows.md 的 细节层:落库字段对照、排障。主流程与四形态关系请先读主文档。
分形态逐步链路(含每步 API、MySQL/Redis、调用示例,风格对齐 COD 单页文档):
- standard-checkout-flow.md
- one-page-checkout-flow.md
- single-page-checkout-flow.md
- cod-checkout-flow.md
- cod-one-page-checkout.md
优惠计算规则见 promotion-discount-checkout.md。
目录
- 1. 标准结账(standard)逐步明细
- 2. 单页结账(one_page)逐步明细
- 3. 渐进式结账(single_page)逐步明细
- 4. COD 结账(cod)逐步明细
- 5. 各折扣/费用持久化时机(全形态)
- 6. checkout_type 与 URL 锁定规则
- 7. Service / Controller 索引
- 8. 排障清单(按形态)
- 9. 与优惠文档的交叉引用
1. 标准结账(standard)逐步明细
Controller:app/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_information | OrderService::saveContactInformation | 无单:createOrder(checkout_type 默认 standard)→ savePreCoupon → saveProducts → 地址 → UTM → tag → OrderCreate 事件;有单:更新地址 + savePreCoupon |
| shipping_method | saveShippingMethod + saveOtherInformation + OrderDiyOfferHandleService::saveDiyOffer | current_shipping_price、o_order_shipping_zone_plan、insurance/tip/note、o_order_diy_offer |
| payment_method | savePaymentMethod + billing address | payment_id/method/type、current_payment_price |
| payment_gateway | 支付 Script / orderZeroPayment | 第三方回调、financial_status |
shipping_method POST 关键字段:shipping_id、offer_from_name(JSON)、tip_price、insurance 等。
代码锚点: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 |
| 预存 Cookie | POST /coupons | 无 token 购物车阶段 |
创单时 OrderService::savePreCoupon 从 Cookie/Cache 正式绑定到 o_order。
1.4 步骤守卫
OrderService::getCheckoutStep() 依据 order 上:
has_contact_informationhas_shipping_methodhas_payment_method
缺前置条件时 getCheckoutUrl 重定向到对应 step。
2. 单页结账(one_page)逐步明细
Controller:app/homeapi/controller/OrderOnePage.php
Service:CheckoutOnePageService
路由组:/:store_random/one-page-checkouts/:checkout_token/*
2.1 API 一览
| 方法 | 路径 | Service 方法 | 落库 |
|---|---|---|---|
| POST | presave | preSave() | 创/更新 order、地址、coupon、products(锁:OnePageCheckoutPresaveLockKey) |
| POST | price | getCart() | 否 |
| POST | shippings | getShippingMethods() | 否 |
| POST | payments | getPaymentList() | 否 |
| POST | insurance | getInsuranceSetting() | 否 |
| POST | addon | getShippingInfoAddon() | 否 |
| POST | precomplete | preComplete() | 是(不触发完整事件) |
| POST | complete | complete() | 是 + 事件 + 支付 |
| POST | paymentform | getPaymentForm() | 否(读最新 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_addresstrans_info:shipping_id、payment_id、coupon_code、offer_from_namecheckoutinfo:附加表单(CheckoutInfoService)
3. 渐进式结账(single_page)逐步明细
Controller:app/homeapi/controller/OrderSinglePage.php
Service:CheckoutSinglePageService
路由组:/:store_random/single-page-checkouts/:checkout_token/*(注释:渐进式结账)
3.1 API 一览
| 方法 | 路径 | Service | 落库 |
|---|---|---|---|
| POST | email | saveEmail | 创单 checkout_type=single_page |
| POST | contact-information | saveContactInformation | 地址等 |
| POST | shipping-method | saveShippingMethod | 运费 + other + saveDiyOffer |
| POST | payment-method | savePaymentMethod | 支付 + billing |
| POST | gateway | getGatewayUrl | 支付跳转 URL |
| POST | use-coupon | useCoupon → CouponHandlerService | 券 + saveProducts |
| POST | cancel-coupon | cancelCouponHandler | 清券 |
| GET | shippings / payments / diy-offer / … | 各 get* | 否 |
| GET | order | CartService::getList | 否(调试/展示) |
3.2 saveEmail 创单
CheckoutSinglePageService::saveEmail(44 行):
- 校验邮箱、黑名单、自动注册顾客
- 无 order 时 insert
o_order,checkout_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_offer | shipping-method | complete 最后 |
| 用券 API | POST use-coupon | complete 内 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::saveOrder → CodOrderHandlerService |
| GET 物流 | .../shippings | 物流列表 |
| GET 税费 | .../tax | 税费试算 |
| POST 用券 | .../use-coupon | CodCouponService |
| 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::saveOrder 写 COD 订单表,checkout_type=cod,current_offer_price 来自 DTO 内 cart 级 diy 折扣,不写 o_order_diy_offer。
5. 各折扣/费用持久化时机(全形态)
| 数据 | 标准 | 单页 | 渐进式 | COD |
|---|---|---|---|---|
o_order / COD 单 | contact POST | presave / complete | email POST | saveOrder POST |
o_order_product | createOrder / getList refresh | complete saveProducts | email 后各步 refresh | COD saveOrder |
current_promotion_price | getList / saveProducts | complete / getCart | getList | DTO 内 |
coupon_code/price | savePreCoupon / useCoupon | complete savePreCoupon | use-coupon / savePreCoupon | CodCoupon |
o_order_diy_offer | shipping POST | complete handlerOrderDiyOffer | shipping-method POST | 无 |
current_shipping_price | shipping POST | complete saveShippingMethod | shipping-method POST | saveOrder |
current_tax_price | getList reconcile | calCartTax + saveOrder | getList / save | getTaxPrice API |
current_payment_price | payment POST | complete savePaymentMethod | payment-method POST | N/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_type → generateCheckoutUrlByOrder |
| COD | cod_checkout_type + 固定 /cod-checkouts/ 路径 |
| 支付回调 failUrl | 读 order.checkout_type 拼 one-page / single-page / standard 路径 |
例外:payment_gateway step 在部分场景强制标准 URL(generateCheckoutUrlByOrder 513–515 行)。
7. Service / Controller 索引
| 形态 | Home 页面 | Homeapi API | 核心 Service |
|---|---|---|---|
| 标准 | Order.php | Coupon.php | OrderService, CartService |
| 单页 | (主题 JS) | OrderOnePage.php | CheckoutOnePageService |
| 渐进式 | (主题 JS) | OrderSinglePage.php | CheckoutSinglePageService |
| COD | OrderCodPage.php | OrderCodPage.php | CodCartService, CodOrderHandlerService |
| 共用 | — | Cart.php | CheckoutService, OrderDiyOfferHandleService |
8. 排障清单(按形态)
| 现象 | 标准 | 单页 | 渐进式 | COD |
|---|---|---|---|---|
| 积分未扣 | 查 shipping POST offer_from_name | 查 complete 是否传 trans_info.offer_from_name | 查 shipping-method POST | 不支持 order_diy_offer |
| 券未绑定 | Cookie / savePreCoupon | complete savePreCoupon | email 后 use-coupon | CodCoupon |
| 价格与下单不一致 | getList reconcile | complete 前调 price vs complete 落盘 | 同标准 | 仅内存 DTO |
| 替换型券仍带满减 | 查 checkCouponUseWithPromotionStatus | 同左 | 同左 | 已知:可能双计 |
| 跳错结账页 | checkout_process / smart Cookie | order.checkout_type 是否 one_page | 是否 single_page | cod_checkout_type |
9. 与优惠文档的交叉引用
| 主题 | 文档位置 |
|---|---|
| promotion_price 计算顺序 | promotion-discount-checkout §2 |
| order_diy_offer 类型 | promotion-discount-checkout §3 |
| 券 REPLACE 全路径 | promotion-discount-checkout §6.7 |
| diy_offer 各 type | promotion-discount-checkout §4.3 |
| COD 单页着陆 | cod-one-page-checkout.md |
细节附录;主流程见 checkout-flows.md。FAQ 见 faq.md。