For more information about the code, see Server-Side Demo.

Prerequisites

  • Install Java environment.
  • Install Maven environment.
  • Download IDEA.

Procedure

graph LR; A[Create Spring Boot Project] --> B[Import and Scan SDK] --> C[Configure Developer Information] --> D[Develop APIs] --> E[Test APIs]

Create a Spring Boot project

Spring Boot

Import and scan SDK

Import SDK

sdf-starter current version : 1.3.0-developer-SNAPSHOT

<dependency>
<groupId>com.tuya</groupId>
<artifactId>sdf-developer-starter</artifactId>
<version>${sdf.version}</version>
</dependency>
<repositories>
<repository>
<id>tuya-maven</id>
<url>https://maven-other.tuya.com/repository/maven-public/</url>
</repository>
</repositories>

Scan interceptor in the SDK

In Application.java, add the package sdf-starter to the scan directory. Add the required interceptor to the request interceptor.

TIP

When you add scanBasePackages, make sure to add com.tuya.sdf.starter and the package path of your applications.

package com.tuya.isv.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"com.tuya.sdf.starter","com.tuya.isv.demo"})
public class IsvDemoApplication {
public static void main(String[] args) {
SpringApplication.run(IsvDemoApplication.class, args);
}
}

Scan

Configure developer information

Get the credentials

Copy the App Key and Secret Key from the SaaS No-Code Platform.

  1. Log in to the SaaS No-Code Platform.

  2. Choose My Applications. Click View Development Credentials.

    Credentials

  3. Copy the credentials for use.

    Credentials

Configure the credentials

# application.properties
developer.code=hdxxxxxxxxxxxxy
developer.key=iuIg9oxxxxxxxxxxxxxxxxei

Develop APIs

Develop APIs

Sample code

@RestController
public class DeviceController {
// Inject Bean for cloud-to-cloud integration.
@Resource
DeviceAbility deviceAbility;
@GetMapping("/hello")
public JSONObject hello() {
// Get information about the user of the current request.
SdfUser user = SdfContextHolder.getUser();
// Get information about the SaaS of the current request.
SdfSaas sdfSaas = SdfContextHolder.getSdfSaas();
System.out.println(JSON.toJSONString(user));
System.out.println(JSON.toJSONString(sdfSaas));
// Call the cloud APIs using the cloud-to-cloud integration SDK to get the instruction set by product category.
JSONObject result = deviceAbility.queryDeviceFunctions("dj");
return result;
}
}

Develop cloud-to-cloud integration capabilities

Sample code

public interface DeviceAbility {
@GET("/v1.0/functions/{category}")
JSONObject queryDeviceFunctions(@Path("category") String category);
}

Test APIs

Test Postman APIs

x-sdf-auth is the JWT parameter. For more information, see JWT Features.

Generate a JWT and start testing.

JWT

JWT decoding interceptor

The interceptor path: com.tuya.sdf.starter.interceptor.SdfContextInterceptor.

Hot to implement the interceptor:

  1. Get the JWT in the request header [x-sdf-auth].
  2. Use developer.code and developer.key to decode JWT. Get and set the SaaS and user information of the current request.
  3. Set the access key and secret key used to call Tuya cloud APIs through the tuya-connector.
@Slf4j
@Component
public class SdfContextInterceptor implements HandlerInterceptor {
private static final String JWT_HEADER = "x-sdf-auth";
private static final ObjectMapper objectMapper = new ObjectMapper();
@Resource
private Configuration configuration;
@Value("${developer.code:#{null}}")
private String developerCode;
@Value("${developer.key:#{null}}")
private String developerKey;
private SdfCrypt sdfCrypt;
@PostConstruct
public void init() {
sdfCrypt = new SdfCrypt(developerCode, developerKey);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
try {
String header = request.getHeader(JWT_HEADER);
if (StringUtils.isBlank(header)) {
log.warn("header:[" + JWT_HEADER + "] is null");
return true;
}
Jws<Claims> jws = Jwts.parserBuilder()
.setSigningKey(Encoders.BASE64URL.encode(developerKey.getBytes(StandardCharsets.UTF_8)))
.build()
.parseClaimsJws(header);
Object userObj = jws.getBody().get("user");
Object saasObj = jws.getBody().get("saas");
if (Objects.isNull(userObj) || Objects.isNull(saasObj)) {
log.error("header token user and saas can't null");
throw new SdfException(HEADER_TOKEN_ERROR);
}
String userStr = objectMapper.writeValueAsString(userObj);
SdfUser sdfUser = objectMapper.readValue(userStr, SdfUser.class);
SdfContextHolder.setUser(sdfUser);
String saasStr = objectMapper.writeValueAsString(saasObj);
SdfContextHolder.setSdfSaas(objectMapper.readValue(saasStr, SdfSaas.class));
String clientId = sdfCrypt.decrypt(SdfContextHolder.getSdfSaas().getClientId());
String secretKey = sdfCrypt.decrypt(SdfContextHolder.getSdfSaas().getSecretKey());
configuration.getApiDataSource().setAk(clientId);
configuration.getApiDataSource().setSk(secretKey);
} catch (SignatureException e) {
log.error("header jwt signature error", e);
throw new SdfException(HEADER_TOKEN_ERROR);
} catch (Exception e) {
log.error("jwt parser error", e);
throw new SdfException(HEADER_TOKEN_ERROR);
}
return true;
}
}

Use utility class to generate JWT

Write unit testing

Call the method SdfDeveloperUtil.generateJwtHeader() to generate JSON Web Token (JWT) for backend API debugging.

Sample code

@SpringBootTest
@TestPropertySource("classpath:application.properties")
class IsvDemoApplicationTests {
@Test
void contextLoads() {
}
@Value("${developer.code}")
private String developerCode;
@Value("${developer.key}")
private String developerKey;
@Test
void jwtTest() {
// Set user objects.
SdfUser sdfUser = new SdfUser();
sdfUser.setUserId("bayxxxxxxxxxxxxrh");
// Set SaaS objects.
SdfSaas sdfSaas = new SdfSaas();
sdfSaas.setClientId("upxxxxxxxxxxxxxxxfma");
sdfSaas.setSecretKey("a5xxxxxxxxxxxxxxxxxxb7");
String u = JSON.toJSONString(sdfUser);
String s = JSON.toJSONString(sdfSaas);
System.out.println(u);
System.out.println(s);
// Generate JWT.
System.out.println(SdfDeveloperUtil.generateJwtHeader(developerCode, developerKey, sdfUser, sdfSaas));
}
}

Reference