DNN Hotcakes checkout address 禁止输入 PO Box
结论
无需为了前端提示专门使用 integration pipeline。可以在 checkout 页面加入 jQuery,在用户填写地址或提交订单时检查是否包含 PO Box。如果发现,就显示错误并阻止提交。
不过,jQuery 只能完成界面层验证。用户仍可通过禁用 JavaScript 或直接发送请求绕过检查。如果“禁止 PO Box”是实际业务规则,服务端也必须在结账扩展点再次验证。integration pipeline 能否承担服务端拦截,要看当前 Hotcakes 版本及其 checkout workflow 配置,不能只依赖前端脚本。
前端验证
下面的示例可以识别这些常见写法:
PO BoxP.O. BoxP O BoxP.O.Box- 大小写混合形式
(function ($) {
"use strict";
var poBoxPattern = /\bP[\s.]*O[\s.]*\s*Box\b/i;
var errorClass = "po-box-validation-error";
function isPoBox(value) {
return poBoxPattern.test($.trim(value || ""));
}
function validateAddressField($field) {
var $error = $field.siblings("." + errorClass);
if (!$error.length) {
$error = $("<div>", {
"class": errorClass,
"role": "alert",
"text": "我们无法配送至 PO Box,请填写实际街道地址。"
}).hide();
$field.after($error);
}
var invalid = isPoBox($field.val());
$field.toggleClass("input-validation-error", invalid);
$error.toggle(invalid);
if ($field[0] && typeof $field[0].setCustomValidity === "function") {
$field[0].setCustomValidity(
invalid ? "我们无法配送至 PO Box,请填写实际街道地址。" : ""
);
}
return !invalid;
}
function getAddressFields() {
/*
* 请替换为实际 checkout 页面中的地址选择器。
* 如果账单地址和配送地址都禁止 PO Box,应同时包含两组字段。
*/
return $(
"#shipping-address-line1, " +
"#shipping-address-line2, " +
"#billing-address-line1, " +
"#billing-address-line2"
);
}
// Hotcakes 的部分 checkout 区域可能通过 AJAX 重绘,因此使用委托事件。
$(document).on(
"input change blur",
"#shipping-address-line1, " +
"#shipping-address-line2, " +
"#billing-address-line1, " +
"#billing-address-line2",
function () {
validateAddressField($(this));
}
);
/*
* 将选择器替换为实际的 checkout form。
* 如果结账按钮完全由 JavaScript/AJAX 控制,还需要在其点击处理入口执行相同检查。
*/
$(document).on("submit", "#checkout-form", function (event) {
var valid = true;
var $firstInvalid = $();
getAddressFields().each(function () {
var $field = $(this);
if (!validateAddressField($field)) {
valid = false;
if (!$firstInvalid.length) {
$firstInvalid = $field;
}
}
});
if (!valid) {
event.preventDefault();
event.stopImmediatePropagation();
$firstInvalid.trigger("focus");
return false;
}
});
})(jQuery);
错误样式可以单独添加到主题 CSS 中:
.po-box-validation-error {
margin-top: 4px;
color: #b00020;
font-size: 0.875rem;
}
.input-validation-error {
border-color: #b00020;
}
确定实际字段和表单选择器
示例中的 ID 只是占位符,不能假定 Hotcakes 实际使用这些名称。请打开浏览器开发者工具检查 checkout 页面,并确认:
- Shipping Address Line 1 和 Line 2 的实际
id或name。 - 如果账单地址也受限制,确认对应的 Billing Address 字段。
- checkout 表单或“继续/提交订单”按钮的实际选择器。
- 选择“账单地址同配送地址”、切换配送方式或完成 AJAX 更新后,地址区域是否会重新生成。
选择器应优先使用稳定的 id、name 或自定义 data-* 属性,避免依赖容易随主题布局变化的层级结构。
服务端验证
服务端应在订单最终创建或提交付款之前检查配送地址。不同 Hotcakes/DNN 版本提供的 checkout workflow、integration task 和错误集合 API 可能不同。下面只展示验证逻辑,并不是可以直接注册到特定版本中的类:
using System.Text.RegularExpressions;
public static class AddressPolicy
{
private static readonly Regex PoBoxPattern = new Regex(
@"\bP[\s.]*O[\s.]*\s*Box\b",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant
);
public static bool ContainsPoBox(params string[] addressLines)
{
if (addressLines == null)
{
return false;
}
foreach (var line in addressLines)
{
if (!string.IsNullOrWhiteSpace(line) && PoBoxPattern.IsMatch(line))
{
return true;
}
}
return false;
}
}
在当前版本提供的服务端结账扩展点中调用它:
var shippingAddress = order.ShippingAddress;
if (AddressPolicy.ContainsPoBox(
shippingAddress.Line1,
shippingAddress.Line2))
{
// 使用当前 Hotcakes 版本提供的错误集合或验证结果 API:
// 1. 添加用户可见的验证错误;
// 2. 返回失败;
// 3. 阻止订单进入付款和最终提交阶段。
}
具体的 order 类型、地址属性名、任务基类和添加错误的方法,应以项目实际引用的 Hotcakes 程序集为准,不要直接套用其他版本的 API 示例。
如果当前版本的 integration pipeline 能在付款前读取订单地址、返回失败并将消息传回 checkout 页面,就可以在该阶段验证。如果 pipeline 只负责订单完成后与外部系统集成,此时再验证已经太晚,应改用 checkout validation 或 order workflow 中更早的扩展点。
注意事项
- 通常需要同时检查地址第一行和第二行,否则用户可能把
PO Box填在 Address Line 2。 - 先确认规则是否只禁止英文
PO Box,以及是否还需要拦截Post Office Box、P.O.B.、PMB等形式。业务未确认前,不要自行扩大拦截范围。 - 不建议只判断
value.indexOf("PO Box"),因为这种写法无法处理大小写和标点变化。 - 前端和服务端应使用相同的匹配规则,避免一端允许、另一端拒绝。
- 如果 checkout 使用 AJAX,需要把验证接入实际的 AJAX 提交入口。只监听原生
submit事件,未必能覆盖所有主题或定制结账流程。 - 服务端拒绝地址时,应返回普通的地址验证错误,不要等到付款完成后再向用户显示集成失败。
备注:内容仅供参考。
