mirror of
https://github.com/getnamingo/registry.git
synced 2025-05-20 19:39:20 +02:00
Added SubSub support for contact verification
This commit is contained in:
parent
f3d1fa22e6
commit
8def259c5f
5 changed files with 678 additions and 26 deletions
|
@ -3,6 +3,7 @@
|
|||
namespace App\Controllers;
|
||||
|
||||
use App\Models\Contact;
|
||||
use App\Lib\Mail;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
@ -1136,34 +1137,91 @@ class ContactsController extends Controller
|
|||
}
|
||||
|
||||
if ($contact) {
|
||||
try {
|
||||
$db->beginTransaction();
|
||||
$currentDateTime = new \DateTime();
|
||||
$stamp = $currentDateTime->format('Y-m-d H:i:s.v');
|
||||
$db->update(
|
||||
'contact',
|
||||
[
|
||||
'validation' => $data['verify'],
|
||||
'validation_stamp' => $stamp,
|
||||
'validation_log' => json_encode($data['v_log']),
|
||||
'upid' => $clid,
|
||||
'lastupdate' => $stamp
|
||||
if (!empty(envi('SUMSUB_TOKEN')) && !empty(envi('SUMSUB_KEY'))) {
|
||||
$level_name = 'idv-and-phone-verification';
|
||||
|
||||
// Build request body
|
||||
$bodyArray = [
|
||||
'levelName' => $level_name,
|
||||
'userId' => $identifier,
|
||||
'applicantIdentifiers' => [
|
||||
'email' => $contact['email'],
|
||||
'phone' => $contact['voice']
|
||||
],
|
||||
[
|
||||
'identifier' => $identifier
|
||||
'ttlInSecs' => 1800
|
||||
];
|
||||
|
||||
$body = json_encode($bodyArray);
|
||||
$path = '/resources/sdkIntegrations/levels/-/websdkLink';
|
||||
$ts = time();
|
||||
$signature = sign($ts, 'POST', $path, $body, envi('SUMSUB_KEY'));
|
||||
|
||||
// Guzzle client
|
||||
$client = new \GuzzleHttp\Client([
|
||||
'base_uri' => 'https://api.sumsub.com',
|
||||
'headers' => [
|
||||
'X-App-Token' => envi('SUMSUB_TOKEN'),
|
||||
'X-App-Access-Ts' => $ts,
|
||||
'X-App-Access-Sig' => $signature,
|
||||
'Content-Type' => 'application/json',
|
||||
]
|
||||
);
|
||||
$db->commit();
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
$this->container->get('flash')->addMessage('error', 'Database failure during update: ' . $e->getMessage());
|
||||
]);
|
||||
|
||||
// Send request
|
||||
try {
|
||||
$response = $client->post($path, ['body' => $body]);
|
||||
$data = json_decode($response->getBody(), true);
|
||||
$link = $data['url'];
|
||||
|
||||
$currentDateTime = new \DateTime();
|
||||
$stamp = $currentDateTime->format('Y-m-d H:i:s.v');
|
||||
$email = $db->selectValue('SELECT email FROM users WHERE id = ?', [$_SESSION['auth_user_id']]);
|
||||
$registry = $db->selectValue('SELECT value FROM settings WHERE name = ?', ['company_name']);
|
||||
$message = file_get_contents(__DIR__.'/../../resources/views/mail/validation.html');
|
||||
$placeholders = ['{registry}', '{link}', '{app_name}', '{app_url}', '{identifier}'];
|
||||
$replacements = [$registry, $link, envi('APP_NAME'), envi('APP_URL'), $contact['identifier']];
|
||||
$message = str_replace($placeholders, $replacements, $message);
|
||||
$mailsubject = '[' . envi('APP_NAME') . '] Contact Verification Required';
|
||||
$from = ['email'=>envi('MAIL_FROM_ADDRESS'), 'name'=>envi('MAIL_FROM_NAME')];
|
||||
$to = ['email'=>$contact['email'], 'name'=>''];
|
||||
// send message
|
||||
Mail::send($mailsubject, $message, $from, $to);
|
||||
|
||||
$this->container->get('flash')->addMessage('info', 'Contact validation process initiated with SumSub on ' . $stamp);
|
||||
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
|
||||
} catch (\GuzzleHttp\Exception\ClientException $e) {
|
||||
$this->container->get('flash')->addMessage('error', 'Contact validation error: ' . $e->getMessage());
|
||||
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$db->beginTransaction();
|
||||
$currentDateTime = new \DateTime();
|
||||
$stamp = $currentDateTime->format('Y-m-d H:i:s.v');
|
||||
$db->update(
|
||||
'contact',
|
||||
[
|
||||
'validation' => $data['verify'],
|
||||
'validation_stamp' => $stamp,
|
||||
'validation_log' => json_encode($data['v_log']),
|
||||
'upid' => $clid,
|
||||
'lastupdate' => $stamp
|
||||
],
|
||||
[
|
||||
'identifier' => $identifier
|
||||
]
|
||||
);
|
||||
$db->commit();
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
$this->container->get('flash')->addMessage('error', 'Database failure during update: ' . $e->getMessage());
|
||||
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
|
||||
}
|
||||
|
||||
unset($_SESSION['contacts_to_validate']);
|
||||
$this->container->get('flash')->addMessage('success', 'Contact ' . $identifier . ' has been validated successfully on ' . $stamp);
|
||||
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
|
||||
}
|
||||
|
||||
unset($_SESSION['contacts_to_validate']);
|
||||
$this->container->get('flash')->addMessage('success', 'Contact ' . $identifier . ' has been validated successfully on ' . $stamp);
|
||||
return $response->withHeader('Location', '/contact/update/'.$identifier)->withStatus(302);
|
||||
|
||||
} else {
|
||||
// Contact does not exist, redirect to the contacts view
|
||||
return $response->withHeader('Location', '/contacts')->withStatus(302);
|
||||
|
@ -1630,4 +1688,62 @@ class ContactsController extends Controller
|
|||
|
||||
}
|
||||
|
||||
public function webhookSumsub(Request $request, Response $response)
|
||||
{
|
||||
$body = $request->getBody()->getContents();
|
||||
$data = json_decode($body, true);
|
||||
$db = $this->container->get('db');
|
||||
|
||||
// Validate input
|
||||
if (!isset($data['externalUserId']) || !isset($data['type'])) {
|
||||
$response->getBody()->write('Missing required fields');
|
||||
return $response->withStatus(400);
|
||||
}
|
||||
|
||||
$identifier = $data['externalUserId'];
|
||||
$type = $data['type'];
|
||||
|
||||
// Only process applicantReviewed type
|
||||
if ($type === 'applicantReviewed') {
|
||||
$answer = $data['reviewResult']['reviewAnswer'] ?? null;
|
||||
switch ($answer) {
|
||||
case 'GREEN':
|
||||
$verify = '4'; // verified
|
||||
break;
|
||||
case 'RED':
|
||||
$verify = '0'; // failed
|
||||
break;
|
||||
default:
|
||||
// Ignore anything else
|
||||
$response->getBody()->write('Ignored (unhandled reviewAnswer)');
|
||||
return $response->withStatus(202);
|
||||
}
|
||||
$v_log = $data; // store full webhook for audit
|
||||
$clid = $data['applicantId'] ?? null;
|
||||
|
||||
$currentDateTime = new \DateTime();
|
||||
$stamp = $currentDateTime->format('Y-m-d H:i:s.v');
|
||||
|
||||
$db->update(
|
||||
'contact',
|
||||
[
|
||||
'validation' => $verify,
|
||||
'validation_stamp' => $stamp,
|
||||
'validation_log' => json_encode($v_log),
|
||||
//'upid' => $clid,
|
||||
'lastupdate' => $stamp
|
||||
],
|
||||
[
|
||||
'identifier' => $identifier
|
||||
]
|
||||
);
|
||||
|
||||
$response->getBody()->write('OK');
|
||||
return $response->withStatus(200);
|
||||
}
|
||||
|
||||
$response->getBody()->write('Ignored');
|
||||
return $response->withStatus(202);
|
||||
}
|
||||
|
||||
}
|
|
@ -1149,3 +1149,9 @@ function isValidHostname($hostname) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// HMAC Signature generator
|
||||
function sign($ts, $method, $path, $body, $secret_key) {
|
||||
$stringToSign = $ts . strtoupper($method) . $path . $body;
|
||||
return hash_hmac('sha256', $stringToSign, $secret_key);
|
||||
}
|
|
@ -44,4 +44,7 @@ NOW_API_KEY='now-api-key'
|
|||
|
||||
NICKY_API_KEY='nicky-api-key'
|
||||
|
||||
SUMSUB_TOKEN=
|
||||
SUMSUB_KEY=
|
||||
|
||||
TEST_TLDS=.test,.com.test
|
526
cp/resources/views/mail/validation.html
Normal file
526
cp/resources/views/mail/validation.html
Normal file
|
@ -0,0 +1,526 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="color-scheme: light dark; supported-color-schemes: light dark;">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta name="supported-color-schemes" content="light dark" />
|
||||
<title></title>
|
||||
<style type="text/css" rel="stylesheet" media="all">
|
||||
/* Base ------------------------------ */
|
||||
|
||||
@import url("https://fonts.googleapis.com/css?family=Nunito+Sans:400,700&display=swap");
|
||||
body {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3869D4;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
td {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.preheader {
|
||||
display: none !important;
|
||||
visibility: hidden;
|
||||
mso-hide: all;
|
||||
font-size: 1px;
|
||||
line-height: 1px;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* Type ------------------------------ */
|
||||
|
||||
body,
|
||||
td,
|
||||
th {
|
||||
font-family: "Nunito Sans", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote {
|
||||
margin: .4em 0 1.1875em;
|
||||
font-size: 16px;
|
||||
line-height: 1.625;
|
||||
}
|
||||
|
||||
p.sub {
|
||||
font-size: 13px;
|
||||
}
|
||||
/* Utilities ------------------------------ */
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-margin-bottom-none {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
/* Buttons ------------------------------ */
|
||||
|
||||
.button {
|
||||
background-color: #3869D4;
|
||||
border-top: 10px solid #3869D4;
|
||||
border-right: 18px solid #3869D4;
|
||||
border-bottom: 10px solid #3869D4;
|
||||
border-left: 18px solid #3869D4;
|
||||
display: inline-block;
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
|
||||
-webkit-text-size-adjust: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.button--green {
|
||||
background-color: #22BC66;
|
||||
border-top: 10px solid #22BC66;
|
||||
border-right: 18px solid #22BC66;
|
||||
border-bottom: 10px solid #22BC66;
|
||||
border-left: 18px solid #22BC66;
|
||||
}
|
||||
|
||||
.button--red {
|
||||
background-color: #FF6136;
|
||||
border-top: 10px solid #FF6136;
|
||||
border-right: 18px solid #FF6136;
|
||||
border-bottom: 10px solid #FF6136;
|
||||
border-left: 18px solid #FF6136;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.button {
|
||||
width: 100% !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
/* Attribute list ------------------------------ */
|
||||
|
||||
.attributes {
|
||||
margin: 0 0 21px;
|
||||
}
|
||||
|
||||
.attributes_content {
|
||||
background-color: #F4F4F7;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.attributes_item {
|
||||
padding: 0;
|
||||
}
|
||||
/* Related Items ------------------------------ */
|
||||
|
||||
.related {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 25px 0 0 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.related_item {
|
||||
padding: 10px 0;
|
||||
color: #CBCCCF;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.related_item-title {
|
||||
display: block;
|
||||
margin: .5em 0 0;
|
||||
}
|
||||
|
||||
.related_item-thumb {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.related_heading {
|
||||
border-top: 1px solid #CBCCCF;
|
||||
text-align: center;
|
||||
padding: 25px 0 10px;
|
||||
}
|
||||
/* Discount Code ------------------------------ */
|
||||
|
||||
.discount {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #F4F4F7;
|
||||
border: 2px dashed #CBCCCF;
|
||||
}
|
||||
|
||||
.discount_heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.discount_body {
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
}
|
||||
/* Social Icons ------------------------------ */
|
||||
|
||||
.social {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.social td {
|
||||
padding: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.social_icon {
|
||||
height: 20px;
|
||||
margin: 0 8px 10px 8px;
|
||||
padding: 0;
|
||||
}
|
||||
/* Data table ------------------------------ */
|
||||
|
||||
.purchase {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 35px 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.purchase_content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 25px 0 0 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.purchase_item {
|
||||
padding: 10px 0;
|
||||
color: #51545E;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.purchase_heading {
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.purchase_heading p {
|
||||
margin: 0;
|
||||
color: #85878E;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.purchase_footer {
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.purchase_total {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.purchase_total--label {
|
||||
padding: 0 15px 0 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F2F4F6;
|
||||
color: #51545E;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #51545E;
|
||||
}
|
||||
|
||||
.email-wrapper {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #F2F4F6;
|
||||
}
|
||||
|
||||
.email-content {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
/* Masthead ----------------------- */
|
||||
|
||||
.email-masthead {
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-masthead_logo {
|
||||
width: 94px;
|
||||
}
|
||||
|
||||
.email-masthead_name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #A8AAAF;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 white;
|
||||
}
|
||||
/* Body ------------------------------ */
|
||||
|
||||
.email-body {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
}
|
||||
|
||||
.email-body_inner {
|
||||
width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
-premailer-width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.email-footer {
|
||||
width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
-premailer-width: 570px;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-footer p {
|
||||
color: #A8AAAF;
|
||||
}
|
||||
|
||||
.body-action {
|
||||
width: 100%;
|
||||
margin: 30px auto;
|
||||
padding: 0;
|
||||
-premailer-width: 100%;
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.body-sub {
|
||||
margin-top: 25px;
|
||||
padding-top: 25px;
|
||||
border-top: 1px solid #EAEAEC;
|
||||
}
|
||||
|
||||
.content-cell {
|
||||
padding: 45px;
|
||||
}
|
||||
/*Media Queries ------------------------------ */
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.email-body_inner,
|
||||
.email-footer {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body,
|
||||
.email-body,
|
||||
.email-body_inner,
|
||||
.email-content,
|
||||
.email-wrapper,
|
||||
.email-masthead,
|
||||
.email-footer {
|
||||
background-color: #333333 !important;
|
||||
color: #FFF !important;
|
||||
}
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
span,
|
||||
.purchase_item {
|
||||
color: #FFF !important;
|
||||
}
|
||||
.attributes_content,
|
||||
.discount {
|
||||
background-color: #222 !important;
|
||||
}
|
||||
.email-masthead_name {
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
supported-color-schemes: light dark;
|
||||
}
|
||||
</style>
|
||||
<!--[if mso]>
|
||||
<style type="text/css">
|
||||
.f-fallback {
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<style type="text/css" rel="stylesheet" media="all">
|
||||
body {
|
||||
width: 100% !important;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Nunito Sans", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F2F4F6;
|
||||
color: #51545E;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="width: 100% !important; height: 100%; -webkit-text-size-adjust: none; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; background-color: #F2F4F6; color: #51545E; margin: 0;" bgcolor="#F2F4F6">
|
||||
<span class="preheader" style="display: none !important; visibility: hidden; mso-hide: all; font-size: 1px; line-height: 1px; max-height: 0; max-width: 0; opacity: 0; overflow: hidden;">We would like to inform you that the registry {registry} has initiated a contact verification process for your domain registration data.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation" style="width: 100%; -premailer-width: 100%; -premailer-cellpadding: 0; -premailer-cellspacing: 0; background-color: #F2F4F6; margin: 0; padding: 0;" bgcolor="#F2F4F6">
|
||||
<tr>
|
||||
<td align="center" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px;">
|
||||
<table class="email-content" width="100%" cellpadding="0" cellspacing="0" role="presentation" style="width: 100%; -premailer-width: 100%; -premailer-cellpadding: 0; -premailer-cellspacing: 0; margin: 0; padding: 0;">
|
||||
<tr>
|
||||
<td class="email-masthead" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px; text-align: center; padding: 25px 0;" align="center">
|
||||
<a href="{app_url}" class="f-fallback email-masthead_name" style="color: #A8AAAF; font-size: 16px; font-weight: bold; text-decoration: none; text-shadow: 0 1px 0 white;">
|
||||
{registry}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Email Body -->
|
||||
<tr>
|
||||
<td class="email-body" width="570" cellpadding="0" cellspacing="0" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px; width: 100%; -premailer-width: 100%; -premailer-cellpadding: 0; -premailer-cellspacing: 0; margin: 0; padding: 0;">
|
||||
<table class="email-body_inner" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation" style="width: 570px; -premailer-width: 570px; -premailer-cellpadding: 0; -premailer-cellspacing: 0; background-color: #FFFFFF; margin: 0 auto; padding: 0;" bgcolor="#FFFFFF">
|
||||
<!-- Body content -->
|
||||
<tr>
|
||||
<td class="content-cell" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px; padding: 45px;">
|
||||
<div class="f-fallback">
|
||||
<h1 style="margin-top: 0; color: #333333; font-size: 22px; font-weight: bold; text-align: left;" align="left">Contact Verification Required</h1>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">Dear Contact {identifier},</p>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">We would like to inform you that the registry {registry} has initiated a <strong>contact verification process</strong> for your domain registration data.</p>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">To <strong>ensure compliance</strong> with our domain policies, please complete the verification by following the link below:</p>
|
||||
<!-- Action -->
|
||||
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation" style="width: 100%; -premailer-width: 100%; -premailer-cellpadding: 0; -premailer-cellspacing: 0; text-align: center; margin: 30px auto; padding: 0;">
|
||||
<tr>
|
||||
<td align="center" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px;">
|
||||
<!-- Border based button
|
||||
https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px;">
|
||||
<a href="{link}" class="f-fallback button" target="_blank" style="color: #FFF; background-color: #3869D4; display: inline-block; text-decoration: none; border-radius: 3px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); -webkit-text-size-adjust: none; box-sizing: border-box; border-color: #3869D4; border-style: solid; border-width: 10px 18px;">Start Validation</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">This verification is <strong>required</strong> to confirm the accuracy of your contact details associated with one or more domain names.</p>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">If the verification is not completed within <strong>15 days</strong>, it may result in temporary suspension or limitations on your domain services. We kindly urge you to complete the verification as soon as possible to avoid any disruptions.</p>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">Thank you for choosing {registry} for your needs. We are here to help!</p>
|
||||
<p style="font-size: 16px; line-height: 1.625; color: #51545E; margin: .4em 0 1.1875em;">Kind regards,
|
||||
<br /><strong>{registry} Support Team</strong></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px;">
|
||||
<table class="email-footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation" style="width: 570px; -premailer-width: 570px; -premailer-cellpadding: 0; -premailer-cellspacing: 0; text-align: center; margin: 0 auto; padding: 0;">
|
||||
<tr>
|
||||
<td class="content-cell" align="center" style="word-break: break-word; font-family: "Nunito Sans", Helvetica, Arial, sans-serif; font-size: 16px; padding: 45px;">
|
||||
<p class="f-fallback sub align-center" style="font-size: 13px; line-height: 1.625; text-align: center; color: #A8AAAF; margin: .4em 0 1.1875em;" align="center">
|
||||
Powered by <a href="{app_url}" target="_blank">{app_name}</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -38,6 +38,7 @@ $app->group('', function ($route) {
|
|||
$route->get('/update-password', PasswordController::class.':createUpdatePassword')->setName('update.password');
|
||||
$route->post('/update-password', PasswordController::class.':updatePassword');
|
||||
$route->post('/webhook/adyen', FinancialsController::class .':webhookAdyen')->setName('webhookAdyen');
|
||||
$route->post('/webhook/sumsub', ContactsController::class .':webhookSumsub')->setName('webhookSumsub');
|
||||
})->add(new GuestMiddleware($container));
|
||||
|
||||
$app->group('', function ($route) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue