如何在 HPP 支付表单中显示即将收取的金额?
支付小周
结论
可以让客户看到即将支付的金额,但要分清两件事:
- 交易金额必须通过 HPP 请求中的金额字段传给支付平台。
- HPP 页面是否显示金额通常取决于支付平台的托管页面模板或商户后台配置,并不是 .NET client library 提供的显示选项。
如果当前的 full page redirect 页面没有显示金额,先检查 HPP 模板配置。如果后台找不到相关设置,请联系支付服务商,确认当前账户或页面模板能否启用金额展示。
实现方式
1. 在服务端确定最终金额
服务端必须根据订单重新计算金额,不能把浏览器提交的金额直接作为最终交易金额。
decimal orderTotal = GetOrderTotalFromServer(orderId);
还应锁定订单内容或保存待支付快照,避免跳转到 HPP 后订单金额发生变化。
2. 按 HPP 要求传递金额
许多 HPP 接口要求使用货币的最小单位表示金额。例如:
decimal orderTotal = 49.95m;
long amountInMinorUnits = decimal.ToInt64(
decimal.Round(orderTotal * 100m, 0, MidpointRounding.AwayFromZero)
);
这样会把 49.95 转换为 4995。
构造 HPP 请求时,应使用当前 SDK 或接口文档规定的字段名。例如,部分 HPP 集成使用 HPP_AMOUNT:
var hppRequest = new Dictionary<string, string>
{
["HPP_AMOUNT"] = amountInMinorUnits.ToString(
System.Globalization.CultureInfo.InvariantCulture
),
["HPP_CURRENCY"] = "EUR",
["HPP_ORDER_ID"] = orderId
};
不同支付服务商和 HPP 版本使用的字段名称及金额单位可能不同。上线前应核对当前账户对应的接口文档,不要直接照搬上面的字段名。
3. 在跳转前明确展示金额
即使托管支付页能够显示金额,也建议在跳转前的订单确认页再次展示:
<p>
即将支付:
<strong><%= Server.HtmlEncode(formattedOrderTotal) %></strong>
</p>
金额应在服务端格式化:
decimal orderTotal = GetOrderTotalFromServer(orderId);
formattedOrderTotal = orderTotal.ToString(
"C",
System.Globalization.CultureInfo.GetCultureInfo("en-IE")
);
页面显示的金额和发送给 HPP 的金额必须来自同一次服务端计算。
4. 检查托管页面配置
如果金额已经正确传入,交易也能按正确金额完成,但 HPP 页面仍未显示金额,需要检查:
- 商户后台中的 HPP 页面模板;
- 是否有
Display amount、订单摘要或类似配置; - 当前模板是否允许显示金额和币种;
- full page redirect 与 iframe 模式是否使用不同模板;
- 测试环境和生产环境的模板配置是否一致。
这些设置通常保存在支付平台侧,因此无法通过查看本地 library 源码找到。
注意事项
- 不要让客户通过 JavaScript 或隐藏字段决定实际扣款金额。
- 不要使用
double处理货币,优先使用decimal。 - 不同币种的小数位不一定都是两位,金额转换规则应以支付接口的币种规范为准。
- HPP 返回后,应通过服务端回调、签名验证或交易查询确认实际支付金额,不能只相信浏览器重定向参数。
- 跳转前显示金额只能改善用户体验,不能代替 HPP 请求中的正式金额字段。
- 如果支付平台的标准 HPP 模板不支持显示金额,不建议使用脚本修改托管页面。更可靠的做法是在跳转前提供清晰的订单确认页,或申请支持订单摘要的 HPP 模板。
备注:内容仅供参考。
