diff --git a/.gitignore b/.gitignore
index a809f9962..842d1127f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,4 @@ report.json
# idea files
.idea
-# Generated binaries
-/_examples/docscan/docscan
diff --git a/README.md b/README.md
index b30085144..da12e43fc 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Ago&metric=code_smells)](https://sonarcloud.io/dashboard?id=getyoti%3Ago)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=getyoti%3Ago&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=getyoti%3Ago)
-Welcome to the Yoti Go SDK. This repo contains the tools and step by step instructions you need to quickly integrate your Go back-end with Yoti so that your users can share their identity details with your application in a secure and trusted way.
+Welcome to the Yoti Go SDK. This repo contains the tools and step by step instructions you need to quickly integrate your Go back-end with Yoti so that your users can receipt their identity details with your application in a secure and trusted way.
## Table of Contents
diff --git a/_examples/.gitignore b/_examples/.gitignore
index 4c49bd78f..041d99030 100644
--- a/_examples/.gitignore
+++ b/_examples/.gitignore
@@ -1 +1,9 @@
.env
+# Generated binaries
+docscan/docscan
+idv/idv
+aml/aml
+docscansandbox/docscansandbox
+profile/profile
+profilesandbox/profilesandbox
+digitalidentity/digitalidentity
\ No newline at end of file
diff --git a/_examples/digitalidentity/.env.example b/_examples/digitalidentity/.env.example
new file mode 100644
index 000000000..dc09949e2
--- /dev/null
+++ b/_examples/digitalidentity/.env.example
@@ -0,0 +1,2 @@
+YOTI_CLIENT_SDK_ID=
+YOTI_KEY_FILE_PATH=
\ No newline at end of file
diff --git a/_examples/digitalidentity/.gitignore b/_examples/digitalidentity/.gitignore
new file mode 100644
index 000000000..1418f3360
--- /dev/null
+++ b/_examples/digitalidentity/.gitignore
@@ -0,0 +1,8 @@
+/images/YotiSelfie.jpeg
+
+# Example project generated self-signed certificate
+/yotiSelfSignedCert.pem
+/yotiSelfSignedKey.pem
+
+# Compiled binary
+/digitalidentity
diff --git a/_examples/digitalidentity/README.md b/_examples/digitalidentity/README.md
new file mode 100644
index 000000000..703e89efc
--- /dev/null
+++ b/_examples/digitalidentity/README.md
@@ -0,0 +1,46 @@
+## Table of Contents
+
+1) [Setup](#setup) -
+How to initialise the Yoti client
+
+1) [Running the digitalidentity examples](#running-the-profile-example) -
+Running the digitalidentity example
+
+## Setup
+
+The YotiClient is the SDK entry point. To initialise it you need include the following snippet inside your endpoint initialisation section:
+
+```Go
+clientSdkID := "your-client-sdk-id"
+key, err := os.ReadFile("path/to/your-application-pem-file.pem")
+if err != nil {
+ // handle key load error
+}
+
+client, err := yoti.NewClient(
+ clientSdkID,
+ key)
+```
+
+Where:
+
+* `"your-client-sdk-id"` is the SDK Client Identifier generated by Yoti Hub in the Key tab when you create your application.
+
+* `path/to/your-application-pem-file.pem` is the path to the application pem file. It can be downloaded from the Keys tab in the [Yoti Hub](https://hub.yoti.com/).
+
+Please do not open the pem file as this might corrupt the key, and you will need regenerate your key.
+
+Keeping your settings and access keys outside your repository is highly recommended. You can use a package like [godotenv](https://github.com/joho/godotenv) to manage environment variables more easily.
+
+
+## Running the DigitalIdentity Example
+
+1. Change directory to the profile example folder: `cd _examples/digitalidentity`
+2. On the [Yoti Hub](https://hub.yoti.com/):
+ 1. Set the application domain of your app to `localhost:8080`
+ 2. Set the scenario callback URL to `/digitalidentity`
+3. Rename the [.env.example](_examples/digitalidentity/.env.example) file to `.env` and fill in the required configuration values (mentioned in the [Configuration](#configuration) section)
+4. Build with `go build`
+5. Start the compiled program by running `./digitalidentity`
+
+Visiting `https://localhost:8080/` should show a webpage with a Yoti button rendered on it
diff --git a/_examples/digitalidentity/certificatehelper.go b/_examples/digitalidentity/certificatehelper.go
new file mode 100644
index 000000000..cdcb4f23a
--- /dev/null
+++ b/_examples/digitalidentity/certificatehelper.go
@@ -0,0 +1,175 @@
+package main
+
+import (
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "fmt"
+ "log"
+ "math/big"
+ "net"
+ "os"
+ "strings"
+ "time"
+)
+
+var (
+ validFrom = ""
+ validFor = 2 * 365 * 24 * time.Hour
+ isCA = true
+ rsaBits = 2048
+)
+
+func publicKey(priv interface{}) interface{} {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &k.PublicKey
+ case *ecdsa.PrivateKey:
+ return &k.PublicKey
+ default:
+ return nil
+ }
+}
+
+func pemBlockForKey(priv interface{}) *pem.Block {
+ switch k := priv.(type) {
+ case *rsa.PrivateKey:
+ return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
+ case *ecdsa.PrivateKey:
+ b, err := x509.MarshalECPrivateKey(k)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
+ os.Exit(2)
+ }
+ return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
+ default:
+ return nil
+ }
+}
+
+func certificatePresenceCheck(certPath string, keyPath string) (present bool) {
+ if _, err := os.Stat(certPath); os.IsNotExist(err) {
+ return false
+ }
+ if _, err := os.Stat(keyPath); os.IsNotExist(err) {
+ return false
+ }
+ return true
+}
+
+func generateSelfSignedCertificate(certPath, keyPath, host string) error {
+ priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
+ if err != nil {
+ log.Printf("failed to generate private key: %s", err)
+ return err
+ }
+
+ notBefore, err := parseNotBefore(validFrom)
+ if err != nil {
+ log.Printf("failed to parse 'Not Before' value of cert using validFrom %q, error was: %s", validFrom, err)
+ return err
+ }
+
+ notAfter := notBefore.Add(validFor)
+
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+ if err != nil {
+ log.Printf("failed to generate serial number: %s", err)
+ return err
+ }
+
+ template := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{
+ Organization: []string{"Yoti"},
+ },
+ NotBefore: notBefore,
+ NotAfter: notAfter,
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ hosts := strings.Split(host, ",")
+ for _, h := range hosts {
+ if ip := net.ParseIP(h); ip != nil {
+ template.IPAddresses = append(template.IPAddresses, ip)
+ } else {
+ template.DNSNames = append(template.DNSNames, h)
+ }
+ }
+
+ if isCA {
+ template.IsCA = true
+ template.KeyUsage |= x509.KeyUsageCertSign
+ }
+
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
+ if err != nil {
+ log.Printf("Failed to create certificate: %s", err)
+ return err
+ }
+
+ err = createPemFile(certPath, derBytes)
+ if err != nil {
+ log.Printf("failed to create pem file at %q: %s", certPath, err)
+ return err
+ }
+ log.Printf("written %s\n", certPath)
+
+ err = createKeyFile(keyPath, priv)
+ if err != nil {
+ log.Printf("failed to create key file at %q: %s", keyPath, err)
+ return err
+ }
+ log.Printf("written %s\n", keyPath)
+
+ return nil
+}
+
+func createPemFile(certPath string, derBytes []byte) error {
+ certOut, err := os.Create(certPath)
+
+ if err != nil {
+ log.Printf("failed to open "+certPath+" for writing: %s", err)
+ return err
+ }
+
+ defer certOut.Close()
+ err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+
+ return err
+}
+
+func createKeyFile(keyPath string, privateKey interface{}) error {
+ keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+
+ if err != nil {
+ log.Print("failed to open "+keyPath+" for writing:", err)
+ return err
+ }
+
+ defer keyOut.Close()
+ err = pem.Encode(keyOut, pemBlockForKey(privateKey))
+
+ return err
+}
+
+func parseNotBefore(validFrom string) (notBefore time.Time, err error) {
+ if len(validFrom) == 0 {
+ notBefore = time.Now()
+ } else {
+ notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
+ return time.Time{}, err
+ }
+ }
+
+ return notBefore, nil
+}
diff --git a/_examples/digitalidentity/error.go b/_examples/digitalidentity/error.go
new file mode 100644
index 000000000..71739df2d
--- /dev/null
+++ b/_examples/digitalidentity/error.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "html/template"
+ "log"
+ "net/http"
+)
+
+func errorPage(w http.ResponseWriter, r *http.Request) {
+ templateVars := map[string]interface{}{
+ "yotiError": r.Context().Value(contextKey("yotiError")).(string),
+ }
+ log.Printf("%s", templateVars["yotiError"])
+ t, err := template.ParseFiles("error.html")
+ if err != nil {
+ panic(errParsingTheTemplate + err.Error())
+ }
+
+ err = t.Execute(w, templateVars)
+ if err != nil {
+ panic(errApplyingTheParsedTemplate + err.Error())
+ }
+
+}
diff --git a/_examples/digitalidentity/error.html b/_examples/digitalidentity/error.html
new file mode 100644
index 000000000..73d7e730b
--- /dev/null
+++ b/_examples/digitalidentity/error.html
@@ -0,0 +1,11 @@
+
+
+
+
+ Yoti Example Project - Error
+
+
+An Error Occurred
+Error: {{.yotiError}}
+
+
\ No newline at end of file
diff --git a/_examples/digitalidentity/go.mod b/_examples/digitalidentity/go.mod
new file mode 100644
index 000000000..7425a0d47
--- /dev/null
+++ b/_examples/digitalidentity/go.mod
@@ -0,0 +1,12 @@
+module digitalidentity
+
+go 1.19
+
+require (
+ github.com/getyoti/yoti-go-sdk/v3 v3.0.0
+ github.com/joho/godotenv v1.3.0
+)
+
+require google.golang.org/protobuf v1.30.0 // indirect
+
+replace github.com/getyoti/yoti-go-sdk/v3 => ../../
diff --git a/_examples/digitalidentity/go.sum b/_examples/digitalidentity/go.sum
new file mode 100644
index 000000000..25b7d7dcf
--- /dev/null
+++ b/_examples/digitalidentity/go.sum
@@ -0,0 +1,11 @@
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+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.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
diff --git a/_examples/digitalidentity/login.html b/_examples/digitalidentity/login.html
new file mode 100644
index 000000000..b3d2729dc
--- /dev/null
+++ b/_examples/digitalidentity/login.html
@@ -0,0 +1,85 @@
+
+
+
+
+
+ Yoti client example
+
+
+
+
+
+
+
+
+
+
+ Digital Identity Share Example page
+
+ SdkId: {{.yotiClientSdkID}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/_examples/digitalidentity/main.go b/_examples/digitalidentity/main.go
new file mode 100644
index 000000000..b1cc553e7
--- /dev/null
+++ b/_examples/digitalidentity/main.go
@@ -0,0 +1,167 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "log"
+ "net/http"
+ "os"
+ "path"
+
+ "github.com/getyoti/yoti-go-sdk/v3"
+ "github.com/getyoti/yoti-go-sdk/v3/digitalidentity"
+ _ "github.com/joho/godotenv/autoload"
+)
+
+type contextKey string
+
+var (
+ errApplyingTheParsedTemplate = "Error applying the parsed template: "
+ errParsingTheTemplate = "Error parsing the template: "
+)
+
+func home(w http.ResponseWriter, req *http.Request) {
+ templateVars := map[string]interface{}{
+ "yotiScenarioID": os.Getenv("YOTI_SCENARIO_ID"),
+ "yotiClientSdkID": os.Getenv("YOTI_CLIENT_SDK_ID")}
+ t, err := template.ParseFiles("login.html")
+
+ if err != nil {
+ errorPage(w, req.WithContext(context.WithValue(
+ req.Context(),
+ contextKey("yotiError"),
+ fmt.Sprintf(errParsingTheTemplate+err.Error()),
+ )))
+ return
+ }
+
+ err = t.Execute(w, templateVars)
+ if err != nil {
+ errorPage(w, req.WithContext(context.WithValue(
+ req.Context(),
+ contextKey("yotiError"),
+ fmt.Sprintf(errApplyingTheParsedTemplate+err.Error()),
+ )))
+ return
+ }
+}
+func buildDigitalIdentitySessionReq() (sessionSpec *digitalidentity.ShareSessionRequest, err error) {
+ policy, err := (&digitalidentity.PolicyBuilder{}).WithFullName().WithEmail().WithPhoneNumber().WithSelfie().WithAgeOver(18).WithNationality().WithGender().WithDocumentDetails().WithDocumentImages().WithWantedRememberMe().Build()
+ if err != nil {
+ return nil, fmt.Errorf("failed to build policy: %v", err)
+ }
+
+ subject := []byte(`{
+ "subject_id": "unique-user-id-for-examples"
+ }`)
+
+ sessionReq, err := (&digitalidentity.ShareSessionRequestBuilder{}).WithPolicy(policy).WithRedirectUri("https:/www.yoti.com").WithSubject(subject).Build()
+ if err != nil {
+ return nil, fmt.Errorf("failed to build create session request: %v", err)
+ }
+ return &sessionReq, nil
+}
+
+func generateSession(w http.ResponseWriter, r *http.Request) {
+ didClient, err := initialiseDigitalIdentityClient()
+ if err != nil {
+ fmt.Fprintf(w, string("Client could't be generated"))
+ return
+ }
+
+ sessionReq, err := buildDigitalIdentitySessionReq()
+ if err != nil {
+ fmt.Fprintf(w, "failed to build session request: %v", err)
+ return
+ }
+
+ shareSession, err := didClient.CreateShareSession(sessionReq)
+ if err != nil {
+ fmt.Fprintf(w, "failed to create share session: %v", err)
+ return
+ }
+
+ output, err := json.Marshal(shareSession)
+ if err != nil {
+ fmt.Fprintf(w, "failed to marshall share session: %v", err)
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, string(output))
+
+}
+
+func getReceipt(w http.ResponseWriter, r *http.Request) {
+ didClient, err := initialiseDigitalIdentityClient()
+ if err != nil {
+ fmt.Fprintf(w, "Client could't be generated")
+ return
+ }
+ receiptID := r.URL.Query().Get("ReceiptID")
+
+ receiptValue, err := didClient.GetShareReceipt(receiptID)
+ if err != nil {
+ fmt.Fprintf(w, "failed to get share receipt: %v", err)
+ return
+ }
+ output, err := json.Marshal(receiptValue)
+ if err != nil {
+ fmt.Fprintf(w, "failed to marshal receipt: %v", err)
+ return
+ }
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprintf(w, string(output))
+}
+
+func initialiseDigitalIdentityClient() (*yoti.DigitalIdentityClient, error) {
+ var err error
+ sdkID := os.Getenv("YOTI_CLIENT_SDK_ID")
+ keyFilePath := os.Getenv("YOTI_KEY_FILE_PATH")
+ key, err := os.ReadFile(keyFilePath)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get key from YOTI_KEY_FILE_PATH :: %w", err)
+ }
+
+ didClient, err := yoti.NewDigitalIdentityClient(sdkID, key)
+ if err != nil {
+ return nil, fmt.Errorf("failed to initialise Share client :: %w", err)
+ }
+
+ return didClient, nil
+}
+func main() {
+ // Check if the cert files are available.
+ selfSignedCertName := "yotiSelfSignedCert.pem"
+ selfSignedKeyName := "yotiSelfSignedKey.pem"
+ certificatePresent := certificatePresenceCheck(selfSignedCertName, selfSignedKeyName)
+ portNumber := "8080"
+ // If they are not available, generate new ones.
+ if !certificatePresent {
+ err := generateSelfSignedCertificate(selfSignedCertName, selfSignedKeyName, "127.0.0.1:"+portNumber)
+ if err != nil {
+ panic("Error when creating https certs: " + err.Error())
+ }
+ }
+
+ http.HandleFunc("/", home)
+ http.HandleFunc("/v2/generate-share", generateSession)
+ http.HandleFunc("/v2/receipt-info", getReceipt)
+
+ rootdir, err := os.Getwd()
+ if err != nil {
+ log.Fatal("Error: Couldn't get current working directory")
+ }
+ http.Handle("/images/", http.StripPrefix("/images",
+ http.FileServer(http.Dir(path.Join(rootdir, "images/")))))
+ http.Handle("/static/", http.StripPrefix("/static",
+ http.FileServer(http.Dir(path.Join(rootdir, "static/")))))
+
+ log.Printf("About to listen and serve on %[1]s. Go to https://localhost:%[1]s/", portNumber)
+ err = http.ListenAndServeTLS(":"+portNumber, selfSignedCertName, selfSignedKeyName, nil)
+
+ if err != nil {
+ panic("Error when calling `ListenAndServeTLS`: " + err.Error())
+ }
+}
diff --git a/_examples/digitalidentity/static/assets/app-store-badge.png b/_examples/digitalidentity/static/assets/app-store-badge.png
new file mode 100755
index 000000000..3ec996cc6
Binary files /dev/null and b/_examples/digitalidentity/static/assets/app-store-badge.png differ
diff --git a/_examples/digitalidentity/static/assets/app-store-badge@2x.png b/_examples/digitalidentity/static/assets/app-store-badge@2x.png
new file mode 100755
index 000000000..84b34068f
Binary files /dev/null and b/_examples/digitalidentity/static/assets/app-store-badge@2x.png differ
diff --git a/_examples/digitalidentity/static/assets/company-logo.jpg b/_examples/digitalidentity/static/assets/company-logo.jpg
new file mode 100644
index 000000000..551474bfe
Binary files /dev/null and b/_examples/digitalidentity/static/assets/company-logo.jpg differ
diff --git a/_examples/digitalidentity/static/assets/google-play-badge.png b/_examples/digitalidentity/static/assets/google-play-badge.png
new file mode 100755
index 000000000..761f237b1
Binary files /dev/null and b/_examples/digitalidentity/static/assets/google-play-badge.png differ
diff --git a/_examples/digitalidentity/static/assets/google-play-badge@2x.png b/_examples/digitalidentity/static/assets/google-play-badge@2x.png
new file mode 100755
index 000000000..46707cea8
Binary files /dev/null and b/_examples/digitalidentity/static/assets/google-play-badge@2x.png differ
diff --git a/_examples/digitalidentity/static/assets/icons/address.svg b/_examples/digitalidentity/static/assets/icons/address.svg
new file mode 100755
index 000000000..533152b76
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/address.svg
@@ -0,0 +1,4 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/calendar.svg b/_examples/digitalidentity/static/assets/icons/calendar.svg
new file mode 100755
index 000000000..71ce63714
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/calendar.svg
@@ -0,0 +1,6 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/chevron-down-grey.svg b/_examples/digitalidentity/static/assets/icons/chevron-down-grey.svg
new file mode 100644
index 000000000..89f55a6fb
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/chevron-down-grey.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/_examples/digitalidentity/static/assets/icons/document.svg b/_examples/digitalidentity/static/assets/icons/document.svg
new file mode 100755
index 000000000..10fc1de31
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/document.svg
@@ -0,0 +1,4 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/email.svg b/_examples/digitalidentity/static/assets/icons/email.svg
new file mode 100755
index 000000000..67880ef32
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/email.svg
@@ -0,0 +1,17 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/gender.svg b/_examples/digitalidentity/static/assets/icons/gender.svg
new file mode 100755
index 000000000..94a0ed909
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/gender.svg
@@ -0,0 +1,6 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/nationality.svg b/_examples/digitalidentity/static/assets/icons/nationality.svg
new file mode 100755
index 000000000..40cbf76d0
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/nationality.svg
@@ -0,0 +1,4 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/phone.svg b/_examples/digitalidentity/static/assets/icons/phone.svg
new file mode 100755
index 000000000..adbaad999
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/phone.svg
@@ -0,0 +1,4 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/profile.svg b/_examples/digitalidentity/static/assets/icons/profile.svg
new file mode 100755
index 000000000..62278ecee
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/profile.svg
@@ -0,0 +1,4 @@
+
diff --git a/_examples/digitalidentity/static/assets/icons/verified.svg b/_examples/digitalidentity/static/assets/icons/verified.svg
new file mode 100755
index 000000000..f6e1d94c8
--- /dev/null
+++ b/_examples/digitalidentity/static/assets/icons/verified.svg
@@ -0,0 +1,7 @@
+
diff --git a/_examples/digitalidentity/static/assets/logo.png b/_examples/digitalidentity/static/assets/logo.png
new file mode 100755
index 000000000..c60227fab
Binary files /dev/null and b/_examples/digitalidentity/static/assets/logo.png differ
diff --git a/_examples/digitalidentity/static/assets/logo@2x.png b/_examples/digitalidentity/static/assets/logo@2x.png
new file mode 100755
index 000000000..9f29784d1
Binary files /dev/null and b/_examples/digitalidentity/static/assets/logo@2x.png differ
diff --git a/_examples/digitalidentity/static/index.css b/_examples/digitalidentity/static/index.css
new file mode 100644
index 000000000..14a2bc8ca
--- /dev/null
+++ b/_examples/digitalidentity/static/index.css
@@ -0,0 +1,173 @@
+.yoti-body {
+ margin: 0;
+}
+
+.yoti-top-section {
+ display: flex;
+ flex-direction: column;
+
+ padding: 38px 0;
+
+ background-color: #f7f8f9;
+
+ align-items: center;
+}
+
+.yoti-logo-section {
+ margin-bottom: 25px;
+}
+
+.yoti-logo-image {
+ display: block;
+}
+
+.yoti-top-header {
+ font-family: Roboto, sans-serif;
+ font-size: 40px;
+ font-weight: 700;
+ line-height: 1.2;
+ margin-top: 0;
+ margin-bottom: 80px;
+ text-align: center;
+
+ color: #000;
+}
+
+@media (min-width: 600px) {
+ .yoti-top-header {
+ line-height: 1.4;
+ }
+}
+
+.yoti-sdk-integration-section {
+ margin: 30px 0;
+}
+
+#yoti-share-button {
+ width: 250px;
+ height: 45px;
+}
+
+.yoti-login-or-separator {
+ text-transform: uppercase;
+ font-family: Roboto;
+ font-size: 16px;
+ font-weight: bold;
+ line-height: 1.5;
+ text-align: center;
+ margin-top: 30px;
+}
+
+.yoti-login-dialog {
+ display: grid;
+
+ box-sizing: border-box;
+ width: 100%;
+ padding: 35px 38px;
+
+ border-radius: 5px;
+ background: #fff;
+
+ grid-gap: 25px;
+}
+
+@media (min-width: 600px) {
+ .yoti-login-dialog {
+ width: 560px;
+ padding: 35px 88px;
+ }
+}
+
+.yoti-login-dialog-header {
+ font-family: Roboto, sans-serif;
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1.1;
+
+ margin: 0;
+
+ color: #000;
+}
+
+.yoti-input {
+ font-family: Roboto, sans-serif;
+ font-size: 16px;
+ line-height: 1.5;
+
+ box-sizing: border-box;
+ padding: 12px 15px;
+
+ color: #000;
+ border: solid 2px #000;
+ border-radius: 4px;
+ background-color: #fff;
+}
+
+.yoti-login-actions {
+ display: flex;
+
+ justify-content: space-between;
+ align-items: center;
+}
+
+.yoti-login-forgot-button {
+ font-family: Roboto, sans-serif;
+ font-size: 16px;
+
+ text-transform: capitalize;
+}
+
+.yoti-login-button {
+ font-family: Roboto, sans-serif;
+ font-size: 16px;
+
+ box-sizing: border-box;
+ width: 145px;
+ height: 50px;
+
+ text-transform: uppercase;
+
+ color: #fff;
+ border: 0;
+ background-color: #000;
+}
+
+.yoti-sponsor-app-section {
+ display: flex;
+ flex-direction: column;
+
+ padding: 70px 0;
+
+ align-items: center;
+}
+
+.yoti-sponsor-app-header {
+ font-family: Roboto, sans-serif;
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.2;
+
+ margin: 0;
+
+ text-align: center;
+
+ color: #000;
+}
+
+.yoti-store-buttons-section {
+ margin-top: 40px;
+ display: grid;
+ grid-gap: 10px;
+ grid-template-columns: 1fr;
+}
+
+@media (min-width: 600px) {
+ .yoti-store-buttons-section {
+ grid-template-columns: 1fr 1fr;
+ grid-gap: 25px;
+ }
+}
+
+.yoti-app-button-link {
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/_examples/digitalidentity/static/profile.css b/_examples/digitalidentity/static/profile.css
new file mode 100644
index 000000000..ff5579cdb
--- /dev/null
+++ b/_examples/digitalidentity/static/profile.css
@@ -0,0 +1,431 @@
+.yoti-html {
+ height: 100%;
+}
+
+.yoti-body {
+ margin: 0;
+ height: 100%;
+}
+
+.yoti-icon-profile,
+.yoti-icon-phone,
+.yoti-icon-email,
+.yoti-icon-calendar,
+.yoti-icon-verified,
+.yoti-icon-address,
+.yoti-icon-gender,
+.yoti-icon-nationality {
+ display: inline-block;
+ height: 28px;
+ width: 28px;
+ flex-shrink: 0;
+}
+
+.yoti-icon-profile {
+ background: no-repeat url('/static/assets/icons/profile.svg');
+}
+
+.yoti-icon-phone {
+ background: no-repeat url('/static/assets/icons/phone.svg');
+}
+
+.yoti-icon-email {
+ background: no-repeat url('/static/assets/icons/email.svg');
+}
+
+.yoti-icon-calendar {
+ background: no-repeat url('/static/assets/icons/calendar.svg');
+}
+
+.yoti-icon-verified {
+ background: no-repeat url('/static/assets/icons/verified.svg');
+}
+
+.yoti-icon-address {
+ background: no-repeat url('/static/assets/icons/address.svg');
+}
+
+.yoti-icon-gender {
+ background: no-repeat url('/static/assets/icons/gender.svg');
+}
+
+.yoti-icon-nationality {
+ background: no-repeat url('/static/assets/icons/nationality.svg');
+}
+
+.yoti-profile-layout {
+ display: grid;
+ grid-template-columns: 1fr;
+}
+
+@media (min-width: 1100px) {
+ .yoti-profile-layout {
+ grid-template-columns: 360px 1fr;
+ height: 100%;
+ }
+}
+
+.yoti-profile-user-section {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-direction: column;
+ padding: 40px 0;
+ background-color: #f7f8f9;
+}
+
+@media (min-width: 1100px) {
+ .yoti-profile-user-section {
+ display: grid;
+ grid-template-rows: repeat(3, min-content);
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ }
+}
+
+.yoti-profile-picture-image {
+ width: 220px;
+ height: 220px;
+ border-radius: 50%;
+ margin-left: auto;
+ margin-right: auto;
+ display: block;
+}
+
+.yoti-profile-picture-powered,
+.yoti-profile-picture-account-creation {
+ font-family: Roboto;
+ font-size: 14px;
+ color: #b6bfcb;
+}
+
+.yoti-profile-picture-powered-section {
+ display: flex;
+ flex-direction: column;
+ text-align: center;
+ align-items: center;
+}
+
+@media (min-width: 1100px) {
+ .yoti-profile-picture-powered-section {
+ align-self: start;
+ }
+}
+
+.yoti-profile-picture-powered {
+ margin-bottom: 20px;
+}
+
+.yoti-profile-picture-section {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+@media (min-width: 1100px) {
+ .yoti-profile-picture-section {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 100%;
+ }
+}
+
+.yoti-logo-image {
+ margin-bottom: 25px;
+}
+
+.yoti-profile-picture-area {
+ position: relative;
+ display: inline-block;
+}
+
+.yoti-profile-picture-verified-icon {
+ display: block;
+ background: no-repeat url("/static/assets/icons/verified.svg");
+ background-size: cover;
+ height: 40px;
+ width: 40px;
+ position: absolute;
+ top: 10px;
+ right: 10px;
+}
+
+.yoti-profile-name {
+ margin-top: 20px;
+ font-family: Roboto, sans-serif;
+ font-size: 24px;
+ text-align: center;
+ color: #333b40;
+}
+
+.yoti-attributes-section {
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ align-items: center;
+
+ width: 100%;
+ padding: 40px 0;
+}
+
+.yoti-attributes-section.-condensed {
+ padding: 0;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attributes-section {
+ padding: 60px 0;
+ align-items: start;
+ overflow-y: scroll;
+ }
+
+ .yoti-attributes-section.-condensed {
+ padding: 0;
+ }
+}
+
+.yoti-company-logo {
+ margin-bottom: 40px;
+}
+
+@media (min-width: 1100px) {
+ .yoti-company-logo {
+ margin-left: 130px;
+ }
+}
+
+/* extended layout list */
+.yoti-attribute-list-header,
+.yoti-attribute-list-subheader {
+ display: none;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-list-header,
+ .yoti-attribute-list-subheader {
+ width: 100%;
+
+ display: grid;
+ grid-template-columns: 200px 1fr 1fr;
+ grid-template-rows: 40px;
+
+ align-items: center;
+ text-align: center;
+
+ font-family: Roboto;
+ font-size: 14px;
+ color: #b6bfcb;
+ }
+}
+
+.yoti-attribute-list-header-attribute,
+.yoti-attribute-list-header-value {
+ justify-self: start;
+ padding: 0 20px;
+}
+
+.yoti-attribute-list-subheader {
+ grid-template-rows: 30px;
+}
+
+.yoti-attribute-list-subhead-layout {
+ grid-column: 3;
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+}
+
+.yoti-attribute-list {
+ display: grid;
+ width: 100%;
+}
+
+.yoti-attribute-list-item:first-child {
+ border-top: 2px solid #f7f8f9;
+}
+
+.yoti-attribute-list-item {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: minmax(60px, auto);
+ border-bottom: 2px solid #f7f8f9;
+ border-right: none;
+ border-left: none;
+}
+
+.yoti-attribute-list-item.-condensed {
+ grid-template-columns: 50% 50%;
+ padding: 5px 35px;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-list-item {
+ display: grid;
+ grid-template-columns: 200px 1fr 1fr;
+ grid-template-rows: minmax(80px, auto);
+ }
+
+ .yoti-attribute-list-item.-condensed {
+ grid-template-columns: 200px 1fr;
+ padding: 0 75px;
+ }
+}
+
+.yoti-attribute-cell {
+ display: flex;
+ align-items: center;
+}
+
+.yoti-attribute-name {
+ grid-column: 1 / 2;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ border-right: 2px solid #f7f8f9;
+
+ padding: 20px;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-name {
+ justify-content: start;
+ }
+}
+
+.yoti-attribute-name.-condensed {
+ justify-content: start;
+}
+
+.yoti-attribute-name-cell {
+ display: flex;
+ align-items: center;
+}
+
+.yoti-attribute-name-cell-text {
+ font-family: Roboto, sans-serif;
+ font-size: 16px;
+ color: #b6bfcb;
+ margin-left: 12px;
+}
+
+.yoti-attribute-value {
+ grid-column: 2 / 3;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ padding: 20px;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-value {
+ justify-content: start;
+ }
+}
+
+.yoti-attribute-value.-condensed {
+ justify-content: start;
+}
+
+.yoti-attribute-value-text {
+ font-family: Roboto, sans-serif;
+ font-size: 18px;
+ color: #333b40;
+ word-break: break-word;
+}
+
+.yoti-attribute-value-text table {
+ font-size: 14px;
+ border-spacing: 0;
+}
+
+.yoti-attribute-value-text table td:first-child {
+ font-weight: bold;
+}
+
+.yoti-attribute-value-text table td {
+ border-bottom: 1px solid #f7f8f9;
+ padding: 5px;
+}
+
+.yoti-attribute-value-text img {
+ width: 100%;
+}
+
+.yoti-attribute-anchors-layout {
+ grid-column: 1 / 3;
+ grid-row: 2 / 2;
+
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ grid-auto-rows: minmax(40px, auto);
+ font-family: Roboto, sans-serif;
+ font-size: 14px;
+
+ background-color: #f7f8f9;
+ border: 5px solid white;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-anchors-layout {
+ grid-column: 3 / 4;
+ grid-row: 1 / 2;
+ }
+}
+
+.yoti-attribute-anchors-head {
+ border-bottom: 1px solid #dde2e5;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+@media (min-width: 1100px) {
+ .yoti-attribute-anchors-head {
+ display: none;
+ }
+}
+
+.yoti-attribute-anchors {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.yoti-attribute-anchors-head.-s-v {
+ grid-column-start: span 1 s-v;
+}
+
+.yoti-attribute-anchors-head.-value {
+ grid-column-start: span 1 value;
+}
+
+.yoti-attribute-anchors-head.-subtype {
+ grid-column-start: span 1 subtype;
+}
+
+.yoti-attribute-anchors.-s-v {
+ grid-column-start: span 1 s-v;
+}
+
+.yoti-attribute-anchors.-value {
+ grid-column-start: span 1 value;
+}
+
+.yoti-attribute-anchors.-subtype {
+ grid-column-start: span 1 subtype;
+}
+
+.yoti-edit-section {
+ padding: 50px 20px;
+}
+
+@media (min-width: 1100px) {
+ .yoti-edit-section {
+ padding: 75px 110px;
+ }
+}
diff --git a/_examples/docscansandbox/go.mod b/_examples/docscansandbox/go.mod
index 5ca0bd14c..4a0f7ccde 100644
--- a/_examples/docscansandbox/go.mod
+++ b/_examples/docscansandbox/go.mod
@@ -21,6 +21,7 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.6.1 // indirect
+ google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
diff --git a/_examples/docscansandbox/go.sum b/_examples/docscansandbox/go.sum
index e9da1058e..8385c5b09 100644
--- a/_examples/docscansandbox/go.sum
+++ b/_examples/docscansandbox/go.sum
@@ -35,11 +35,13 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
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/google/go-github/v27 v27.0.4/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -136,6 +138,8 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -151,7 +155,9 @@ google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dT
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
diff --git a/_examples/profile/dynamic-share.html b/_examples/profile/dynamic-share.html
index ca3dad90a..cf05ca393 100644
--- a/_examples/profile/dynamic-share.html
+++ b/_examples/profile/dynamic-share.html
@@ -70,7 +70,7 @@