package com.izouma.nineth.service.sms; import com.aliyuncs.CommonRequest; import com.aliyuncs.CommonResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import com.izouma.nineth.config.Constants; import com.izouma.nineth.domain.SmsRecord; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.SmsRecordRepo; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.configurationprocessor.json.JSONException; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Date; import java.util.HashMap; @Service @Slf4j public class AliSmsService implements SmsService { @Value("${aliyun.access-key-id}") private String accessKeyId; @Value("${aliyun.access-key-secret}") private String accessKeySecret; @Value("${aliyun.sms-sign}") private String smsSign; @Value("${aliyun.sms-code}") private String smsCode; @Autowired private SmsRecordRepo smsRecordRepo; @Override public String sendVerify(String phone) { if (smsSign.equals("身份验证")) { accessKeyId = "LTAI5tEL3wr9XeiyseqKLrEK"; accessKeySecret = "I9JzOThjzeJMcpVf6melaMY3nt7ucU"; } smsRecordRepo.findLastByPhoneAndExpiresAtAfterAndExpiredFalse(phone, LocalDateTime.now()).ifPresent(record -> { if (record.getCreatedAt().plusMinutes(1L).isAfter(LocalDateTime.now())) { long sec = record.getCreatedAt().plusMinutes(1L).toInstant(ZoneOffset.UTC) .getEpochSecond() - LocalDateTime.now().toInstant(ZoneOffset.UTC).getEpochSecond() + 1; throw new BusinessException("请" + sec + "秒后再试"); } }); String code = RandomStringUtils.randomNumeric(4); DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret); IAcsClient client = new DefaultAcsClient(profile); CommonRequest request = new CommonRequest(); request.setMethod(MethodType.POST); request.setDomain("dysmsapi.aliyuncs.com"); request.setVersion("2017-05-25"); request.setAction("SendSms"); request.putQueryParameter("PhoneNumbers", phone); request.putQueryParameter("SignName", smsSign); request.putQueryParameter("TemplateCode", smsCode); if (smsSign.equals("身份验证")) { request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\",\"product\":\"用户\"}"); } else { request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}"); } try { CommonResponse response = client.getCommonResponse(request); if (response.getHttpStatus() != 200) { throw new BusinessException("发送失败,请稍后再试", response.getHttpStatus() + "," + response.getData()); } log.info("send sms response {}", response.getData()); JSONObject jsonObject = new JSONObject(response.getData()); if (!"ok".equalsIgnoreCase(jsonObject.getString("Code"))) { throw new BusinessException("发送失败,请稍后再试", jsonObject.getString("Message")); } smsRecordRepo.expire(phone); String sessionId = RandomStringUtils.randomAlphabetic(10); smsRecordRepo.save(SmsRecord.builder() .sessionId(sessionId) .phone(phone) .code(code) .expiresAt(LocalDateTime.now().plusMinutes(5)) .expired(false) .build()); return sessionId; } catch (ClientException | JSONException e) { e.printStackTrace(); throw new BusinessException("发送失败,请稍后再试", e.getMessage()); } } @Override public String verify(String phone, String code) { SmsRecord smsRecord = smsRecordRepo.findLastByPhoneAndExpiresAtAfterAndExpiredFalse(phone, LocalDateTime.now()) .orElseThrow(new BusinessException("短信验证码错误")); if (!smsRecord.getCode().equalsIgnoreCase(code)) { throw new BusinessException("短信验证码错误"); } smsRecord.setExpired(true); smsRecordRepo.save(smsRecord); return Jwts.builder() .setClaims(new HashMap<>()) .setSubject(phone) .setIssuedAt(new Date()) .setExpiration(new Date(new Date().getTime() + 10 * 60 * 1000)) //10min .signWith(SignatureAlgorithm.HS512, Constants.SMS_TOKEN_SECRET) .compact(); } }