paascloud/paascloud-master · warning · ValidateCodeException

Mobile当天短信发送数上限

Error message

Mobile当天短信发送数上限

What it means

SmsCodeProcessor.checkSendSmsCount enforces per-mobile daily SMS quotas by reading a Redis counter (mobileSmsCountKey, 1-day TTL) and comparing it to sms.getMobileMaxSendCount(). If the counter exceeds the configured mobile daily limit, it throws ValidateCodeException('Mobile当天短信发送数上限'). This is a deliberate anti-abuse throttle to stop a single phone number from exhausting SMS quota or receiving too many codes.

Solutions

  1. Wait for the 1-day Redis key (mobile SMS count) to expire, or delete the key (e.g. DEL <mobileSmsCountKey>) to reset the quota for testing
  2. Raise sms.getMobileMaxSendCount() in the security code SMS properties configuration to a value fitting real traffic
  3. In tests, use different phone numbers per run or flush the Redis counter before each test
  4. Catch ValidateCodeException in the controller and return a friendly 'daily SMS limit reached, try tomorrow' message

Example fix

// before: repeated test sends hit the limit
smsCodeSender.send(mobile); // throws ValidateCodeException after N sends
// after: reset the counter in test setup
@Test
void setUp() {
    redisTemplate.delete("paascloud:sms:count:" + mobile);
}
Defensive patterns

Strategy: try-catch

Validate before calling

Integer count = (Integer) redisTemplate.opsForValue().get(mobileSmsCountKey);
if (count != null && count > maxMobileSendCount) {
    throw new BizException("SMS daily limit reached for this phone");
}

Try / catch

try {
    smsCodeSender.send(mobile);
} catch (ValidateCodeException e) {
    if (e.getMessage().contains("上限")) {
        return Result.error(429, "短信发送次数已达今日上限,请明日再试");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling the SMS send flow (send -> checkSendSmsCount) for a mobile number whose Redis day-counter already exceeds smsProperties.getMobileMaxSendCount(); the counter increments on every send and lives 1 day, so repeated sends to the same phone within 24h trip it.

Common situations: QA/load tests hammering one phone number; users repeatedly requesting codes during login failures; mobileMaxSendCount configured too low in properties for legitimate traffic; integration tests not resetting the Redis counter between runs.

Related errors


AI-assisted analysis of paascloud/paascloud-master@781281a950 (2026-09-10). Data as JSON: /api/errors/20ae2286ed1a21f1. Report an issue: GitHub.

Appendix: source

Thrown at paascloud-common/paascloud-security-core/src/main/java/com/paascloud/security/core/validate/code/sms/SmsCodeProcessor.java:116

	private void checkSendSmsCount(String mobile, String ipAddr) {
		String mobileSmsCountKey = RedisKeyUtil.getSendSmsCountKey(mobile, "mobile");
		String ipSmsCountKey = RedisKeyUtil.getSendSmsCountKey(ipAddr, "ip");
		String totalSmsCountKey = RedisKeyUtil.getSendSmsCountKey("total", "total");
		String sendSmsRateKey = RedisKeyUtil.getSendSmsRateKey(ipAddr);
		SmsCodeProperties sms = securityProperties.getCode().getSms();

		Integer sendSmsRateCount = (Integer) redisTemplate.opsForValue().get(sendSmsRateKey);
		if (sendSmsRateCount != null) {
			log.error("操作频率过快 ipAddr={}, mobile={}", ipAddr, mobile);
			throw new ValidateCodeException("操作频率过快");
		} else {
			redisTemplate.opsForValue().set(sendSmsRateKey, 1, 1, TimeUnit.MINUTES);
		}

		Integer mobileSmsCount = (Integer) redisTemplate.opsForValue().get(mobileSmsCountKey);
		if (mobileSmsCount != null && mobileSmsCount > sms.getMobileMaxSendCount()) {
			log.error("Mobile当天短信发送数上限 ipAddr={}, mobile={}", ipAddr, mobile);
			throw new ValidateCodeException("Mobile当天短信发送数上限");
		} else {
			redisTemplate.opsForValue().set(mobileSmsCountKey, mobileSmsCount == null ? 1 : mobileSmsCount + 1, 1, TimeUnit.DAYS);
		}
		Integer ipSmsCount = (Integer) redisTemplate.opsForValue().get(ipSmsCountKey);
		if (ipSmsCount != null && ipSmsCount > sms.getIpMaxSendCount()) {
			log.error("IP当天短信发送数上限 ipAddr={}, mobile={}", ipAddr, mobile);
			throw new ValidateCodeException("IP当天短信发送数上限");
		} else {
			redisTemplate.opsForValue().set(ipSmsCountKey, ipSmsCount == null ? 1 : ipSmsCount + 1, 1, TimeUnit.DAYS);
		}
		Integer totalSmsCount = (Integer) redisTemplate.opsForValue().get(totalSmsCountKey);
		if (totalSmsCount != null && totalSmsCount > sms.getTotalMaxSendCount()) {
			log.error("当天短信发送数上限 ipAddr={}, mobile={}", ipAddr, mobile);
			throw new ValidateCodeException("当天短信发送数上限");
		} else {
			redisTemplate.opsForValue().set(totalSmsCountKey, totalSmsCount == null ? 1 : totalSmsCount + 1, 1, TimeUnit.DAYS);
		}
	}

View on GitHub (pinned to 781281a950)