# 扩展点

> Shoplazza 结账扩展可渲染的全部扩展点：结账页与感谢页的各个插槽位置，以及传给 extend() 的名称。

扩展点是结账页和感谢页上的固定插槽。把插槽名字填进 `extend()` 的 `extensionPoint` 字段，你的 HTML 就渲染在那个位置：

```javascript
import { extend } from 'shoplazza-extension-ui';

extend({
  extensionPoint: 'Checkout::StepSubmit::RenderBefore',
  component: '<p>30 天内免费退货</p>',
});
```

同一个扩展点可以被多次 `extend`，内容按调用顺序追加，不会互相覆盖。`extend` 的完整签名和 HTML 模板机制见 [extend 函数](/docs/app/extensions/checkout/extension-reference#extend-函数与-html-模板)。下面每个区域还列出了该区域可以用 [deleteTarget](/docs/app/extensions/checkout/extension-reference#隐藏原生模块deletetarget) 隐藏的原生模块，用来让自己的内容替换掉原生内容，而不是并排摆着。

## 结账页

以下扩展点渲染在结账页上。具体哪些插槽会出现在屏幕上取决于店铺配置：自提相关的插槽需要开启门店自提，分步骤的插槽只在两页和三页布局下才有。

### 页面框架

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::RenderBefore` | 页面之前 |
| `Checkout::RenderAfter` | 页面之后 |
| `Checkout::Head::RenderAfter` | 页头的店铺 logo 后面 |
| `Checkout::Advertise::RenderBefore` | 广告位之前 |
| `Checkout::MainHeader::RenderAfter` | 主区域头部之后 |
| `Checkout::Main::RenderBefore` | 地址信息列之前 |
| `Checkout::Main::RenderAfter` | 地址信息列之后 |
| `Checkout::FooterTop::RenderAfter` | 页脚顶部之后 |
| `Checkout::CheckoutFooter::RenderBefore` | 页脚之前 |
| `Checkout::CheckoutFooter::RenderAfter` | 页脚之后 |

这一区域可隐藏的原生模块：`header`、`loginOrLogout`。

### 步骤导航栏

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::Navigate::RenderBefore` | 步骤导航栏的前面 |
| `Checkout::Navigate::RenderAfter` | 步骤导航栏的后面 |

这一区域可隐藏的原生模块：`navigate`。

### 已填信息卡片

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::FilledInformation::RenderAfter` | 已填信息卡片之后 |

这一区域可隐藏的原生模块：`addressCard`。

### 联系信息

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::ContactInformation::RenderBefore` | 联系信息模块的前面 |
| `Checkout::ContactInformation::RenderAfter` | 联系信息模块的后面 |
| `Checkout::ContactInformationHeader::RenderAfter` | 联系信息标题的后面 |
| `Checkout::BlockContactInformation::RenderAfter` | 联系方式之后；联系方式被隐藏时这个点位也跟着隐藏 |
| `Checkout::ContactEmail::RenderAfter` | 邮箱输入框的后面 |
| `Checkout::ContactPhone::RenderAfter` | 手机号输入框的后面 |
| `Checkout::EmailOrPhone::RenderAfter` | 「邮箱或手机号」输入框之后 |

这一区域可隐藏的原生模块：`contactInformation`、`contactInformationHeader`、`contactEmail`、`contactPhone`、`emailOrPhone`、`contactSubscribe`。

### 收货地址

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::ShippingAddress::RenderAfter` | 收货地址模块之后 |
| `Checkout::ShippingAddressHeader::RenderAfter` | 收货地址标题之后 |
| `Checkout::ShippingAddressForm::RenderBefore` | 收货地址表单之前 |
| `Checkout::ShippingAddressForm::RenderAfter` | 收货地址表单之后 |

这一区域可隐藏的原生模块：`shippingAddress`、`shippingAddressHeader`、`shippingAddressBook`、`securityIdentifier`。

### 账单地址

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::BillingAddress::RenderBefore` | 账单地址模块之前 |
| `Checkout::BillingAddress::RenderAfter` | 账单地址模块之后 |

这一区域可隐藏的原生模块：`billingAddress`。

### 交付方式

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::DeliveryMethod::RenderBefore` | 交付方式模块之前 |
| `Checkout::DeliveryMethod::RenderAfter` | 交付方式模块之后 |
| `Checkout::DeliveryMethodHeader::RenderAfter` | 交付方式标题之后 |

这一区域可隐藏的原生模块：`deliveryMethod`、`deliveryMethodHeader`。

### 物流方案列表

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::ShippingList::RenderAfter` | 物流方案模块之后 |
| `Checkout::ShippingLinesTitle::RenderBefore` | 物流方案列表标题的前面 |
| `Checkout::ShippingLinesTitle::RenderAfter` | 物流方案列表标题的后面 |
| `Checkout::ShippingLines::RenderAfter` | 物流方案列表之后 |

这一区域可隐藏的原生模块：`shippingList`、`shippingLinesTitle`。

### 自提信息

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::PickupInformation::RenderBefore` | 自提信息模块之前；顾客切换到自提方式后才展示这个模块 |
| `Checkout::PickupInformation::RenderAfter` | 自提信息模块之后；顾客切换到自提方式后才展示这个模块 |
| `Checkout::PickupInformationHeader::RenderAfter` | 自提信息标题的后面 |

这一区域可隐藏的原生模块：`pickupInformation`、`pickupInformationHeader`。

### 自提地址列表

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::PickupAddress::RenderBefore` | 自提地址列表的前面 |
| `Checkout::PickupAddress::RenderAfter` | 自提地址列表的后面 |
| `Checkout::PickupAddressHeader::RenderAfter` | 自提地址列表标题的后面 |

这一区域可隐藏的原生模块：`pickupAddress`、`pickupAddressHeader`。

### 支付

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::SectionPayment::RenderBefore` | 支付区块之前 |
| `Checkout::SectionPayment::RenderAfter` | 支付区块之后 |
| `Checkout::PaymentHeader::RenderBefore` | 支付方式标题之前 |
| `Checkout::PaymentHeader::RenderAfter` | 支付方式标题之后 |
| `Checkout::Payment::RenderAfter` | 支付方式列表之后 |

这一区域可隐藏的原生模块：`paymentHeader`、`payPalExpress`。

### 提交按钮

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::StepSubmit::RenderBefore` | 提交按钮之前 |
| `Checkout::StepSubmit::RenderAfter` | 提交按钮之后 |
| `Checkout::InfoSubmit::RenderBefore` | 信息步提交按钮之前 |
| `Checkout::InfoSubmit::RenderAfter` | 信息步提交按钮之后 |
| `Checkout::ShippingSubmit::RenderBefore` | 配送步提交按钮之前 |
| `Checkout::ShippingSubmit::RenderAfter` | 配送步提交按钮之后 |
| `Checkout::PaymentSubmit::RenderBefore` | 支付步提交按钮之前 |
| `Checkout::PaymentSubmit::RenderAfter` | 支付步提交按钮之后 |

这一区域可隐藏的原生模块：`infoSubmit`、`shippingSubmit`、`paymentSubmit`、`returnBtn`。

### 留言备注

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::SpecialInstruction::RenderBefore` | 留言备注模块之前 |
| `Checkout::SpecialInstruction::RenderAfter` | 留言备注模块之后 |

这一区域可隐藏的原生模块：`specialInstruction`。

### 订单摘要

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::Summary::RenderBefore` | 商品信息列之前 |
| `Checkout::Summary::RenderAfter` | 商品信息列之后 |
| `Checkout::OrderSummaryHeader::RenderBefore` | 订单摘要标题之前 |
| `Checkout::OrderSummaryHeader::RenderAfter` | 订单摘要标题之后 |
| `Checkout::OrderSummary::RenderAfter` | 订单摘要之后 |

这一区域可隐藏的原生模块：`orderSummary`、`orderSummaryHeader`。

### 商品行列表

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::ProductList::RenderBefore` | 商品列表模块之前 |
| `Checkout::ProductList::RenderAfter` | 商品列表模块之后 |

这一区域可隐藏的原生模块：`productList`、`ProductListCover`、`productListSkuProperties`。

### 优惠码与礼品卡

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::Reductions::RenderBefore` | 优惠码与礼品卡模块之前 |
| `Checkout::Reductions::RenderAfter` | 优惠码与礼品卡模块之后 |
| `Checkout::GiftCardTag::RenderAfter` | 优惠码与礼品卡 tag 之后 |

这一区域可隐藏的原生模块：`reductions`、`giftCardTag`、`mobileCoupon`。

### 价格明细

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::PriceList::RenderBefore` | 价格明细模块之前 |
| `Checkout::PriceList::RenderAfter` | 价格明细模块之后 |
| `Checkout::PriceListSubTotal::RenderAfter` | 小计之后 |
| `Checkout::PriceListShippingTotal::RenderAfter` | 物流费用之后 |
| `Checkout::PriceListTaxTotal::RenderAfter` | 税费之后 |
| `Checkout::PriceListShippingTaxTotal::RenderAfter` | 物流税费之后 |
| `Checkout::PriceListGiftCard::RenderAfter` | 礼品卡扣减之后 |
| `Checkout::TotalPrice::RenderAfter` | 总价之后 |

这一区域可隐藏的原生模块：`priceList`、`priceListSubTotal`、`priceListShippingTotal`、`priceListTaxTotal`、`priceListShippingTaxTotal`、`priceListGiftCard`、`totalPrice`。

## 感谢页

以下扩展点渲染在感谢页，也就是顾客下单成功后落地的那个页面。感谢页上同样挂着 `CheckoutAPI`，但只有一部分方法能取到数据——顾客已经不再编辑订单了。

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::ThankyouHeader::RenderBefore` | 感谢页头部之前 |
| `Checkout::ThankyouHeader::RenderAfter` | 感谢页头部之后 |
| `Checkout::ThankyouContent::RenderBefore` | 感谢页内容区之前 |
| `Checkout::ThankyouContent::RenderAfter` | 感谢页内容区之后 |
| `Checkout::ResultContentInfo::RenderBefore` | 订单结果信息块之前 |
| `Checkout::ResultContentInfo::RenderAfter` | 订单结果信息块之后 |
| `Checkout::ResultFooter::RenderBefore` | 感谢页底部之前 |
| `Checkout::ResultFooter::RenderAfter` | 感谢页底部之后 |

这一区域可隐藏的原生模块：`thankyouHeader`、`thankyouContent`、`thankyouFooter`、`thankyouShippingInfo`、`thankyouFailOrderStatus`、`thankyouPageGiftCardAddress`、`thankyouPagePickupAddress`。

## 动态扩展点

动态扩展点跟着数据走，每一行渲染一次——每个商品行、每个物流方案、每条价格明细、每个弹窗各一个，所以名字里带着这一行的 id。下面列的是模板，用时把 `{id}` 换成对应数据的 id。

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::Product-{id}::RenderAfter` | 商品行的后面，`{id}` 是商品行 id |
| `Checkout::ProductTitle-{id}::RenderAfter` | 商品行标题的后面，`{id}` 是商品行 id |
| `Checkout::ProductOption-{id}::RenderAfter` | 商品行规格选项的后面，`{id}` 是商品行 id |
| `Checkout::ProductProperty-{id}::RenderAfter` | 商品行自定义属性的后面，`{id}` 是商品行 id |
| `Checkout::ProductApplication-{id}::RenderAfter` | 商品行所享优惠活动的后面，`{id}` 是商品行 id |
| `Checkout::ShippingLine-{id}::RenderAfter` | 物流方案列表中某一项的后面，`{id}` 是物流方案 id |
| `Checkout::PriceListItemTitle-{id}::Replace` | 替换价格明细中某一行的标题，`{id}` 是价格行 id |
| `Checkout::Dialog-{id}::RenderAfter` | 结算中断弹窗的内容区，`{id}` 是 `registerBuyerJourneyIntercept` 回调返回的 `pointId` |
| `Checkout::DialogFooter-{id}::RenderAfter` | 结算中断弹窗的底部区，`{id}` 是 `registerBuyerJourneyIntercept` 回调返回的 `pointId` |
| `Checkout::DialogTrueBtn-{id}::Render` | 结算中断弹窗的确认按钮，`{id}` 是 `registerBuyerJourneyIntercept` 回调返回的 `pointId` |
| `Checkout::DialogFalseBtn-{id}::Render` | 结算中断弹窗的取消按钮，`{id}` 是 `registerBuyerJourneyIntercept` 回调返回的 `pointId` |

用 `CheckoutAPI.extension.generateRealDynamicPoint()` 拼出真实的点位名：

```javascript
const [lineItem] = window.CheckoutAPI.summary.getProductList();
const point = window.CheckoutAPI.extension.generateRealDynamicPoint(
  'Checkout::Product-{id}::RenderAfter',
  lineItem.id,
);
// point === 'Checkout::Product-6c7c018e-bcc6-4896-9b75-238438178cc8::RenderAfter'

extend({
  extensionPoint: point,
  component: '<p>单独发货</p>',
});
```

它等价于把模板里的 `{id}` 替换成数据 id。各类 id 的来源：商品行 id 是 `CheckoutAPI.summary.getProductList()` 返回项里的 `id`，物流方案 id 是 `CheckoutAPI.order.getShippingLines()` 返回项里的 `id`，弹窗 id 是 `registerBuyerJourneyIntercept` 回调返回的 `pointId`。商品行 id 在删除后重新添加时会变，每次现取，不要缓存。

## 逻辑扩展点

| 扩展点 | 位置说明 |
|---|---|
| `Checkout::LogicContainer::RenderAfter` | 不渲染可见内容的容器 |

`Checkout::LogicContainer::RenderAfter` 是给没有界面的扩展用的点位。只需要在结账页跑代码——读 `CheckoutAPI`、注册监听、调自己的后端——又不想在页面上占位置时，挂到这个点位。
