alipay.trade.page.pay 的 time_expire 应传入哪个时区?
支付小周
结论
alipay.trade.page.pay 的 time_expire 应传中国标准时间,也就是东八区时间(UTC+8),不能直接传 UTC 时间。
参数格式为:
yyyy-MM-dd HH:mm:ss
例如,订单需要在北京时间 2026-09-09 18:30:00 过期,应传:
2026-09-09 18:30:00
参数值不包含 Z、+08:00 等时区标识。调用方需要先将时间转换为 Asia/Shanghai 时区,再按指定格式生成字符串。
为什么不能直接传 UTC 时间
time_expire 表示一个绝对过期时间,但它使用的是不带时区信息的日期字符串。支付宝无法通过参数内容判断调用方传入的是 UTC、服务器本地时间还是其他时区的时间。
直接格式化 UTC 时间并传入,可能导致 8 小时的偏差。例如:
UTC 时间: 2026-09-09 10:30:00
北京时间: 2026-09-09 18:30:00
如果订单原定于北京时间 18
过期,实际传入的却是:2026-09-09 10:30:00
支付宝会按东八区时间处理这个值,订单可能提前 8 小时过期。
正确处理方式
无论应用服务器部署在哪个地区,都应显式指定 Asia/Shanghai,不要依赖操作系统、JVM 或 PHP 运行环境的默认时区。
处理步骤如下:
- 获取当前时间或业务指定的过期时间。
- 将其转换到
Asia/Shanghai时区。 - 按
yyyy-MM-dd HH:mm:ss格式输出。 - 把生成的字符串赋值给
time_expire。
Java 示例
下面的代码将订单过期时间设为当前时间之后 30 分钟:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
ZoneId alipayZone = ZoneId.of("Asia/Shanghai");
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timeExpire = ZonedDateTime.now(alipayZone)
.plusMinutes(30)
.format(formatter);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setTotalAmount("100.00");
model.setSubject("测试订单");
model.setProductCode("FAST_INSTANT_TRADE_PAY");
model.setTimeExpire(timeExpire);
request.setBizModel(model);
如果业务系统内部统一使用 UTC 保存时间,需要先转换时区:
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
Instant expireInstant = Instant.now().plusSeconds(30 * 60);
String timeExpire = expireInstant
.atZone(ZoneId.of("Asia/Shanghai"))
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
PHP 示例
<?php
$expireTime = new DateTime('now', new DateTimeZone('Asia/Shanghai'));
$expireTime->modify('+30 minutes');
$timeExpire = $expireTime->format('Y-m-d H:i:s');
$bizContent = [
'out_trade_no' => 'ORDER_202609090001',
'total_amount' => '100.00',
'subject' => '测试订单',
'product_code' => 'FAST_INSTANT_TRADE_PAY',
'time_expire' => $timeExpire,
];
已有 UTC 时间时,可以显式转换:
<?php
$expireTime = new DateTime(
'2026-09-09 10:30:00',
new DateTimeZone('UTC')
);
$expireTime->setTimezone(new DateTimeZone('Asia/Shanghai'));
$timeExpire = $expireTime->format('Y-m-d H:i:s');
// 结果:2026-09-09 18:30:00
注意事项
- 不要传入 ISO 8601 格式,例如
2026-09-09T18:30:00+08:00或2026-09-09T10:30:00Z。 - 不要依赖服务器的默认时区。如果服务器运行在 UTC 环境中,直接格式化当前时间会产生偏差。
time_expire表示绝对过期时间。如果需要使用相对有效期,应根据接口当前文档确认是否改用timeout_express。- 如果同时传入
time_expire和timeout_express,应按支付宝当前接口文档规定的优先级处理。为避免歧义,通常只传其中一个。 - 生成时间后,应确认它晚于当前北京时间,并为网络延迟和请求处理预留时间。
- 如果对过期时间有严格要求,业务系统内部可使用时间戳或 UTC 保存时间,仅在组装支付宝请求参数时转换为
Asia/Shanghai。
备注:内容仅供参考。
