Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Build artifacts and dependencies
node_modules/
vendor/
target/
dist/
build/
bin/
obj/

# Go module cache
/root/

# IDE files
.idea/
.vscode/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Environment and keys
.env
*.pem
!.env.example

# Logs
*.log
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
# age-scan-examples
# age-scan-examples

This repository contains examples for integrating with Yoti AI Services API in multiple programming languages.

## API Overview

The examples use the Yoti AI Services API with the following structure:

- **Base URL**: `https://api.yoti.com/ai/v1`
- **Available Endpoints**:
- `/age` - Age estimation only
- `/antispoofing` - Liveness/antispoofing check only
- `/age-antispoofing` - Combined age estimation and antispoofing check (default)

## Available Examples

- [Python](./python/README.md)
- [JavaScript/Node.js](./javascript/README.md)
- [Java](./java/README.md)
- [Go](./go/README.md)
- [.NET Core](./dotnet/CoreExample/README.md)
- [PHP](./php/README.md)

## Getting Started

Each example requires:

1. A Yoti SDK ID and PEM file (obtain from [Yoti Hub](https://hub.yoti.com))
2. Configuration of environment variables or properties file
3. An image file for testing (provided as `testimage.jpg` or `image.jpeg`)

See individual example READMEs for language-specific setup instructions.

## Reference

For more information, see:
- [Yoti AI Services API Documentation](https://developers.yoti.com/ai-services-api)
- [Web FCM Demo](https://github.com/getyoti/web-fcm-demo)
3 changes: 2 additions & 1 deletion dotnet/CoreExample/CoreExample/.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
TEST_IMAGE_PATH = "testimage.jpg"
BASE_URL = "https://api.yoti.com"
BASE_URL = "https://api.yoti.com/ai/v1"
ENDPOINT = "age-antispoofing"
PEM_FILE_PATH = "keys/key.pem"
SDK_ID = ""

34 changes: 17 additions & 17 deletions dotnet/CoreExample/CoreExample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Yoti.Auth.Web;
using System;
Expand All @@ -8,13 +8,13 @@
using Org.BouncyCastle.Crypto;
using System.Text;

namespace CoreExample
{
class Program
{
static void Main(string[] args)
{
namespace CoreExample
{

class Program
{
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
var serviceProvider = serviceCollection.BuildServiceProvider();
Expand Down Expand Up @@ -46,14 +46,14 @@ static void Main(string[] args)

string serializedRequest = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
data = Convert.ToBase64String(imgBytes)
img = Convert.ToBase64String(imgBytes)
});

byte[] byteContent = Encoding.UTF8.GetBytes(serializedRequest);

Request request = new RequestBuilder()
.WithBaseUri(new Uri(DotNetEnv.Env.GetString("BASE_URL") + "/api/v1/age-verification"))
.WithEndpoint("/checks")
.WithBaseUri(new Uri(DotNetEnv.Env.GetString("BASE_URL")))
.WithEndpoint("/" + DotNetEnv.Env.GetString("ENDPOINT"))
.WithHttpMethod(HttpMethod.Post)
.WithKeyPair(key)
.WithHeader("X-Yoti-Auth-Id", DotNetEnv.Env.GetString("SDK_ID"))
Expand All @@ -78,9 +78,9 @@ private static void ConfigureServices(IServiceCollection services)

}

}
}

}
}



3 changes: 2 additions & 1 deletion dotnet/CoreExample/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# .NET Core Example

- Save your PEM file into the keys directory and name it key.pem
- Edit the `.env` file, adding client SDK ID and BASE_URL
- Edit the `.env` file, adding client SDK ID
- Optional - Update the ENDPOINT in `.env` (default is `age-antispoofing`, can be `age`, `antispoofing`, or `age-antispoofing`)
- Optional - Replace the `testimage.jpg` with your own.
- Run the project with `dotnet run -p CoreExample.csproj`
3 changes: 2 additions & 1 deletion go/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
TEST_IMAGE_PATH = "testimage.jpg"
BASE_URL = "https://api.yoti.com"
BASE_URL = "https://api.yoti.com/ai/v1"
ENDPOINT = "age-antispoofing"
PEM_FILE_PATH = "keys/key.pem"
SDK_ID = ""

3 changes: 2 additions & 1 deletion go/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Golang Example

- Save your PEM file into the keys directory and name it key.pem
- Edit the `.env` file, adding client SDK ID and BASE_URL
- Copy `.env.example` to `.env` and add your client SDK ID
- Optional - Update the ENDPOINT in `.env` (default is `age-antispoofing`, can be `age`, `antispoofing`, or `age-antispoofing`)
- Optional - Replace the `testimage.jpg` with your own.
- Run the project with `go run main.go`
8 changes: 8 additions & 0 deletions go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/getyoti/age-scan-examples/go

go 1.24.4

require (
github.com/getyoti/yoti-go-sdk/v3 v3.15.0
github.com/joho/godotenv v1.5.1
)
8 changes: 8 additions & 0 deletions go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/getyoti/yoti-go-sdk/v3 v3.15.0 h1:jLbL6gGvNXUYaI8GHQ3S7uLoPk/S6SMeWaHI4TtSIFo=
github.com/getyoti/yoti-go-sdk/v3 v3.15.0/go.mod h1:FH8g7mRttc6SBUd9P0Jihm7ut0rNhkU3rDFljUHL33I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
43 changes: 33 additions & 10 deletions go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,69 @@ import (
)

type Estimation struct {
Data string `json:"data"`
Img string `json:"img"`
}

func main(){

sdkID := os.Getenv("SDK_ID")
baseURL := os.Getenv("BASE_URL")
endpoint := os.Getenv("ENDPOINT")
keyFile := os.Getenv("PEM_FILE_PATH")
imgPath := os.Getenv("TEST_IMAGE_PATH")

file, _ := os.Open(imgPath)
file, err := os.Open(imgPath)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
content, _ := ioutil.ReadAll(reader)
content, err := ioutil.ReadAll(reader)
if err != nil {
fmt.Println(err)
return
}
encoded := base64.StdEncoding.EncodeToString(content)

estimation := &Estimation{
Data:encoded,
Img: encoded,
}

jsonData,err := json.Marshal(estimation)
jsonData, err := json.Marshal(estimation)
if err != nil {
fmt.Println(err)
return
}

key, _ := ioutil.ReadFile(keyFile)
key, err := ioutil.ReadFile(keyFile)
if err != nil {
fmt.Println(err)
return
}
// Create request
req,_ := requests.SignedRequest{
req, err := requests.SignedRequest{
HTTPMethod: http.MethodPost,
BaseURL: baseURL + "/api/v1/age-verification",
Endpoint: "/checks",
BaseURL: baseURL,
Endpoint: "/" + endpoint,
Headers: map[string][]string{
"Content-Type": {"application/json"},
"Accept": {"application/json"},
"X-Yoti-Auth-Id":{sdkID},
},
Body: jsonData,
}.WithPemFile(key).Request()
if err != nil {
fmt.Println(err)
return
}

//get Yoti response
response, _ := http.DefaultClient.Do(req)
response, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println(err)
return
}

buffer := new(strings.Builder)
_, err = io.Copy(buffer, response.Body)
Expand Down
5 changes: 3 additions & 2 deletions java/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Java Example

- Save your PEM file into the keys directory and name it key.pem
- Edit the `application.properties` file, adding client SDK ID and BASE_URL
- Save your PEM file into the `resources/keys` directory and name it key.pem
- Edit the `application.properties` file, adding client SDK ID
- Optional - Update the ENDPOINT in `application.properties` (default is `age-antispoofing`, can be `age`, `antispoofing`, or `age-antispoofing`)
- Optional - Replace the testimage.jpg with your own.
- Build the project `mvn clean package`
- Run the example `java -jar target/age-scan-1.0.jar`
45 changes: 42 additions & 3 deletions java/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.yoti</groupId>
Expand All @@ -18,6 +18,45 @@

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.yoti.agescan.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
Expand Down Expand Up @@ -46,4 +85,4 @@
</dependencies>


</project>
</project>
25 changes: 16 additions & 9 deletions java/src/main/java/com/yoti/agescan/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,31 @@ public static void main(String[] args) {
BufferedImage bufferedImage = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
bufferedImage = ImageIO.read(new File(Application.class.getClassLoader().
getResource(prop.getProperty("TEST_IMAGE_PATH")).
getFile()));
InputStream imageStream = Application.class.getClassLoader()
.getResourceAsStream(prop.getProperty("TEST_IMAGE_PATH"));
if (imageStream == null) {
System.out.println("Image not found in resources!");
return;
}
bufferedImage = ImageIO.read(imageStream);
byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream );
ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);
} catch (IOException e) {
e.printStackTrace();
}

byte[] image = byteArrayOutputStream.toByteArray();
JsonObject body = new JsonObject();
body.put("data", image);
body.put("img", image);


byte[] payload = body.encode().getBytes();

try {
SignedRequest signedRequest = SignedRequestBuilder.newInstance()
.withKeyPair(findKeyPair())
.withBaseUrl(prop.getProperty("HOST") + "/api/v1/age-verification")
.withEndpoint("/checks")
.withBaseUrl(prop.getProperty("BASE_URL"))
.withEndpoint("/" + prop.getProperty("ENDPOINT"))
.withPayload(payload)
.withHttpMethod("POST")
.withHeader("X-Yoti-Auth-Id", prop.getProperty("SDK_ID"))
Expand All @@ -74,8 +78,11 @@ public static void main(String[] args) {
* @throws IOException
*/
private static KeyPair findKeyPair() throws IOException {
InputStream keyStream = new FileInputStream(Application.class.getClassLoader().getResource(prop.getProperty("PEM_FILE_PATH")).getFile());
PEMParser reader = new PEMParser(new BufferedReader(new InputStreamReader(keyStream, Charset.defaultCharset())));
InputStream keyStream = Application.class.getClassLoader()
.getResourceAsStream(prop.getProperty("PEM_FILE_PATH"));
if (keyStream == null) {
throw new FileNotFoundException("PEM key file not found in resources!");
} PEMParser reader = new PEMParser(new BufferedReader(new InputStreamReader(keyStream, Charset.defaultCharset())));
KeyPair keyPair = null;
for (Object o = null; (o = reader.readObject()) != null;) {
if (o instanceof PEMKeyPair) {
Expand Down
3 changes: 2 additions & 1 deletion java/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
TEST_IMAGE_PATH = testimage.jpg
HOST =
BASE_URL = https://api.yoti.com/ai/v1
ENDPOINT = age-antispoofing
PEM_FILE_PATH = keys/key.pem
SDK_ID =
Loading