Changeset 3320256
- Timestamp:
- 06/30/2025 09:58:58 PM (8 months ago)
- Location:
- trust-swiftly-verification
- Files:
-
- 279 added
- 9 edited
-
tags/1.1.14 (added)
-
tags/1.1.14/.gitignore (added)
-
tags/1.1.14/LICENSE (added)
-
tags/1.1.14/README.md (added)
-
tags/1.1.14/assets (added)
-
tags/1.1.14/assets/banner-772x250.png (added)
-
tags/1.1.14/assets/css (added)
-
tags/1.1.14/assets/css/admin.css (added)
-
tags/1.1.14/assets/css/app.css (added)
-
tags/1.1.14/assets/css/select2.min.css (added)
-
tags/1.1.14/assets/icon-128x128.png (added)
-
tags/1.1.14/assets/img (added)
-
tags/1.1.14/assets/img/pill-grey-ts.svg (added)
-
tags/1.1.14/assets/img/pill-outlined-ts.svg (added)
-
tags/1.1.14/assets/img/pill-solid-color-ts.svg (added)
-
tags/1.1.14/assets/img/rectangle-grey-ts.svg (added)
-
tags/1.1.14/assets/img/rectangle-outlined-ts.svg (added)
-
tags/1.1.14/assets/img/rectangle-solid-color-ts.svg (added)
-
tags/1.1.14/assets/js (added)
-
tags/1.1.14/assets/js/admin.js (added)
-
tags/1.1.14/assets/js/checkout-block.js (added)
-
tags/1.1.14/assets/js/checkout-helper.js (added)
-
tags/1.1.14/assets/js/checkout.js (added)
-
tags/1.1.14/assets/js/select2.min.js (added)
-
tags/1.1.14/bootstrap.php (added)
-
tags/1.1.14/composer.json (added)
-
tags/1.1.14/composer.lock (added)
-
tags/1.1.14/config (added)
-
tags/1.1.14/config/config.php (added)
-
tags/1.1.14/config/constants.php (added)
-
tags/1.1.14/core (added)
-
tags/1.1.14/core/Autoloader.php (added)
-
tags/1.1.14/lib (added)
-
tags/1.1.14/lib/TrustSwiftly (added)
-
tags/1.1.14/lib/TrustSwiftly/Api (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Client.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Statistics (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Statistics/StatisticsApiClient.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Templates (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Templates/TemplateApiClient.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Users (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Users/UserApiClient.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Validation (added)
-
tags/1.1.14/lib/TrustSwiftly/Api/Validation/CredentialValidationClient.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Enums (added)
-
tags/1.1.14/lib/TrustSwiftly/Enums/HttpStatusCodes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions/ApiException.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions/ConfigException.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions/HttpException.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions/RequestTimeOut.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Exceptions/RequiredParameterMissing.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/BaseResponseManager.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/BaseRouteManager.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/ConfigManager.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Interfaces (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Interfaces/StatisticsRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Interfaces/TemplateRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Interfaces/UserRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Interfaces/ValidationRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Routes (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Routes/StatisticApiRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Routes/TemplateApiRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Routes/UserApiRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Managers/Routes/ValidationApiRoutes.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Resources (added)
-
tags/1.1.14/lib/TrustSwiftly/Resources/User.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Responses (added)
-
tags/1.1.14/lib/TrustSwiftly/Responses/UserCreateResponse.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Responses/UserDetailResponse.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Responses/UserMagicLinkResponse.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Security (added)
-
tags/1.1.14/lib/TrustSwiftly/Security/EmbedSignature.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Security/ValidationSignature.php (added)
-
tags/1.1.14/lib/TrustSwiftly/Security/WebhookSignature.php (added)
-
tags/1.1.14/lib/TrustSwiftly/TrustSwiftly.php (added)
-
tags/1.1.14/readme.txt (added)
-
tags/1.1.14/src (added)
-
tags/1.1.14/src/Api (added)
-
tags/1.1.14/src/Api/Ipn.php (added)
-
tags/1.1.14/src/Settings (added)
-
tags/1.1.14/src/Settings/Settings.php (added)
-
tags/1.1.14/src/TrustVerifyPlugin.php (added)
-
tags/1.1.14/src/WooCommerce (added)
-
tags/1.1.14/src/WooCommerce/ReturnHandler.php (added)
-
tags/1.1.14/src/WooCommerce/Verification.php (added)
-
tags/1.1.14/src/helpers (added)
-
tags/1.1.14/src/helpers/functions.php (added)
-
tags/1.1.14/trustswiftly-verification.php (added)
-
tags/1.1.14/vendor (added)
-
tags/1.1.14/vendor/autoload.php (added)
-
tags/1.1.14/vendor/composer (added)
-
tags/1.1.14/vendor/composer/ClassLoader.php (added)
-
tags/1.1.14/vendor/composer/LICENSE (added)
-
tags/1.1.14/vendor/composer/autoload_classmap.php (added)
-
tags/1.1.14/vendor/composer/autoload_files.php (added)
-
tags/1.1.14/vendor/composer/autoload_namespaces.php (added)
-
tags/1.1.14/vendor/composer/autoload_psr4.php (added)
-
tags/1.1.14/vendor/composer/autoload_real.php (added)
-
tags/1.1.14/vendor/composer/autoload_static.php (added)
-
tags/1.1.14/vendor/composer/installed.json (added)
-
tags/1.1.14/vendor/guzzlehttp (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/CHANGELOG.md (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/LICENSE (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/README.md (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/UPGRADING.md (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/composer.json (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/BodySummarizer.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/BodySummarizerInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Client.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/ClientInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/ClientTrait.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/HeaderProcessor.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/HandlerStack.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/MessageFormatter.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/MessageFormatterInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Middleware.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Pool.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/RequestOptions.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/TransferStats.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/Utils.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/functions.php (added)
-
tags/1.1.14/vendor/guzzlehttp/guzzle/src/functions_include.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/CHANGELOG.md (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/LICENSE (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/Makefile (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/README.md (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/composer.json (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/AggregateException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/CancellationException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Coroutine.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Create.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Each.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/EachPromise.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/FulfilledPromise.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Is.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Promise.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/PromiseInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/PromisorInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/RejectedPromise.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/RejectionException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/TaskQueue.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/TaskQueueInterface.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/Utils.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/functions.php (added)
-
tags/1.1.14/vendor/guzzlehttp/promises/src/functions_include.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7 (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/CHANGELOG.md (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/LICENSE (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/README.md (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/composer.json (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/AppendStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/BufferStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/CachingStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/DroppingStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Exception (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Exception/MalformedUriException.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/FnStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Header.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/HttpFactory.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/InflateStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/LazyOpenStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/LimitStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Message.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/MessageTrait.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/MimeType.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/MultipartStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/NoSeekStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/PumpStream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Query.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Request.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Response.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Rfc7230.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/ServerRequest.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Stream.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/StreamWrapper.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/UploadedFile.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Uri.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/UriNormalizer.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/UriResolver.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/src/Utils.php (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/php-cs-fixer (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/php-cs-fixer/composer.json (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/phpstan (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/phpstan/composer.json (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/psalm (added)
-
tags/1.1.14/vendor/guzzlehttp/psr7/vendor-bin/psalm/composer.json (added)
-
tags/1.1.14/vendor/psr (added)
-
tags/1.1.14/vendor/psr/http-client (added)
-
tags/1.1.14/vendor/psr/http-client/CHANGELOG.md (added)
-
tags/1.1.14/vendor/psr/http-client/LICENSE (added)
-
tags/1.1.14/vendor/psr/http-client/README.md (added)
-
tags/1.1.14/vendor/psr/http-client/composer.json (added)
-
tags/1.1.14/vendor/psr/http-client/src (added)
-
tags/1.1.14/vendor/psr/http-client/src/ClientExceptionInterface.php (added)
-
tags/1.1.14/vendor/psr/http-client/src/ClientInterface.php (added)
-
tags/1.1.14/vendor/psr/http-client/src/NetworkExceptionInterface.php (added)
-
tags/1.1.14/vendor/psr/http-client/src/RequestExceptionInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory (added)
-
tags/1.1.14/vendor/psr/http-factory/.gitignore (added)
-
tags/1.1.14/vendor/psr/http-factory/.pullapprove.yml (added)
-
tags/1.1.14/vendor/psr/http-factory/LICENSE (added)
-
tags/1.1.14/vendor/psr/http-factory/README.md (added)
-
tags/1.1.14/vendor/psr/http-factory/composer.json (added)
-
tags/1.1.14/vendor/psr/http-factory/src (added)
-
tags/1.1.14/vendor/psr/http-factory/src/RequestFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory/src/ResponseFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory/src/StreamFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-factory/src/UriFactoryInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message (added)
-
tags/1.1.14/vendor/psr/http-message/CHANGELOG.md (added)
-
tags/1.1.14/vendor/psr/http-message/LICENSE (added)
-
tags/1.1.14/vendor/psr/http-message/README.md (added)
-
tags/1.1.14/vendor/psr/http-message/composer.json (added)
-
tags/1.1.14/vendor/psr/http-message/src (added)
-
tags/1.1.14/vendor/psr/http-message/src/MessageInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/RequestInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/ResponseInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/ServerRequestInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/StreamInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/UploadedFileInterface.php (added)
-
tags/1.1.14/vendor/psr/http-message/src/UriInterface.php (added)
-
tags/1.1.14/vendor/ralouphie (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders/LICENSE (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders/README.md (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders/composer.json (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders/src (added)
-
tags/1.1.14/vendor/ralouphie/getallheaders/src/getallheaders.php (added)
-
tags/1.1.14/vendor/symfony (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/.gitignore (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/CHANGELOG.md (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/LICENSE (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/README.md (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/composer.json (added)
-
tags/1.1.14/vendor/symfony/deprecation-contracts/function.php (added)
-
tags/1.1.14/views (added)
-
tags/1.1.14/views/admin-settings-page.php (added)
-
tags/1.1.14/views/post-order-verification.php (added)
-
trunk/.gitignore (modified) (1 diff)
-
trunk/assets/css/app.css (modified) (1 diff)
-
trunk/assets/js/checkout-block.js (added)
-
trunk/assets/js/checkout.js (modified) (1 diff)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/src/Settings/Settings.php (modified) (4 diffs)
-
trunk/src/TrustVerifyPlugin.php (modified) (7 diffs)
-
trunk/src/WooCommerce/Verification.php (modified) (14 diffs)
-
trunk/trustswiftly-verification.php (modified) (2 diffs)
-
trunk/views/post-order-verification.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trust-swiftly-verification/trunk/.gitignore
r2960921 r3320256 1 1 /vendor/ 2 .DS_Store -
trust-swiftly-verification/trunk/assets/css/app.css
r3108811 r3320256 21 21 display: block; 22 22 } 23 /* Defines the new, larger size for the verification button */ 24 .ts-verify-link { 25 height: 54px; 26 width: 240px; 27 28 /* Adds a smooth transition for the hover effect */ 29 transition: transform 0.2s ease-in-out; 30 } 31 32 /* Optional but recommended: A subtle grow effect on hover */ 33 .ts-verify-link:hover { 34 transform: scale(1.03); 35 } 36 37 /* The main call-out box for the verification step (base styles) */ 38 .ts-verification-callout { 39 border: 2px solid #0073e6; 40 background-color: #f8f9fa; 41 border-radius: 8px; 42 padding: 20px; 43 margin-top: 20px !important; 44 text-align: center; 45 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); 46 /* Transition for color changes and content fades */ 47 transition: background-color 0.4s ease, border-color 0.4s ease; 48 } 49 50 /* The class that specifically triggers the pulse animation */ 51 .ts-verification-callout.ts-pulse-animation { 52 animation: ts-pulse-border 2.5s infinite; 53 } 54 55 /* --- NEW: Success State Transformation --- */ 56 /* When verification is successful, the box transforms to a green confirmation state */ 57 .ts-verification-callout.ts-verification-success { 58 border-color: #28a745; /* Green border */ 59 background-color: #f0f9f2; /* Lighter green background */ 60 } 61 62 /* The main instructional/status text */ 63 .ts-verification-callout .ts-verification-message { 64 font-size: 16px; 65 font-weight: 600; 66 color: #3c434a; 67 margin: 0; 68 line-height: 1.5; 69 /* Transition for smooth fading */ 70 transition: opacity 0.3s ease; 71 } 72 73 /* The success message gets a distinct color */ 74 .ts-verification-callout.ts-verification-success .ts-verification-message { 75 color: #155724; /* Dark green text for readability */ 76 } 77 78 /* Wrapper for the button and spinner for easy layout */ 79 .ts-verification-callout .ts-verification-button-wrapper, 80 .ts-verification-callout .ts-verification-spinner { 81 min-height: 45px; /* Ensures layout doesn't jump */ 82 display: flex; 83 justify-content: center; 84 align-items: center; 85 } 86 87 /* Animation keyframes for the pulsing border */ 88 @keyframes ts-pulse-border { 89 0% { 90 box-shadow: 0 0 0 0 rgba(0, 115, 230, 0.5); 91 } 92 70% { 93 box-shadow: 0 0 0 10px rgba(0, 115, 230, 0); 94 } 95 100% { 96 box-shadow: 0 0 0 0 rgba(0, 115, 230, 0); 97 } 98 } -
trust-swiftly-verification/trunk/assets/js/checkout.js
r3131714 r3320256 1 function isEmailValid(email) { 2 var pattern = new RegExp( 3 /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i 4 ); 5 // eslint-disable-line max-len 6 7 return pattern.test(email); 8 } 1 /** 2 * Trust Swiftly Checkout Verification Script 3 * 4 * Final Version for Modern WooCommerce Blocks: 5 * - Uses the official `onCheckoutValidation` hook for Block Checkout. 6 * - Classic Checkout is handled by server-side PHP hooks. 7 * - Asynchronously updates a client-side verification status variable. 8 * - Synchronously validates against that status when the user places the order. 9 */ 9 10 (function ($) { 10 // Custom code here 11 12 $(function () { 13 window.TSVerification = { 14 config: { 15 userEmail: TSCheckoutConfig.user_email, 16 ajaxUrl: TSCheckoutConfig.ajax_url, 17 nonce: TSCheckoutConfig.nonce, 18 verifyLinkText: TSCheckoutConfig.verify_link_text, 19 thankyouPage: TSCheckoutConfig.thank_you_page, 20 }, 21 22 $billingEmail: null, 23 $submitBtn: null, 24 25 init: function () { 26 this.thankyouPage = TSCheckoutConfig.thank_you_page; 27 this.userEmail = TSCheckoutConfig.user_email; 28 29 if (this.thankyouPage !== "1") { 30 if (jQuery("#billing_email").length !== 0) { 31 this.$billingEmail = $("#billing_email"); 11 'use strict'; 12 13 function isEmailValid(email) { 14 var pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 15 return pattern.test(email); 16 } 17 18 var TSVerification = { 19 config: null, 20 $emailInput: null, 21 debounceTimer: null, 22 isInitialized: false, 23 isBlockCheckout: false, 24 // This state variable holds the current verification status. It is updated by the verifyUser() function. 25 isClientSideVerified: false, 26 27 /** 28 * Initializes the script, determines checkout type, and binds all necessary events. 29 */ 30 init: function ($emailElement) { 31 if (this.isInitialized) return; 32 this.isInitialized = true; 33 if (typeof TSCheckoutConfig === 'undefined') return console.error("Trust Swiftly: Config object not found."); 34 35 this.config = TSCheckoutConfig; 36 this.$emailInput = $emailElement; 37 this.isBlockCheckout = this.$emailInput.attr('id') === 'email'; 38 39 if (this.config.thank_you_page === "1") return; 40 41 this.setupVerificationUI(); 42 this.bindEvents(); 43 44 // For Block Checkout, subscribe to the official validation hook. 45 if (this.isBlockCheckout) { 46 this.initCheckoutValidationSubscriber(); 47 } 48 49 // Perform an initial check on page load with the current email value. 50 this.verifyUser(this.$emailInput.val()); 51 console.log("Trust Swiftly Verification Initialized for " + (this.isBlockCheckout ? "Block" : "Classic") + " Checkout."); 52 }, 53 54 /** 55 * Injects the verification UI elements into the page. 56 */ 57 setupVerificationUI: function() { 58 if ($('#ts-verification-container').length > 0) return; 59 var $parent = this.isBlockCheckout ? 60 this.$emailInput.closest('.wc-block-components-address-form__email, .wc-block-checkout__contact-fields') : 61 this.$emailInput.closest('p.form-row'); 62 if (!$parent.length) $parent = this.$emailInput.parent(); 63 if (!$parent.length) return; 64 65 var spinnerImage = this.config.spinner_url || '/wp-includes/images/wpspin.gif'; 66 const messageText = this.config.checkout_message || 'To checkout, please complete the required verification.'; 67 const verificationContainerHTML = ` 68 <div id="ts-verification-container" class="ts-verification-callout" style="display: none;"> 69 <p class="ts-verification-message">${messageText}</p> 70 <div class="ts-verification-spinner" style="display: none;"> 71 <img src="${spinnerImage}" alt="Loading..." style="width: 20px; height: 20px; margin-right: 8px;"> 72 <span>Verifying...</span> 73 </div> 74 <div class="ts-verification-button-wrapper"></div> 75 </div>`; 76 $parent.append(verificationContainerHTML); 77 }, 78 79 /** 80 * Binds events for email input and payment method changes. 81 */ 82 bindEvents: function() { 83 // When the user types in the email field. 84 $(document.body).on("input", '#billing_email, #email', (e) => { 85 clearTimeout(this.debounceTimer); 86 this.debounceTimer = setTimeout(() => this.verifyUser(e.target.value), 500); 87 }); 88 // When the user changes the payment method. 89 $(document.body).on('change', 'input[name="payment_method"], input[name="radio-control-wc-payment-method-options"]', this.handlePaymentMethodChange.bind(this)); 90 }, 91 92 /** 93 * Wrapper to trigger verification on payment method change. 94 */ 95 handlePaymentMethodChange: function() { 96 if (!this.isInitialized || !this.$emailInput) return; 97 this.verifyUser(this.$emailInput.val()); 98 }, 99 100 /** 101 * The core logic. Makes an API call to check user status and updates the UI and the 102 * isClientSideVerified state variable based on the response. 103 */ 104 verifyUser: function (email) { 105 const $container = $('#ts-verification-container'); 106 const $message = $container.find('.ts-verification-message'); 107 const $spinner = $container.find('.ts-verification-spinner'); 108 const $buttonWrapper = $container.find('.ts-verification-button-wrapper'); 109 110 // Pre-flight checks 111 const currentMethod = $('input[name="payment_method"]:checked').val() || $('input[name="radio-control-wc-payment-method-options"]:checked').val(); 112 const applicableMethods = this.config.applicable_payment_methods || []; 113 114 // If verification isn't required by the current settings, set status to verified and hide the UI. 115 if ((applicableMethods.length > 0 && $.inArray(currentMethod, applicableMethods) === -1) || !isEmailValid(email)) { 116 this.isClientSideVerified = true; 117 this.hideIt(); 118 return; 119 } 120 121 // Prepare for AJAX Call 122 $container.removeClass('ts-pulse-animation ts-verification-success'); 123 $buttonWrapper.hide().empty(); 124 $message.hide(); 125 $spinner.show(); 126 127 // AJAX Call to our custom REST endpoint 128 $.ajax({ 129 url: this.config.rest_url, method: 'POST', beforeSend: (xhr) => xhr.setRequestHeader('X-WP-Nonce', this.config.nonce), 130 data: { email: email, payment_method: currentMethod } 131 }).done((resp) => { 132 $spinner.hide(); 133 if (resp.success) { 134 if (resp.data.type === "user_already_verified") { 135 this.isClientSideVerified = true; // Update state 136 $container.addClass('ts-verification-success'); 137 $message.html('Verification Successful ✔').show(); 138 this.showIt(); 139 } else if (resp.data.type === "ok" && resp.data.method === "link") { 140 this.isClientSideVerified = false; // Update state 141 $container.addClass('ts-pulse-animation'); 142 const messageText = this.config.checkout_message || 'To checkout, please complete the required verification.'; 143 $message.text(messageText).show(); 144 const $btn = $('<a>', { id: 'ts-verify-link', class: 'ts-verify-link', target: '_blank', href: resp.data.link }) 145 .css({ "background-image": "url(" + this.config.btn_img + ")", "display": "block", "background-repeat": "no-repeat", "background-size": "contain", "margin": "10px auto 0" }); 146 $buttonWrapper.append($btn).fadeIn(); 147 this.showIt(); 32 148 } else { 33 if (jQuery("#email").length !== 0) { 34 this.$billingEmail = $("#email"); 35 } else { 36 return 0; 37 } 149 // Unknown success type, treat as verified to not block user, hide UI. 150 this.isClientSideVerified = true; 151 this.hideIt(); 38 152 } 39 40 if (!this.$billingEmail.val()) {41 let img2 = "'" + TSCheckoutConfig.btn_img + "'";42 $checkBtn = $(43 '<span class="ts_emb_verify_temp">' +44 '<div class="row" style="margin-top: 20px"> ' +45 '<div class="col-6" style="margin-top: 20px"> ' +46 '<div class="row" style="margin-top: 20px"> ' +47 '<p style="text-align:center;"><u>Input a Email to verify</u></p> <button id="ts-verify-link" disabled class="btn ts-verify-link col-8" style="border-radius:20px;opacity: 0.5;background-image: url(' +48 img2 +49 ');margin: auto"></button>' +50 "</div></div></div></span>"51 );52 this.$billingEmail.after($checkBtn);53 }54 55 if (jQuery("#email").length !== 0) {56 $("#email").on(57 "change",58 this.maybeVerifyUser.bind(this)59 );60 } else {61 if (jQuery("#billing_email").length !== 0) {62 $("#billing_email").on(63 "change",64 this.maybeVerifyUser.bind(this)65 );66 } else {67 return 0;68 }69 }70 71 this.verifyUser(this.$billingEmail.val());72 73 153 } else { 74 this.verifyUser(this.userEmail); 154 // API call was not successful (e.g., verification not required by API logic). 155 // This means the API said "no verification needed", so the user is clear to proceed. 156 this.isClientSideVerified = true; 157 this.hideIt(); 75 158 } 76 77 // this.initCheckoutFormSubmit(); 78 }, 79 80 // initCheckoutFormSubmit: function() { 81 // $(document).on('submit', '.woocommerce-checkout form', function(e) { 82 // this.checkVerify(); 83 // console.log(123); 84 // return false; 85 // }); 86 // }, 87 88 maybeVerifyUser: function (e) { 89 var email = e.target.value; 90 this.verifyUser(email); 91 }, 92 93 verifyUser: function (email) { 94 if (!email || !this.isEmailValid(email)) { 95 $("#ts-verify-link").remove(); 96 $(".ts_emb_verify_temp").remove(); 97 $(".ts_emb_verify").remove(); 98 return; 159 }).fail(() => { 160 $spinner.hide(); 161 // On server error, block checkout to be safe. 162 this.isClientSideVerified = false; 163 this.hideIt(); 164 }); 165 }, 166 167 /** 168 * Subscribes our validation logic to the official WooCommerce Block Checkout validation hook. 169 */ 170 initCheckoutValidationSubscriber: function() { 171 // The wc.hooks object may not be available immediately on page load, so we wait for it. 172 const interval = setInterval(() => { 173 if (window.wc && window.wc.hooks) { 174 clearInterval(interval); 175 // Add our custom validation function to the checkout_validation hook. 176 window.wc.hooks.addAction('checkout_validation', this.handleCheckoutValidation.bind(this)); 99 177 } 100 101 $('.ts_verification_successful').remove(); 102 $("#ts-verify-link").remove(); 103 $(".ts_emb_verify_temp").remove(); 104 $(".ts_emb_verify").remove(); 105 $(".ts-loader").remove(); 106 107 var sURL = jQuery("#sURL").val(); 108 var sSpinImage = 109 '<img class="ts-loader" src="' + 110 sURL + 111 '/wp-includes/images/wpspin.gif">'; 112 // this.$billingEmail.after(sSpinImage) 113 $("#verify_div").append(sSpinImage); 114 let is_verified = 0; 115 let urlParams = new URLSearchParams(window.location.search); 116 if (urlParams.has("is_verified")) { 117 if (urlParams.get("is_verified") === "1") { 118 is_verified = 1; 119 } 120 } 121 122 if (TSCheckoutConfig.payment_method == "unknown") { 123 TSCheckoutConfig.payment_method = jQuery( 124 "input[name=payment_method]:checked" 125 ).val(); 126 } 127 if ( 128 TSCheckoutConfig.payment_method == "unknown" || 129 typeof TSCheckoutConfig.payment_method === "undefined" 130 ) { 131 if ( 132 jQuery( 133 "input[name=radio-control-wc-payment-method-options]:checked" 134 ).length !== 0 135 ) { 136 TSCheckoutConfig.payment_method = jQuery( 137 "input[name=radio-control-wc-payment-method-options]:checked" 138 ).val(); 139 } 140 } 141 142 $.post( 143 this.config.ajaxUrl + location.search, 144 { 145 action: "ts_get_user_verification", 146 nonce: this.config.nonce, 147 email: email, 148 payment_method: TSCheckoutConfig.payment_method, 149 thank_you_page: this.thankyouPage, 150 }, 151 function (resp) { 152 if (!resp.success) { 153 $(".ts_emb_verify").hide(); 154 return; 155 } 156 157 if (resp.data.type == "ok") { 158 var method = resp.data.method; 159 let pre1 = ""; 160 let pre2 = ""; 161 if (this.thankyouPage === "1") { 162 pre1 = 163 '<div class="col-8" style="margin-top: 20px"> ' + 164 '<div class="row" style="margin-top: 20px"> '; 165 pre2 = "</div></div>"; 166 } 167 if (method == "modal") { 168 if (is_verified === 1) { 169 let $checkBtn; 170 $checkBtn = $( 171 '<span class="ts_emb_verify">' + 172 '<div class="row" style="margin-top: 20px"> ' + 173 pre1 + 174 resp.data.html + 175 '<i class="fa fa-hourglass col-1" style="margin: auto;color:orange"></i>' + 176 '<button id="ts-verify-check-button" class="ts-check-verify btn btn-small col-3" type="button">' + 177 '<i class="fa fa-refresh"></i></button>' + 178 pre2 + 179 "</div></span>" 180 ); 181 if (this.thankyouPage !== "1") { 182 this.$billingEmail.after($checkBtn); 183 } else { 184 $("#verify_div").html($checkBtn); 185 } 186 $("#trustVerify").addClass("col-8"); 187 $("#ts-verify-check-button").on( 188 "click", 189 this.checkVerify.bind(this) 190 ); 191 } else { 192 if (this.thankyouPage !== "1") { 193 this.$billingEmail.after( 194 resp.data.html 195 ); 196 } else { 197 $("#verify_div").html(resp.data.html); 198 } 199 } 200 trustVerify.configs = { 201 embedKey: TSCheckoutConfig.embed_key, 202 signature: resp.data.ts_user_signature, 203 baseUrl: TSCheckoutConfig.base_url, 204 type: "modal_link", 205 verifyDivId: "trustVerify", 206 userId: resp.data.ts_embed_user_id, 207 moduleType: "wordpress", 208 }; 209 210 trustVerify.load(); 211 212 return; 213 } 214 if (this.thankyouPage === "1") { 215 pre1 = 216 '<div class="col-6" style="margin-top: 20px"> ' + 217 '<div class="row" style="margin-top: 20px"> '; 218 } 219 220 var url = resp.data.link; 221 img = TSCheckoutConfig.btn_img; 222 jQuery(".ts-loader").remove(); 223 if (is_verified === 1) { 224 jQuery("#ts-verify-link").remove(); 225 let $checkBtn; 226 img = "'" + img + "'"; 227 $checkBtn = $( 228 '<span class="ts_emb_verify">' + 229 '<div class="row" style="margin-top: 20px"> ' + 230 pre1 + 231 '<a id="ts-verify-link" class="ts-verify-link col-8" style="background-image: url(' + 232 img + 233 ');margin: auto" target="_blank" href="' + 234 url + 235 '"></a>' + 236 '<i class="fa fa-hourglass col-1" style="margin: auto;color:orange"></i>' + 237 '<button id="ts-verify-check-button" class="ts-check-verify btn btn-small col-3" type="button">' + 238 '<i class="fa fa-refresh"></i></button>' + 239 pre2 + 240 "</div></span>" 241 ); 242 if (this.thankyouPage !== "1") { 243 this.$billingEmail.after($checkBtn); 244 } else { 245 $("#verify_div").html($checkBtn); 246 } 247 $("#ts-verify-check-button").on( 248 "click", 249 this.checkVerify.bind(this) 250 ); 251 } else { 252 jQuery("#ts-verify-link").remove(); 253 var $btn = $( 254 '<a id="ts-verify-link" class="ts-verify-link" target="_blank" href="' + 255 url + 256 '"></a>' 257 ); 258 $btn = $btn.css({ 259 "background-image": "url(" + img + ")", 260 }); 261 if (this.thankyouPage !== "1") { 262 this.$billingEmail.after($btn); 263 } else { 264 $("#verify_div").html($btn); 265 } 266 } 267 } else if (resp.data.type == "user_already_verified") { 268 $(".ts_emb_verify").hide(); 269 let $btn = 270 "<span class='ts_verification_successful' style='color:green;" + 271 (jQuery( 272 ".wc-block-components-address-form__email" 273 ).length !== 0 274 ? "display:block" 275 : "") + 276 "'>Verification Successful <i class='fa fa-check' style='color:green'></i></span>"; 277 if (this.thankyouPage !== "1") { 278 this.$billingEmail.after($btn); 279 } else { 280 $("#verify_div").html($btn); 281 } 282 } 283 }.bind(this) 284 ).done(function (resp) { 285 $(".ts-loader").remove(); 286 }); 287 }, 288 isEmailValid: function (email) { 289 var pattern = new RegExp( 290 /^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([ \t]*\r\n)?[ \t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([ \t]*\r\n)?[ \t]+)?")@(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i 291 ); 292 // eslint-disable-line max-len 293 294 return pattern.test(email); 295 }, 296 checkVerify: function (e) { 297 $.post( 298 this.config.ajaxUrl, 299 { 300 action: "ts_check_user_verification", 301 nonce: this.config.nonce, 302 }, 303 function (resp) { 304 if (!resp.success) { 305 return; 306 } 307 308 if (resp.data.is_verified == "1") { 309 $(".ts_emb_verify").hide(); 310 let $btn = 311 "<span style='color:green'>Verification Successful <i class='fa fa-check' style='color:green'></i></span>"; 312 if (this.thankyouPage !== "1") { 313 this.$billingEmail.after($btn); 314 } else { 315 $("#verify_div").html($btn); 316 } 317 } 318 }.bind(this) 319 ); 320 }, 321 hideIt: function (e) { 322 $(".ts_emb_verify").hide(); 323 $(".ts-verify-link").hide(); 324 }, 325 }; 178 }, 100); 179 }, 180 181 /** 182 * This is the callback for the 'checkout_validation' hook. It runs when the user clicks "Place Order". 183 * It must be SYNCHRONOUS and immediately return a value. 184 */ 185 handleCheckoutValidation: function() { 186 // It simply reads the state variable we've been maintaining. 187 if (this.isClientSideVerified) { 188 return true; // Return true to allow checkout to proceed. 189 } 190 // If not verified, return an error object. WooCommerce will display the message. 191 return { 192 errorMessage: 'Please complete the Trust Swiftly verification before placing your order.' 193 }; 194 }, 195 196 hideIt: function () { $('#ts-verification-container').slideUp(); }, 197 showIt: function () { $('#ts-verification-container').slideDown(); } 198 }; 199 200 /** 201 * Finds the email input field on the page and initializes the script. 202 * Retries for a few seconds to handle cases where the field is rendered late. 203 */ 204 $(document).ready(function() { 205 const checkInterval = 1000; 206 const maxChecks = 15; 207 let checks = 0; 208 const observerInterval = setInterval(() => { 209 // Find the first visible email input for either classic or block checkout. 210 const $emailInput = $('#billing_email:visible, #email:visible').first(); 211 if ($emailInput.length > 0) { 212 clearInterval(observerInterval); 213 TSVerification.init($emailInput); 214 } 215 checks++; 216 if (checks >= maxChecks) { 217 clearInterval(observerInterval); 218 } 219 }, checkInterval); 326 220 }); 327 var fInterval = 0; 328 var bIsVerified = 0; 329 var funcAreAllItemsLoaded = function () { 330 /*if(jQuery('input[name=payment_method]').length!==0){ 331 //return ; 332 }*/ 333 if ( 334 jQuery("#email").length !== 0 || 335 jQuery("#billing_email").length !== 0 336 ) { 337 if (TSCheckoutConfig.thank_you_page !== "1") { 338 window.TSVerification.init(); 339 } 340 341 jQuery(".wc-block-components-checkout-place-order-button").click( 342 function (event) { 343 if (bIsVerified) { 344 return true; 345 } 346 event.preventDefault(); 347 var email = ""; 348 if (jQuery("#email").length !== 0) { 349 email = jQuery("#email").val(); 350 } 351 if (jQuery("#billing_email").length !== 0) { 352 email = jQuery("#billing_email").val(); 353 } 354 355 if (!email || !isEmailValid(email)) { 356 return; 357 } 358 359 var payment_method = "unknown"; 360 if ( 361 jQuery( 362 "input[name=radio-control-wc-payment-method-options]:checked" 363 ).length !== 0 364 ) { 365 payment_method = jQuery( 366 "input[name=radio-control-wc-payment-method-options]:checked" 367 ).val(); 368 } 369 370 if (payment_method == "unknown") { 371 payment_method = jQuery( 372 "input[name=payment_method]:checked" 373 ).val(); 374 } 375 if (typeof payment_method === "undefined") { 376 payment_method = "unknown"; 377 } 378 jQuery.ajax({ 379 type: "POST", 380 url: TSCheckoutConfig.ajax_url, 381 data: { 382 action: "ts_verifyVerification", 383 email: email, 384 payment_method: payment_method, 385 }, 386 success: function (data) { 387 if (data.message != "") { 388 jQuery( 389 ".ts-err-verification-required" 390 ).remove(); 391 jQuery( 392 ".wp-block-woocommerce-checkout-actions-block" 393 ).prepend( 394 '<div class="woocommerce-error ts-err-verification-required" role="alert">' + 395 data.message + 396 "</div>" 397 ); 398 } else { 399 bIsVerified = 1; 400 jQuery( 401 ".wc-block-components-checkout-place-order-button" 402 ).click(); 403 } 404 }, 405 error: function (data) {}, 406 }); 407 408 return false; 409 } 410 ); 411 } 412 if ( 413 jQuery("#email").length !== 0 || 414 jQuery("#billing_email").length !== 0 415 ) { 416 clearInterval(fInterval); 417 } 418 }; 419 fInterval = window.setInterval(funcAreAllItemsLoaded, 1000); 221 420 222 })(jQuery); -
trust-swiftly-verification/trunk/readme.txt
r3238884 r3320256 1 === Top Identity Verificationsfor WooCommerce | Trust Swiftly ===1 === Identity Verification for WooCommerce | Trust Swiftly === 2 2 Contributors: trustswiftly 3 Tags: id verification, fraud prevention, verify id, woocommerce, age verify3 Tags: id verification, identity verification, fraud prevention, age verification, woocommerce, kyc, aml, identity proofing, verify id 4 4 Requires at least: 6.7 5 Tested up to: 6. 7.15 Tested up to: 6.8.1 6 6 Requires PHP: 8.2 7 Stable tag: 1.1.1 37 Stable tag: 1.1.14 8 8 License: GPLv2 or later 9 9 10 Flexible, secure, and accurate identity verifications for WooCommerce stores 10 The most flexible, secure, and accurate identity verification platform for WooCommerce. 11 11 12 12 == Description == 13 13 14 Trust Swiftly provides flexible and accurate identity verifications with over 15 different verification methods. Trust Swiftly is easily customizable through our dashboard and configurable with Woocommerce to optimize your customer's experience with frictionless verifications.14 Trust Swiftly provides the most flexible and accurate identity verification platform for WooCommerce. Protect your store from fraud, prevent chargebacks, and comply with age-restricted sales regulations using over 15 customizable verification methods. Our plugin is easily configurable to optimize your customer's experience with frictionless verifications. 15 15 16 Trust Swiftly helps businesses adaptively fight fraud by applying the right friction when needed. From SMS verification to ID, Banking, Voice, Signatures and Credit Cards, you can be sure all checks are covered.16 Trust Swiftly helps businesses adaptively fight fraud by applying the right level of friction when needed. From simple SMS verification to robust document, banking, voice, and signature checks, you can be sure all your compliance and security needs are covered. 17 17 18 * Verify age for restricted products (Alcohol, cannabis and vaping) 19 * Prevent fraud from risky transactions (Chargebacks and high value goods) 20 * Verify all country IDs, Driver License, Passports, State IDs, and more 21 * Adhere to KYC and AML regulations 18 **Key Use Cases:** 19 20 * **Verify Age:** For restricted products like alcohol, cannabis, and vaping. 21 * **Prevent Fraud:** Reduce chargebacks on risky transactions and high-value goods. 22 * **Global ID Verification:** Verify government-issued IDs, Driver's Licenses, Passports, and more from hundreds of countries. 23 * **Regulatory Compliance:** Adhere to Know Your Customer (KYC) and Anti-Money Laundering (AML) regulations. 22 24 23 25 [youtube https://www.youtube.com/watch?v=9aUsSZgLXOo] 24 26 25 Trust Swiftly supports all types of identity documents from hundreds of different countries. Supported documents include: 27 **Supported Document Types Include:** 26 28 27 * Driver’s Licenses 28 * Passports 29 * Insurance Cards 30 * Concealed Carry Licenses 31 * State IDs 32 * Country IDs 33 * National ID Cards 29 * Driver’s Licenses 30 * Passports 31 * Insurance Cards 32 * Concealed Carry Licenses 33 * State IDs & National ID Cards 34 34 35 S tart using the best and top identity verification plugin for WooCommerce.35 Secure your business and build trust with your customers today. 36 36 37 37 == Installation == 38 38 39 **Prerequisite:** A Trust Swiftly account . Sign up for free [https://app.trustswiftly.com/create](https://app.trustswiftly.com/create)39 **Prerequisite:** A Trust Swiftly account is required. [**Sign up for a free account here**](https://app.trustswiftly.com/create). 40 40 41 = Setup in Trust Swiftly and WP Plugin = 41 Follow these steps to configure the integration. 42 42 43 To configure the integration with Trust Swiftly, follow the steps below. 43 1. **Get Your API Key & Base URL:** 44 * Log in to your [Trust Swiftly Dashboard](https://app.trustswiftly.com/login). 45 * Your **Base URL** is your unique, branded site name (e.g., `https://your-company.trustswiftly.com`). 46 * Navigate to <kbd>Developer</kbd> -> <kbd>API</kbd> to get your **API Key**. 44 47 45 1. Log in to the Trust Swiftly dashboard. Your **base url** is your branded site name you login i.e. `https://EXAMPLE.trustswiftly.com` 46 2. **Create a Template** in the Trust Swiftly dashboard to configure the user verification steps. Read the documentation on managing templates for more information. [How to create templates?](https://support.trustswiftly.com/how-to-manage-templates.html) 47 3. Navigate to the **Developer > API** page to create an API key. i.e. `https://EXAMPLE.trustswiftly.com/settings/developer` 48 4. Navigate to the **Developer > Webhooks** page to create an IPN which notifies your store about completed verifications incase of redirect problems. Click add Webhook at enter the IPN listed on your TS settings page. i.e. `https://example.com/wp-json/ts/v1/ipn` Afterwards make sure to copy the secret from the button to input later. 49 5. Update in your Trust Swiftly dashboard settings the **Completion Redirect URL**, Go to `https://EXAMPLE.trustswiftly.com/settings` copy and paste the url given on the Wordpress TS settings page and update. i.e. `https://example.com/wp-json/ts/v1/return/?order_id=[order_id]&email=[user_email]` 50 6. You should now have the **API Key, Secret, and Embed Key** then update in the Wordpress settings of Trust Swiftly. The webhoook secret should also be added if that feature is enabled. 51 7. Click Save to test the API connection. Once it is confirmed you can then select the remaining settings like the Verification template or trigger location of the verification (Before or after checkout). 48 2. **Connect to WordPress:** 49 * In your WordPress admin, go to the Trust Swiftly settings page. 50 * Enter your **Base URL** and **API Key**. 51 * Click **Save Changes**. The plugin will test the connection. 52 53 3. **Create a Verification Template:** 54 * In the Trust Swiftly dashboard, go to <kbd>Templates</kbd> and create a new template to define the verification steps you want users to follow. 55 * For more details, read our guide on [how to manage templates](https://support.trustswiftly.com/how-to-manage-templates.html). 56 57 4. **Set Up Webhooks (IPN):** 58 * A webhook ensures verification updates are always received, even if a user has redirect issues. 59 * In your Trust Swiftly dashboard, go to <kbd>Developer</kbd> -> <kbd>Webhooks</kbd> and click **Add Webhook**. 60 * Copy the IPN URL from your WordPress plugin settings page (e.g., `https://your-site.com/wp-json/ts/v1/ipn`) and paste it into the webhook form. 61 * After creating it, click **Show Secret**, copy the **Webhook Secret**, and paste it into the corresponding field in your WordPress plugin settings. 62 63 5. **Configure Final Settings:** 64 * Back in WordPress, select your newly created **Verification Template** from the dropdown menu. 65 * Choose where to trigger the verification (e.g., before or after checkout) and configure any other desired options. 66 * Save your settings, and you're ready to go! 52 67 53 68 == Frequently Asked Questions == 54 69 55 = How does it work? 70 = How does it work? = 56 71 57 Trust Swiftly uses AI to automatically detect and verify identities. Driver license, passports, and more can be checked for age and fraud related checks. You can learn how the customer receives the email, link, or SMS to complete the verification. [https://trustswiftly.com/features/](https://trustswiftly.com/features/)72 Trust Swiftly uses AI to automatically detect and verify identities. Customers receive a secure link via email, QR code, or SMS to complete the verification on any device. You can learn more about our verification methods on our [Features page](https://trustswiftly.com/features/). 58 73 59 = What countries and types of identity documents do es your system support?74 = What countries and types of identity documents do you support? = 60 75 61 Trust Swiftly supports all types of ID documents from hundreds of differentcountries. Supported documents include:76 We support all major types of ID documents from hundreds of countries. Supported documents include: 62 77 63 * Driver’s Licenses64 * Passports65 * Insurance Cards66 * Concealed Carry Licenses67 * State IDs68 * Country IDs69 * National ID Cards78 * Driver’s Licenses 79 * Passports 80 * Insurance Cards 81 * Concealed Carry Licenses 82 * State IDs 83 * Country IDs 84 * National ID Cards 70 85 71 If you find an ID that doesn't work let us know. We’d be happy to help by adding it to our system.86 If you encounter an ID that isn't supported, let us know! We are always expanding our coverage. 72 87 73 = How much does this cost? 88 = How much does this cost? = 74 89 75 Depending on the verification we offer different pricing. As low as $0.01 per verify. No montly commitments with pay as you go pricing. You can learn more here [https://trustswiftly.com/#pricing](https://trustswiftly.com/#pricing) 90 We offer flexible, pay-as-you-go pricing with no monthly commitments, starting as low as $0.01 per verification. You can find detailed pricing information here: [Trust Swiftly Pricing](https://trustswiftly.com/#pricing). 76 91 77 92 = What is Trust Swiftly? = 78 93 79 Trust Swiftly is a cloud-based identity verification software designed to help businesses verify their customers through over 15 different security capabilities. Adding this plugin, gives anyone the ability to step up identity proofing on Wordpress. The plugin will allow you to verify IDs, selfies, credit cards, addresses, SSNs, phone numbers, signatures and much more. Use Trust Swiftly to verify your customers to prevent chargebacks or when they purchase age restricted products.94 Trust Swiftly is a cloud-based identity verification platform designed to help businesses secure their operations. Our plugin for WordPress allows you to easily integrate over 15 different verification capabilities, including ID checks, selfie biometrics, address validation, SSN lookups, and more, to prevent fraud and meet compliance standards. 80 95 81 See [https://trustswiftly.com/features/](https://trustswiftly.com/features/) for more info. 96 = Does this work with any other WooCommerce plugins? = 82 97 83 = Does this work with any other WooCommerce plugins? 98 Yes, Trust Swiftly integrates perfectly with the official [WooCommerce Anti-Fraud](https://woo.com/document/woocommerce-anti-fraud/) plugin. Combine our identity verification with their AI-powered fraud detection for comprehensive, multi-layered security. 84 99 85 Yes Trust Swiftly works with the top rated Anti-Fraud plugin. Combining our identity verifications with Anti-Fraud AI fraud detection will secure your site. You can learn more here [https://woo.com/document/woocommerce-anti-fraud/](https://woo.com/document/woocommerce-anti-fraud/) 100 = Need help getting started or have feedback? = 86 101 87 = Need help getting started or changes? 88 89 We are always looking to improve our plugin and any feedback is appreciated. Contact us at [email protected] for support or feedback. Our support site also has useful tips on preventing fraud [https://support.trustswiftly.com/](https://support.trustswiftly.com/) 102 We are always looking to improve our plugin. Please contact us at `[email protected]` for assistance or feedback. Our support site also has useful tips on preventing fraud: [support.trustswiftly.com](https://support.trustswiftly.com/). 90 103 91 104 == Changelog == 92 105 93 = 1.0.0 = 94 Initial release. 106 = 1.1.14 = 107 * **Tweak:** Improved the checkout user experience by making the verification button appear instantly as a valid email is typed. 108 * **Tweak:** Added a loading spinner and instructional text during the verification process for better user feedback and a more polished feel. 109 * **Update:** Updated and improved the plugin's `readme.txt` for better clarity and easier setup. 110 * **Update:** Compatibility confirmed for WordPress 6.8.1 and WooCommerce 6.8.1. 95 111 96 = 1.0.1 = 97 * Permission fix 98 * Updated readme 112 = 1.1.13 = 113 * **Tweak:** Simplified plugin setup. The Secret and Embed Key are no longer required. Removed the legacy modal option in favor of a more streamlined verification flow. 99 114 100 = 1. 0.2 =101 * Updated readme115 = 1.1.12 = 116 * Fix: Resolved an issue with the verification status on the customer's return to the site. 102 117 103 = 1. 0.3=104 * Updated css assets for buttons118 = 1.1.11 = 119 * Fix: Addressed a bug related to the block-based checkout. 105 120 106 = 1. 0.4=107 * Version fix121 = 1.1.10 = 122 * Feature: Added support for the new WooCommerce block-based checkout. 108 123 109 = 1.0.5 = 110 * Fix icons loading 124 = 1.1.6 = 125 * Feature: Added enhancements for identity verification options. Tested with WordPress 6.4. 126 127 = 1.1.4 = 128 * Feature: Added an option to notify users via email. 129 130 = 1.1.3 = 131 * Fix: Resolved an API warning. 132 133 = 1.0.8 = 134 * Feature: Added the ability to require verification only for specific payment methods. 111 135 112 136 = 1.0.7 = 113 * Fix bugs137 * Fix: General bug fixes and stability improvements. 114 138 115 = 1.0.8 = 116 * Added feature to limit payment methods that require verification 117 118 = 1.1.3 = 119 * Fixed API warning. 120 121 = 1.1.4 = 122 * Add email notify option 123 124 = 1.1.6 = 125 * Added support for 6.4 and identity verification option enhancements 126 127 = 1.1.10 = 128 * Added support for WooCommerce Block checkout 129 130 = 1.1.11 = 131 * Fix block checkout bug 132 133 = 1.1.12 = 134 * Fix verification status on return 135 136 = 1.1.13 = 137 * Removed modal option, secret and embed key no longer needed. 139 = 1.0.0 = 140 * Initial release. -
trust-swiftly-verification/trunk/src/Settings/Settings.php
r3238884 r3320256 161 161 'verification_method', 162 162 'allow_guest_checkout_verify', 163 'checkout_message', // Added this line 163 164 'custom_css' 164 165 ]; 165 166 166 167 foreach ($sanitizeValues as $field) { 167 if (is_array($input[$field])) { 168 $sanitaryValues[$field] = array_map('esc_attr', $input[$field]); 169 } 170 else { 171 $sanitaryValues[$field] = sanitize_text_field($input[$field]); 168 // --- THE FIX IS HERE --- 169 // First, check if the key was actually submitted in the form. 170 if (isset($input[$field])) { 171 // If it was, sanitize it. 172 // If the key was submitted, sanitize it. 173 if (is_array($input[$field])) { 174 $sanitaryValues[$field] = array_map('esc_attr', $input[$field]); 175 } else { 176 $sanitaryValues[$field] = sanitize_text_field($input[$field]); 177 } 178 } else { 179 // If the key was NOT submitted (e.g., an empty multi-select or unchecked checkbox), 180 // we must explicitly set it to an empty value to clear it in the database. 181 // This is the fix. 182 $sanitaryValues[$field] = ''; 172 183 } 173 184 } … … 201 212 case 'url': 202 213 case 'password': 203 $html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($optionName) . '" placeholder="' . esc_attr(ts_array_get($field, 'placeholder', '')) . '" value="' . $data . '" />' . "\n";214 $html .= '<input id="' . esc_attr($field['id']) . '" type="' . $field['type'] . '" name="' . esc_attr($optionName) . '" placeholder="' . esc_attr(ts_array_get($field, 'placeholder', '')) . '" value="' . $data . '"' . (isset($field['autocomplete']) ? ' autocomplete="' . esc_attr($field['autocomplete']) . '"' : '') . '/>' . "\n"; 204 215 if (ts_array_get($field, 'toggle') == 1) { 205 216 $html .= '<a href="#" class="js-toggle-password-visibility">' . __('Show', 'trustswifly-verification') . '</a>'; … … 459 470 'type' => 'password', 460 471 'toggle' => 1, 472 'autocomplete' => 'off', // Add this line 461 473 'default' => '', 462 474 'required' => 'true', … … 615 627 'default' => '', 616 628 'description' => __('Select the button style of Trust Swiftly to display on your checkout page or order complete.', 'trustswiftly-verifications') 629 ], 630 [ 631 'id' => 'checkout_message', 632 'label' => __('Checkout Message' , 'trustswiftly-verification'), 633 'type' => 'textarea', 634 'default' => __('To checkout, please complete the required verification.', 'trustswiftly-verification'), 635 'placeholder' => __('To checkout, please complete the required verification.', 'trustswiftly-verification'), 636 'description' => __('The message displayed to users on the checkout page when verification is required.', 'trustswiftly-verifications') 617 637 ], 618 638 [ -
trust-swiftly-verification/trunk/src/TrustVerifyPlugin.php
r3238884 r3320256 7 7 use TrustswiftlyVerification\WooCommerce\ReturnHandler; 8 8 use TrustswiftlyVerification\WooCommerce\Verification; 9 9 10 class TrustVerifyPlugin 10 11 { … … 22 23 */ 23 24 protected static $singletons = []; 24 25 /** 26 * Required plugins 27 * 28 * @var array 29 */ 30 protected static $requiredPlugins = [ 31 'woocommerce/woocommerce.php' => 'WooCommerce' 32 ]; 25 33 /** 26 34 * Plugin components … … 36 44 37 45 /** 38 * Required plugins39 *40 * @var array41 */42 protected static $requiredPlugins = [43 'woocommerce/woocommerce.php' => 'WooCommerce'44 ];45 46 /**47 46 * Constructor 48 47 */ … … 50 49 { 51 50 add_action('admin_init', [$this, 'checkRequirements']); 52 if( !function_exists('is_plugin_active') ) { 53 include_once( ABSPATH . 'wp-admin/includes/plugin.php' ); 54 } 51 52 if (!function_exists('is_plugin_active')) { 53 include_once(ABSPATH . 'wp-admin/includes/plugin.php'); 54 } 55 56 // Only initialize components and add hooks if the required plugins are active. 57 // The 'checkRequirements' hook will handle notices if they are not. 55 58 if (is_plugin_active('trust-swiftly-verification/trustswiftly-verification.php') && is_plugin_active('woocommerce/woocommerce.php')) { 56 59 $this->initComponents(); 57 60 add_action('wp_enqueue_scripts', [$this, 'addAssets']); 58 61 add_action('admin_enqueue_scripts', [$this, 'addAdminAssets']); 59 } 62 add_action('rest_api_init', [$this, 'register_rest_routes']); 63 } 64 } 65 66 /** 67 * Init plugin components 68 * @return void 69 */ 70 public function initComponents() 71 { 72 foreach ($this->components as $component) { 73 new $component(); 74 } 75 } 76 77 /** 78 * Get a singleton servce 79 * @param string $class 80 * @return mixed 81 */ 82 public static function get($class) 83 { 84 if (!class_exists($class) || !in_array($class, static::$singletons)) { 85 return null; 86 } 87 if (!isset(static::$container[$class])) { 88 static::$container[$class] = new $class; 89 } 90 return static::$container[$class]; 91 } 92 93 /** 94 * Get Plugin Path 95 * @return string 96 */ 97 public static function pluginDir() 98 { 99 return plugin_dir_path(TS_PLUGIN_BASE_PATH); 100 } 101 102 /** 103 * --- ADDED --- 104 * Registers the custom REST API routes for the plugin. 105 */ 106 public function register_rest_routes() 107 { 108 register_rest_route('trustswiftly/v1', '/verify-user', [ 109 'methods' => \WP_REST_Server::CREATABLE, // This corresponds to POST 110 'callback' => [Verification::class, 'handle_rest_get_user_verification'], 111 'permission_callback' => '__return_true', // Public endpoint, security is handled by nonce 112 ]); 113 } 114 115 /** 116 * Check if all required plugins are active 117 * @return boolean 118 */ 119 public function checkRequirements() 120 { 121 return self::activate(); 60 122 } 61 123 … … 68 130 69 131 foreach (self::$requiredPlugins as $key => $name) { 70 71 if (! is_plugin_active($key)) { 132 if (!is_plugin_active($key)) { 72 133 $missingPlugins[$key] = $name; 73 134 } … … 78 139 } 79 140 80 add_action('admin_notices', function () use ($missingPlugins) {141 add_action('admin_notices', function () use ($missingPlugins) { 81 142 $names = rtrim(implode(', ', $missingPlugins), ', '); 82 83 143 printf( 84 144 '<div class="notice notice-error is-dismissible"><p>%s</p></div>', 85 145 __("Trustswiftly Verification requires <strong>{$names}</strong> to be active", 'trustswiftly-verification') 86 146 ); 87 88 147 }); 89 148 deactivate_plugins('trust-swiftly-verification/trustswiftly-verification.php'); … … 92 151 93 152 /** 94 * Check if all required plugins are active95 *96 * @return boolean97 */98 public function checkRequirements()99 {100 return self::activate();101 }102 103 /**104 153 * Add plugin assets 105 *106 154 * @return void 107 155 */ 108 156 public function addAssets() 109 157 { 110 $loadScripts = Verification::shouldVerifyBeforeCheckoutAtAssets(); 111 if (!$loadScripts){ 112 $loadScripts = ts_get_option('verify_on', Verification::VERIFY_AFTER_CHECKOUT) == Verification::VERIFY_AFTER_CHECKOUT; 113 } 114 $verificationMethod = ts_get_option('verification_method', Settings::defaultVerificationMethod()); 158 // This function now only handles the Classic Checkout and the settings object. 159 // Block checkout assets are handled separately. 160 $verificationMethod = ts_get_option('verification_method', 'link'); 115 161 $baseUrl = ts_get_option('base_url'); 116 162 117 $recievedPage=is_wc_endpoint_url( 'order-received' );118 if ($loadScripts && (is_wc_endpoint_url( 'order-received' ) || is_checkout())) {163 if (is_checkout()) { 164 // Enqueue assets for checkout pages. 119 165 $currentUser = wp_get_current_user(); 120 $jsDependecies = [ 121 'jquery',122 ]; 123 124 wp_enqueue_script('ts-checkout-js', static::pluginUrl() . 'assets/js/checkout.js', $jsDependecies, '1.0');125 wp_enqueue_script('ts-checkout- helper-js', static::pluginUrl() . 'assets/js/checkout-helper.js', $jsDependecies);166 $jsDependecies = ['jquery']; 167 $plugin_version = defined('TS_PLUGIN_VERSION') ? TS_PLUGIN_VERSION : time(); 168 169 // Enqueue script for both checkouts, but it will have logic to differentiate 170 wp_enqueue_script('ts-checkout-js', static::pluginUrl() . 'assets/js/checkout.js', $jsDependecies, $plugin_version, true); 171 wp_enqueue_script('ts-checkout-block-js', static::pluginUrl() . 'assets/js/checkout-block.js', $jsDependecies, $plugin_version, true); 126 172 127 173 wp_localize_script('ts-checkout-js', 'TSCheckoutConfig', [ 128 'is_checkout' => is_checkout(), 129 'nonce' => wp_create_nonce('ts_action'), 174 'nonce' => wp_create_nonce('wp_rest'), // For REST API calls 175 'ajax_nonce' => wp_create_nonce('ts_action'), // For admin-ajax calls 176 'rest_url' => get_rest_url(null, 'trustswiftly/v1/verify-user'), 130 177 'ajax_url' => admin_url('admin-ajax.php'), 131 'verify_link_text' => __('Verify Your Account', 'trustswiftly-verification'),132 'is_user_verified' => ts_is_user_verified($currentUser->ID),133 'verify_before_checkout' => ts_get_option('verify_on', Verification::VERIFY_AFTER_CHECKOUT) == Verification::VERIFY_BEFORE_CHECKOUT,134 178 'btn_img' => self::pluginUrl() . 'assets/img/' . ts_get_option('btn_img', Settings::defaultBtnImg()), 135 ' verification_method' => $verificationMethod,136 ' thank_you_page' => $recievedPage,137 ' payment_method' => "unknown",138 ' base_url' => $baseUrl,179 'applicable_payment_methods' => (array)ts_get_option('applicable_payment_methods', []), 180 'checkout_message' => ts_get_option('checkout_message', __('To checkout, please complete the required verification.', 'trustswiftly-verification')), 181 'user_email' => $currentUser->user_email, // Added for the old JS 182 'thank_you_page' => is_wc_endpoint_url('order-received') ? '1' : '0', // Added for the old JS 139 183 ]); 140 wp_enqueue_style('ts-app-css', static::pluginUrl() . 'assets/css/app.css'); 141 wp_add_inline_style('ts-app-css',".ts_emb_verify{".ts_get_option('custom_css')."}"); 142 } 143 } 144 184 wp_enqueue_style('ts-app-css', static::pluginUrl() . 'assets/css/app.css', [], $plugin_version); 185 wp_add_inline_style('ts-app-css', ".ts_emb_verify{" . ts_get_option('custom_css') . "}"); 186 } 187 } 188 189 /** 190 * Get Plugin Url 191 * @return string 192 */ 193 public static function pluginUrl() 194 { 195 return plugin_dir_url(TS_PLUGIN_BASE_PATH); 196 } 145 197 146 198 /** 147 199 * Add admin assets 148 *149 200 * @return void 150 201 */ 151 202 public function addAdminAssets() 152 203 { 153 // Add admin assets154 204 $screen = get_current_screen(); 155 156 205 if ($screen && $screen->id == 'toplevel_page_ts-settings') { 157 158 206 wp_enqueue_style('ts-admin-css', static::pluginUrl() . 'assets/css/admin.css'); 159 207 wp_enqueue_style('ts-select2', static::pluginUrl() . 'assets/css/select2.min.css'); 160 161 wp_enqueue_script('ts-select2', static::pluginUrl() . 'assets/js/select2.min.js', [ 162 'jquery' 163 ]); 164 165 wp_enqueue_script('ts-admin-js', static::pluginUrl() . 'assets/js/admin.js', [ 166 'jquery', 167 'ts-select2' 168 ]); 208 wp_enqueue_script('ts-select2', static::pluginUrl() . 'assets/js/select2.min.js', ['jquery']); 209 wp_enqueue_script('ts-admin-js', static::pluginUrl() . 'assets/js/admin.js', ['jquery', 'ts-select2']); 169 210 $cm_settings['codeEditor'] = wp_enqueue_code_editor(array('type' => 'text/css')); 170 211 wp_localize_script('jquery', 'cm_settings', $cm_settings); 171 172 212 wp_enqueue_script('wp-theme-plugin-editor'); 173 213 wp_enqueue_style('wp-codemirror'); 174 214 } 175 215 } 176 177 /**178 * Init plugin components179 *180 * @return void181 */182 public function initComponents()183 {184 foreach ($this->components as $component) {185 new $component();186 }187 }188 189 /**190 * Get a singleton servce191 *192 * @param string $class193 * @return mixed194 */195 public static function get($class)196 {197 if (! class_exists($class) || ! in_array($class, static::$singletons)) {198 return null;199 }200 201 if (! isset(static::$container[$class])) {202 static::$container[$class] = new $class;203 }204 205 return static::$container[$class];206 }207 208 /**209 * Get Plugin Url210 *211 * @return string212 */213 public static function pluginUrl()214 {215 return plugin_dir_url(TS_PLUGIN_BASE_PATH);216 }217 218 /**219 * Get Plugin Path220 *221 * @return string222 */223 public static function pluginDir()224 {225 return plugin_dir_path(TS_PLUGIN_BASE_PATH);226 }227 216 } -
trust-swiftly-verification/trunk/src/WooCommerce/Verification.php
r3238884 r3320256 9 9 use TrustswiftlyVerification\Settings\Settings; 10 10 11 class Verification 11 class Verification 12 12 { 13 13 const USER_ALREADY_VERIFIED = 'user_already_verified'; 14 14 const OK = 'ok'; 15 16 15 const VERIFY_BEFORE_CHECKOUT = 'before_checkout'; 17 16 const VERIFY_AFTER_CHECKOUT = 'after_checkout'; … … 19 18 public function __construct() 20 19 { 21 add_filter( 'query_vars', [$this,'add_query_vars_filter'] ); 20 // --- FINALIZED HOOKS --- 21 add_filter('query_vars', [$this, 'add_query_vars_filter']); 22 22 add_action('wp_ajax_ts_get_user_verification', [$this, 'getUserVerification']); 23 23 add_action('wp_ajax_nopriv_ts_get_user_verification', [$this, 'getUserVerification']); 24 add_action('wp_ajax_nopriv_ts_verifyVerification', [$this, 'verifyVerification_forBlocks']);25 add_action('wp_ajax_ts_verifyVerification', [$this, 'verifyVerification_forBlocks']);26 24 add_action('wp_ajax_ts_check_user_verification', [$this, 'checkUserVerification']); 27 25 add_action('wp_ajax_nopriv_ts_check_user_verification', [$this, 'checkUserVerification']); 28 29 26 add_action('woocommerce_thankyou', [$this, 'maybeRenderVerification']); 30 27 add_action('woocommerce_admin_order_data_after_shipping_address', [$this, 'displayCustomOrderData']); 31 32 add_action('woocommerce_after_checkout_validation', [$this, 'verifyVerification'], 10, 2); 33 34 add_filter( 'manage_edit-shop_order_columns', [$this,'ts_add_new_order_admin_list_column'] ); 35 36 add_action( 'manage_shop_order_posts_custom_column', [$this,'ts_add_new_order_admin_list_column_content'] ); 37 38 add_action( 'woocommerce_review_order_before_payment', [$this,'refresh_payment_methods'] ); 28 add_filter('manage_edit-shop_order_columns', [$this, 'ts_add_new_order_admin_list_column']); 29 add_action('manage_shop_order_posts_custom_column', [$this, 'ts_add_new_order_admin_list_column_content']); 30 add_action('woocommerce_review_order_before_payment', [$this, 'refresh_payment_methods']); 39 31 add_action('wp_footer', [$this, 'ExtraFooter'], 9999); 40 41 // add_action('init', function() { 42 // $v = ts_is_user_verified(17); 43 // var_dump($v); 44 // die; 45 // }); 32 add_action('wp_ajax_ts_verifyVerification', [$this, 'verifyVerification_forBlocks']); 33 add_action('wp_ajax_nopriv_ts_verifyVerification', [$this, 'verifyVerification_forBlocks']); 34 35 // Server-side validation for Classic Checkout 36 add_action('woocommerce_after_checkout_validation', [$this, 'validate_classic_checkout'], 10, 2); 37 38 // Server-side validation for Block Checkout 39 add_action('woocommerce_blocks_checkout_process', [$this, 'validate_block_checkout'], 10, 2); 40 } 41 42 public function ExtraFooter(){ 43 echo '<input type="hidden" id="sURL" value="'.esc_url(get_site_url()).'">'; 44 } 45 46 public static function handle_rest_get_user_verification(\WP_REST_Request $request) { 47 $email = sanitize_email($request->get_param('email')); 48 $paymentMethod = sanitize_text_field($request->get_param('payment_method')); 49 $self = new self(); 50 51 if (empty($email) || !is_email($email)) { 52 return new \WP_REST_Response(['success' => false, 'data' => ['message' => 'Email is required']], 400); 53 } 54 if (!self::shouldVerifyBeforeCheckout($paymentMethod)) { 55 return new \WP_REST_Response(['success' => false, 'data' => ['reason' => 'not_required']], 200); 56 } 57 58 if ( (is_user_logged_in() && ts_is_user_verified(get_current_user_id())) || 59 (!is_user_logged_in() && ts_get_option('allow_guest_checkout_verify') && $self->is_verification_complete($email, $paymentMethod)) ) { 60 return new \WP_REST_Response(['success' => true, 'data' => ['type' => self::USER_ALREADY_VERIFIED]]); 61 } 46 62 47 48 // add_action('init', function() { 49 // if (isset($_GET['delete_ts_user'])) { 50 // $user = wp_get_current_user(); 51 52 // if (! $user) { 53 // return; 54 // } 55 56 // $userId = get_user_meta($user->ID, '_trust_user_id', true); 57 58 // delete_user_meta($user->ID, '_trust_user_id'); 59 // delete_user_meta($user->ID, '_trust_data'); 60 // delete_user_meta($user->ID, '_trust_embed_user_id'); 61 62 // if ($userId) { 63 // $api = ts_api(); 64 // $api->userClient()->deleteUser($userId); 65 // } 66 // } 67 68 // }); 69 } 70 public function ExtraFooter(){ 71 echo'<input type="hidden" id="sURL" value="'.get_site_url().'">'; 72 } 63 $userIds = $self->createOrFindTsUser(is_user_logged_in() ? get_current_user_id() : null, $email); 64 if (!$userIds) { 65 return new \WP_REST_Response(['success' => false, 'data' => ['message' => 'API Error']], 500); 66 } 67 if (is_user_logged_in()) { 68 update_user_meta(get_current_user_id(), '_trust_user_id', $userIds[0]); 69 } 70 $link = $self->getMagicLink($userIds[0]); 71 if (!$link) { 72 return new \WP_REST_Response(['success' => false, 'data' => ['message' => 'Could not generate link']], 500); 73 } 74 return new \WP_REST_Response(['success' => true, 'data' => ['type' => self::OK, 'method' => 'link', 'link' => $link]]); 75 } 76 77 /** 78 * --- NEW: SERVER-SIDE VALIDATION FOR BLOCK CHECKOUT --- 79 * Hooks into the native block process to add a validation error. 80 */ 81 public function validate_block_checkout($data, $errors) { 82 $email = isset($data['billing_address']['email']) ? sanitize_email($data['billing_address']['email']) : ''; 83 $payment_method = isset($data['payment_method']) ? sanitize_text_field($data['payment_method']) : ''; 84 85 if (!$this->is_verification_complete($email, $payment_method)) { 86 $errors->add('ts_verification_required', __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification')); 87 } 88 } 89 90 /** 91 * --- RENAMED: SERVER-SIDE VALIDATION FOR CLASSIC CHECKOUT --- 92 * Includes a "run-once" guard to prevent duplicate errors. 93 */ 94 public function validate_classic_checkout($fields, $errors) { 95 static $has_run = false; 96 if ($has_run) { 97 return; 98 } 99 $has_run = true; 100 101 $email = isset($fields['billing_email']) ? sanitize_email($fields['billing_email']) : ''; 102 $payment_method = isset($fields['payment_method']) ? sanitize_text_field($fields['payment_method']) : ''; 103 104 if (!$this->is_verification_complete($email, $payment_method)) { 105 $errors->add('validation', __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification')); 106 } 107 } 108 109 /** 110 * --- NEW: CENTRALIZED VALIDATION LOGIC --- 111 * A single function to check if verification is complete. 112 * Returns true if verification is complete or not required. 113 * Returns false if verification is required and not complete. 114 */ 115 private function is_verification_complete($email, $payment_method) { 116 if (ts_get_option('verify_on', self::VERIFY_BEFORE_CHECKOUT) !== self::VERIFY_BEFORE_CHECKOUT) { 117 return true; 118 } 119 if (!self::shouldVerifyBeforeCheckout($payment_method)) { 120 return true; 121 } 122 if (is_user_logged_in()) { 123 return ts_is_user_verified(get_current_user_id()); 124 } 125 if (ts_get_option('allow_guest_checkout_verify') && !empty($email)) { 126 $user = $this->tryFindUser($email); 127 return ($user && !empty($user['is_verified'])); 128 } 129 // If guest checkout is disabled and user is not logged in, fail open (let WooCommerce handle it) 130 if (!ts_get_option('allow_guest_checkout_verify')) { 131 return true; 132 } 133 // If guest but no email, it's not complete 134 return false; 135 } 136 137 138 public function verifyVerification_forBlocks() { 139 check_ajax_referer('ts_action', 'nonce'); 140 141 $response = ['message' => '']; 142 $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; 143 $payment_method = isset($_POST['payment_method']) ? sanitize_text_field($_POST['payment_method']) : ''; 144 145 if (ts_get_option('verify_on', self::VERIFY_BEFORE_CHECKOUT) !== self::VERIFY_BEFORE_CHECKOUT || !self::shouldVerifyBeforeCheckout($payment_method)) { 146 wp_send_json($response); 147 return; 148 } 149 150 $is_verified = false; 151 if (is_user_logged_in()) { 152 $is_verified = ts_is_user_verified(get_current_user_id()); 153 } elseif (ts_get_option('allow_guest_checkout_verify') && !empty($email)) { 154 $user = $this->tryFindUser($email); 155 $is_verified = ($user && !empty($user['is_verified'])); 156 } 157 158 if (!$is_verified) { 159 $response['message'] = __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification'); 160 } 161 162 wp_send_json($response); 163 } 164 165 // --- NOTE: THE DUPLICATED CODE BLOCK THAT WAS HERE HAS BEEN REMOVED TO FIX THE PARSE ERROR --- 166 73 167 function refresh_payment_methods(){ 74 168 $loadScripts = Verification::shouldVerifyBeforeCheckoutAtAssets(); 75 169 if ($loadScripts){ 76 $chosen_payment_method = WC()->session->get('chosen_payment_method');77 $applicableMethodsData=ts_get_option('applicable_payment_methods');78 170 ?> 79 171 <script type="text/javascript"> 80 var j_method = <?='"'. $chosen_payment_method .'"'?>;81 var availableArray = <?= json_encode($applicableMethodsData) ?>;82 172 (function($){ 83 $( 'form.checkout' ).on( 'change', 'input[name^="payment_method"]', function(event) { 173 function handlePaymentMethodChange() { 174 if (typeof TSCheckoutConfig === 'undefined') { 175 return; 176 } 84 177 var payment_method = $('form.checkout').find('input[name^="payment_method"]:checked').val(); 85 if(jQuery.inArray(payment_method, availableArray) !== -1)86 {178 var applicableMethods = TSCheckoutConfig.applicable_payment_methods || []; 179 if(applicableMethods.length === 0 || $.inArray(payment_method, applicableMethods) !== -1) { 87 180 TSCheckoutConfig.payment_method = payment_method; 88 window.TSVerification.init(); 89 }else{ 90 window.TSVerification.hideIt(); 181 if (window.TSVerification && typeof window.TSVerification.showIt === 'function') { 182 window.TSVerification.showIt(); 183 window.TSVerification.verifyUser($('#billing_email').val()); 184 } 185 } else { 186 if (window.TSVerification && typeof window.TSVerification.hideIt === 'function') { 187 window.TSVerification.hideIt(); 188 } 91 189 } 92 //set new value 93 j_method = $('form.checkout').find('input[name^="payment_method"]:checked').val(); 190 } 191 $(document).ready(function() { 192 $('form.checkout').on('change', 'input[name^="payment_method"]', handlePaymentMethodChange); 193 handlePaymentMethodChange(); 94 194 }); 95 195 })(jQuery); … … 104 204 $order = wc_get_order($post->ID); 105 205 $user = $order->get_user(); 206 if (!$user) { 207 echo "Guest"; 208 return; 209 } 106 210 $tsUserId = get_user_meta($user->ID, '_trust_user_id', true); 107 108 211 if (!$tsUserId) { 109 212 echo "Unknown"; 110 } 111 112 $url = $this->getTSUserShowUrl($tsUserId); 113 if (!$url) { 114 echo "Unknown"; 115 } 116 213 return; 214 } 117 215 $isVerified = ts_is_user_verified($user->ID); 118 119 if ($isVerified) { 120 echo "Verified"; 121 } else { 122 echo "Unverified"; 123 } 124 } 125 216 echo $isVerified ? "Verified" : "Unverified"; 217 } 126 218 } 127 219 128 220 public function ts_add_new_order_admin_list_column($columns){ 129 221 $reordered_columns = array(); 130 // Inserting columns to a specific location131 222 foreach( $columns as $key => $column){ 132 223 $reordered_columns[$key] = $column; 133 224 if( $key == 'order_status' ){ 134 // Inserting after "Status" column135 225 $reordered_columns['ts_verify_status'] = 'Verify Status'; 136 226 } … … 138 228 return $reordered_columns; 139 229 } 230 140 231 public function add_query_vars_filter( $vars ){ 141 232 $vars[] = "is_verified"; 142 233 return $vars; 143 234 } 144 public function verifyVerification_forBlocks(){ 145 $aAnswer = ['not_verified'=>0,'skip'=>0,'message'=>'']; 146 $email = sanitize_text_field($_POST['email']); 235 236 /** 237 * --- CORRECTED & FINAL --- 238 * This hook now ONLY handles validation for the Classic Checkout. 239 * It includes a "run-once" guard to prevent duplicate errors caused by themes or other plugins. 240 * It also explicitly ignores Block Checkout submissions. 241 */ 242 public function verifyVerification($fields, $errors) 243 { 244 // --- FIX: START --- 245 // "Run-once" guard. This prevents the function from executing more than once per request, 246 // solving the duplicate error issue on Classic Checkout. 247 static $has_run = false; 248 if ($has_run) { 249 return $errors; 250 } 251 $has_run = true; 147 252 148 $payment_method = sanitize_text_field($_POST['payment_method'] ); 253 // This "firewall" prevents this function from ever running during a Block Checkout submission. 254 if (function_exists('wc_is_rest_api_request') && wc_is_rest_api_request('wc/store/v1')) { 255 return $errors; 256 } 257 // --- FIX: END --- 149 258 150 259 if (!ts_get_option('allow_guest_checkout_verify') && !is_user_logged_in()) { 151 $aAnswer['skip'] = 2;152 }153 $verifyAfterCheckout = ts_get_option('verify_on', static::VERIFY_BEFORE_CHECKOUT) == static::VERIFY_AFTER_CHECKOUT;154 if ($verifyAfterCheckout){155 $aAnswer['skip'] = 3;156 }157 158 if (is_user_logged_in()) {159 160 $user = wp_get_current_user();161 $isVerified = ts_is_user_verified($user->ID);162 // $isVerified = true;163 164 if (!$isVerified) {165 if (self::shouldVerifyBeforeCheckout($payment_method)) {166 $aAnswer['message'] = __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification');167 } else {168 $aAnswer['skip'] = 4;169 }170 }171 }else if (ts_get_option('allow_guest_checkout_verify') && ($email)){172 if($email){173 $user = $this->tryFindUser($email);174 }175 176 if ($user){177 $isVerified = ts_array_get($user, 'is_verified', false);178 if (!$isVerified) {179 180 if (self::shouldVerifyBeforeCheckout($payment_method)) {181 $aAnswer['message'] = __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification');182 } else {183 $aAnswer['skip'] = 1;184 }185 186 }187 }188 }189 $aJSONAnswer = json_encode($aAnswer);190 header('Content-type: application/json');191 echo($aJSONAnswer);192 die();193 }194 public function verifyVerification($fields, $errors)195 {196 if (!ts_get_option('allow_guest_checkout_verify') && !is_user_logged_in()) {197 260 return $errors; 198 261 } 199 $verifyAfterCheckout = ts_get_option('verify_on', static::VERIFY_BEFORE_CHECKOUT) == static::VERIFY_AFTER_CHECKOUT; 200 if ($verifyAfterCheckout){ 262 if (ts_get_option('verify_on', static::VERIFY_BEFORE_CHECKOUT) == static::VERIFY_AFTER_CHECKOUT){ 201 263 return $errors; 202 264 } 265 203 266 if (is_user_logged_in()) { 204 267 $user = wp_get_current_user(); 205 $isVerified = ts_is_user_verified($user->ID); 206 207 if (!$isVerified) { 208 if (self::shouldVerifyBeforeCheckout()) { 209 $errors->add( 210 'validation', 211 __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification') 212 ); 213 } else { 214 return $errors; 268 if (!ts_is_user_verified($user->ID) && self::shouldVerifyBeforeCheckout()) { 269 $errors->add('validation', __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification')); 270 } 271 } else if (ts_get_option('allow_guest_checkout_verify') && !empty($fields['billing_email'])) { 272 $user = $this->tryFindUser($fields['billing_email']); 273 if ($user) { 274 if (empty($user['is_verified']) && self::shouldVerifyBeforeCheckout()) { 275 $errors->add('validation', __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification')); 215 276 } 216 277 } 217 }else if (ts_get_option('allow_guest_checkout_verify') && ($fields['billing_email'] || $fields['email'])){218 if($fields['email']){219 $user = $this->tryFindUser($fields['email']);220 }221 if($fields['billing_email']){222 $user = $this->tryFindUser($fields['billing_email']);223 }224 225 if ($user){226 $isVerified = $user['is_verified'];227 if (!$isVerified) {228 if (self::shouldVerifyBeforeCheckout()) {229 $errors->add(230 'validation',231 __('Please complete the verification requirements by clicking the 🛡️ Trust Swiftly button prior to paying', 'trustswiftly-verification')232 );233 } else {234 return $errors;235 }236 }237 }238 239 278 } 240 279 … … 250 289 } 251 290 $tsUserId = get_user_meta($user->ID, '_trust_user_id', true); 252 253 291 if (! $tsUserId) { 254 292 return; 255 293 } 256 257 294 $url = $this->getTSUserShowUrl($tsUserId); 258 295 if (! $url) { 259 296 return; 260 297 } 261 262 298 $msg = __('View User', 'trustswiftly-verifications'); 263 299 $isVerified = ts_is_user_verified($user->ID); 264 265 300 printf( 266 301 '<h3>%s</h3><a href="%s" target="_blank">%s</a> - %s', … … 271 306 ); 272 307 } 308 273 309 protected function CreateTheUserIfNotExists($orderId){ 274 310 if(!is_user_logged_in()){ … … 285 321 $order->set_customer_id($userId); 286 322 $order->save(); 287 288 323 }else{ 289 324 if(empty($order->get_user_id())){ … … 306 341 } 307 342 } 308 309 }310 } 343 } 344 } 345 311 346 public function maybeRenderVerification($orderId) 312 347 { 313 $verifyAfterCheckout = ts_get_option('verify_on', static::VERIFY_BEFORE_CHECKOUT) == static::VERIFY_AFTER_CHECKOUT; 314 if (! $verifyAfterCheckout) { 348 if (ts_get_option('verify_on', static::VERIFY_BEFORE_CHECKOUT) == static::VERIFY_BEFORE_CHECKOUT) { 315 349 $this->CreateTheUserIfNotExists($orderId); 316 350 return; … … 319 353 return; 320 354 } 321 322 355 if (! static::shouldVerifyAfterCheckout($orderId)) { 323 356 return; 324 357 } 325 if(!is_user_logged_in()){ 326 $order = wc_get_order($orderId); 358 $order = wc_get_order($orderId); 359 $user = $order->get_user(); 360 if (!$user) { 327 361 $email = $order->get_billing_email(); 328 $userId = email_exists($email); 329 if(empty($userId )){ 330 $username = sanitize_user(current(explode('@', $email)), true); 362 $user_id = $order->get_customer_id(); 363 if ($user_id === 0) { 364 $user_id = email_exists($email); 365 } 366 if (!$user_id) { 367 $username = sanitize_user(current(explode('@', $email)), true); 331 368 if (username_exists($username)) { 332 $username = $username .'_' . wp_generate_password(4, false, false);369 $username .= '_' . wp_generate_password(4, false, false); 333 370 } 334 371 $password = wp_generate_password(); 335 $user Id = wp_create_user($username, $password, $email);336 $order->set_customer_id($user Id);372 $user_id = wp_create_user($username, $password, $email); 373 $order->set_customer_id($user_id); 337 374 $order->save(); 338 339 } 340 $user = get_user_by( 'id', $userId ); 341 if(isset($user->data)){ 342 $user = $user->data; 343 } 344 }else{ 345 $user = wp_get_current_user(); 346 } 347 375 } 376 $user = get_user_by('id', $user_id); 377 } 378 if (!$user) { return; } 379 348 380 $isUserAlreadyVerified = ts_is_user_verified($user->ID); 349 350 381 if ($isUserAlreadyVerified) { 351 echo ts_render('post-order-verification.php', [ 352 'btnImg' => TrustVerifyPlugin::pluginUrl() . 'assets/img/' . ts_get_option('btn_img', Settings::defaultBtnImg()), 353 'isVerified' => true, 354 'link' => null 355 ]); 356 357 return; 358 } 359 360 $trustUserId = get_user_meta($user->ID, '_trust_user_id', true); 361 $trustEmbedUserId = get_user_meta($user->ID, '_trust_embed_user_id', true); 362 if (! $trustUserId || !$trustEmbedUserId) { 363 $userId = $this->createOrFindTsUser($user->ID, $user->user_email); 364 365 if (! $userId) { 366 return; 367 } 368 369 $trustUserId = $userId[0]; 370 $trustEmbedUserId = $userId[1]; 371 if ($trustUserId) { 372 update_user_meta($user->ID, '_trust_user_id', $trustUserId); 373 } 374 if ($trustEmbedUserId) { 375 update_user_meta($user->ID, '_trust_embed_user_id', $trustEmbedUserId); 376 } 377 } 378 382 echo ts_render('post-order-verification.php', ['isVerified' => true]); 383 return; 384 } 385 $userIds = $this->createOrFindTsUser($user->ID, $user->user_email); 386 if (!$userIds) { return; } 387 $trustUserId = $userIds[0]; 388 $trustEmbedUserId = $userIds[1]; 389 update_user_meta($user->ID, '_trust_user_id', $trustUserId); 390 update_user_meta($user->ID, '_trust_embed_user_id', $trustEmbedUserId); 379 391 $this->updateOrderId($trustUserId, $orderId); 380 381 392 $link = $this->getMagicLink($trustUserId); 382 383 393 echo ts_render('post-order-verification.php', [ 384 'btnImg' => TrustVerifyPlugin::pluginUrl() . 'assets/img/' . ts_get_option('btn_img', Settings::defaultBtnImg()),385 394 'isVerified' => false, 386 395 'link' => $link, 387 'user_email' =>$user->user_email396 'user_email' => $user->user_email 388 397 ]); 389 398 } 390 399 391 public function checkUserVerification(){392 393 $user = wp_get_current_user();394 395 $isUserAlreadyVerified = ts_is_user_verified($user->ID);396 397 if ($isUserAlreadyVerified) {398 return wp_send_json_success([399 'is_verified' => 1,400 ]);401 }402 403 return wp_send_json_success([404 'is_verified' => 0,405 ]);406 }407 408 400 public function getUserVerification() 409 401 { 410 402 check_ajax_referer('ts_action', 'nonce'); 411 412 403 $email = sanitize_email(ts_array_get($_POST, 'email')); 413 $thank_you_page = sanitize_text_field(ts_array_get($_POST, 'thank_you_page')); 414 415 if (! $email) { 416 return wp_send_json_error([ 417 'message' => __('Email is required'. 'trustswiftly-verification') 418 ]); 419 } 420 421 $paymentMethod = sanitize_text_field(ts_array_get($_POST, 'payment_method')); 422 423 if ($thank_you_page!=="1") { 424 if ($paymentMethod!=="unknown") { 425 if (!static::shouldVerifyBeforeCheckout($paymentMethod)) { 426 return wp_send_json_error(); 427 } 428 }else{ 429 if (!static::shouldVerifyBeforeCheckout()) { 430 return wp_send_json_error(); 431 } 432 } 433 } 434 404 if (!$email) { 405 wp_send_json_error(['message' => __('Email is required', 'trustswiftly-verification')]); 406 } 407 if (ts_array_get($_POST, 'thank_you_page') !== "1") { 408 $paymentMethod = sanitize_text_field(ts_array_get($_POST, 'payment_method')); 409 if (!static::shouldVerifyBeforeCheckout($paymentMethod)) { 410 wp_send_json_error(); 411 } 412 } 435 413 if (is_user_logged_in()) { 436 437 414 $user = wp_get_current_user(); 438 $trustUserId = null; 439 $isUserAlreadyVerified = ts_is_user_verified($user->ID); 440 441 if ($isUserAlreadyVerified) { 442 return wp_send_json_success([ 443 'type' => static::USER_ALREADY_VERIFIED, 444 ]); 445 } 446 447 $trustUserId = get_user_meta($user->ID, '_trust_user_id', true); 448 $trustEmbedUserId = get_user_meta($user->ID, '_trust_embed_user_id', true); 449 /*check whether the user exists to prevent exclusion when the user is deleted from the portal*/ 450 if(!empty($trustUserId)&&!$this->isUserExists($trustUserId)){ 451 $trustUserId = 0; 452 $trustEmbedUserId = 0; 453 update_user_meta($user->ID, '_trust_user_id', 0); 454 update_user_meta($user->ID, '_trust_embed_user_id', 0); 455 } 456 457 if (! $trustUserId || ! $trustEmbedUserId) { 458 459 $userId = $this->createOrFindTsUser($user->ID, $email); 460 if (! $userId) { 461 return wp_send_json_error([ 462 'message' => __('Error occurred', 'trustswiftly-verification') 463 ]); 464 } 465 466 $trustUserId = $userId[0]; 467 $trustEmbedUserId = $userId[1]; 468 469 if ($trustUserId) { 470 update_user_meta($user->ID, '_trust_user_id', $trustUserId); 471 } 472 if ($trustEmbedUserId) { 473 update_user_meta($user->ID, '_trust_embed_user_id', $trustEmbedUserId); 474 } 475 if (isset($userId[2]) && $userId[2]) { 476 $alreadyVerified = ts_array_get($userId[2], 'is_verified', false); 477 if ($alreadyVerified) { 478 return wp_send_json_success([ 479 'type' => static::USER_ALREADY_VERIFIED, 480 ]); 481 } 482 } 483 }else{ 484 $tsUser = $this->tryFindUser($email); 485 $isUserAlreadyVerified = $tsUser ? ts_array_get($tsUser, 'is_verified', false) : false; 486 if ($isUserAlreadyVerified) { 487 return wp_send_json_success([ 488 'type' => static::USER_ALREADY_VERIFIED, 489 ]); 490 } 491 } 492 } else if (ts_get_option('allow_guest_checkout_verify')) { 415 if (ts_is_user_verified($user->ID)) { 416 wp_send_json_success(['type' => static::USER_ALREADY_VERIFIED]); 417 } 418 $userIds = $this->createOrFindTsUser($user->ID, $email); 419 if (!$userIds) { wp_send_json_error(['message' => 'API Error']); } 420 $trustUserId = $userIds[0]; 421 update_user_meta($user->ID, '_trust_user_id', $trustUserId); 422 } elseif (ts_get_option('allow_guest_checkout_verify')) { 493 423 $tsUser = $this->tryFindUser($email); 494 $isUserAlreadyVerified = $tsUser ? ts_array_get($tsUser, 'is_verified', false) : false; 495 // echo '<pre>'; 496 // var_dump($isUserAlreadyVerified); 497 // die; 498 if ($isUserAlreadyVerified) { 499 return wp_send_json_success([ 500 'type' => static::USER_ALREADY_VERIFIED, 501 ]); 424 if ($tsUser && !empty($tsUser['is_verified'])) { 425 wp_send_json_success(['type' => static::USER_ALREADY_VERIFIED]); 502 426 } 503 427 $userIds = $this->createOrFindTsUser(null, $email); 504 if (! $userIds) { 505 return wp_send_json_error([ 506 'message' => __('Error occurred', 'trustswiftly-verification') 507 ]); 508 } 509 428 if (!$userIds) { wp_send_json_error(['message' => 'API Error']); } 510 429 $trustUserId = $userIds[0]; 511 $trustEmbedUserId = $userIds[1]; 512 513 }else{ 514 return wp_send_json_error(); 515 } 516 430 } else { 431 wp_send_json_error(); 432 } 517 433 $link = $this->getMagicLink($trustUserId); 518 519 return wp_send_json_success([ 520 'ts_user_id' => $trustUserId, 521 'ts_embed_user_id' => $trustEmbedUserId, 522 'method' => 'link', 523 'type' => static::OK, 524 // 'type' => static::USER_ALREADY_VERIFIED, 525 'link' => $link 526 ]); 434 wp_send_json_success(['ts_user_id' => $trustUserId, 'method' => 'link', 'type' => static::OK, 'link' => $link]); 527 435 } 528 436 … … 538 446 return false; 539 447 } 540 $params = [ 541 'email' => $email, 542 'template_id' => ts_get_option('template_id', Settings::getDefaultTemplateId()), 543 'reference_id' => $userId 544 ]; 448 $params = ['email' => $email, 'template_id' => ts_get_option('template_id', Settings::getDefaultTemplateId()), 'reference_id' => $userId]; 545 449 if (ts_get_option('send_verify_link',false)){ 546 450 $params['send_link']=true; 547 451 } 548 549 452 $response = $api->userClient()->createUser($params); 550 551 453 if (! $response instanceof UserCreateResponse || ts_array_get($response->createArray, 'status') !== 'success') { 552 454 return false; 553 455 } 554 555 456 $userId = ts_array_get($response->createArray, 'id'); 556 457 $embedUserId = ts_array_get($response->createArray, 'user_id'); 557 558 458 return [$userId, $embedUserId,null]; 559 560 459 } catch (ApiException $e) { 561 562 460 return null; 563 461 } 564 462 } 463 565 464 public function isUserExists($user_id){ 566 465 $api = ts_api(); 567 466 return $api->userClient()->isUserExists($user_id); 568 467 } 468 569 469 public function getMagicLink($userId) 570 470 { … … 572 472 try { 573 473 $link = $api->userClient()->getMagicLink($userId); 574 if (! $link instanceof UserMagicLinkResponse) { 575 return null; 576 } 577 474 if (! $link instanceof UserMagicLinkResponse) { return null; } 578 475 return $link->magicArray['full_url']; 579 476 } catch (ApiException $e) { … … 585 482 { 586 483 $api = ts_api(); 587 588 $users = $api->userClient()->getAllUsers([ 589 'filter' => [ 590 // 'search' => $email 591 'email' => $email 592 ] 593 ]); 594 // return ts_array_get($users, 'data', 0); 484 $users = $api->userClient()->getAllUsers(['filter' => ['email' => $email]]); 595 485 return ts_array_get($users['data'], 0); 596 486 } … … 599 489 { 600 490 $baseUrl = ts_get_option('base_url'); 601 if (! $baseUrl) { 602 return ''; 603 } 604 605 $baseUrl = untrailingslashit($baseUrl) . "/user/{$tsUserId}/show"; 606 607 return $baseUrl; 491 if (! $baseUrl) { return ''; } 492 return untrailingslashit($baseUrl) . "/user/{$tsUserId}/show"; 608 493 } 609 494 610 495 public static function shouldVerifyBeforeCheckoutAtAssets(){ 611 $verifyBeforeCheckout = ts_get_option('verify_on', Verification::VERIFY_BEFORE_CHECKOUT) == Verification::VERIFY_BEFORE_CHECKOUT; 612 613 if (! $verifyBeforeCheckout) { 496 if (ts_get_option('verify_on', Verification::VERIFY_BEFORE_CHECKOUT) !== Verification::VERIFY_BEFORE_CHECKOUT) { 614 497 return false; 615 498 } 616 617 499 $categories = (array)ts_get_option('product_categories', []); 618 500 $comparePriceMode = ts_get_option('compare_price_mode'); 619 501 $comparePrice = ts_get_option('compare_price'); 620 502 $isPriceChecked = true; 621 622 if ($comparePriceMode && $comparePrice>0) { 503 if ($comparePriceMode && $comparePrice > 0 && function_exists('WC') && WC()->cart) { 623 504 $cartTotalPrice = (double) WC()->cart->get_total('edit'); 624 505 $comparePrice = doubleval($comparePrice); 625 $isPriceChecked = false; 626 627 if ($comparePriceMode == 'less_than') { 628 $isPriceChecked = $comparePrice > $cartTotalPrice; 629 } 630 else { 631 $isPriceChecked = $comparePrice < $cartTotalPrice; 632 } 633 } 634 635 return (empty($categories) || ts_cart_has_products_in_categories($categories)) 636 && $isPriceChecked 637 ; 638 } 639 640 public static function shouldVerifyBeforeCheckout($paymentMethod = null) 641 { 642 $verifyBeforeCheckout = ts_get_option('verify_on', Verification::VERIFY_BEFORE_CHECKOUT) == Verification::VERIFY_BEFORE_CHECKOUT; 643 644 if (! $verifyBeforeCheckout) { 506 $isPriceChecked = ($comparePriceMode == 'less_than') ? ($comparePrice > $cartTotalPrice) : ($comparePrice < $cartTotalPrice); 507 } 508 return (empty($categories) || ts_cart_has_products_in_categories($categories)) && $isPriceChecked; 509 } 510 511 public static function shouldVerifyBeforeCheckout($paymentMethod = null) 512 { 513 if (ts_get_option('verify_on', self::VERIFY_BEFORE_CHECKOUT) !== self::VERIFY_BEFORE_CHECKOUT) { 514 return false; 515 } 516 $applicableMethods = (array) ts_get_option('applicable_payment_methods', []); 517 if (!empty($applicableMethods) && function_exists('WC')) { 518 519 // --- THIS IS THE CRITICAL FIX FOR STATELESS VALIDATION --- 520 $chosen_payment_method = $paymentMethod; // Rely ONLY on the passed-in argument. 521 522 if (!$chosen_payment_method || !in_array($chosen_payment_method, $applicableMethods)) { 645 523 return false; 646 524 } 647 648 $categories = (array)ts_get_option('product_categories', []); 525 } 526 $categories = (array) ts_get_option('product_categories', []); 527 if (!empty($categories) && function_exists('ts_cart_has_products_in_categories') && !ts_cart_has_products_in_categories($categories)) { 528 return false; 529 } 530 $comparePriceMode = ts_get_option('compare_price_mode'); 531 $comparePrice = ts_get_option('compare_price'); 532 if ($comparePriceMode && !empty($comparePrice) && $comparePrice > 0 && function_exists('WC') && WC()->cart) { 533 $cartTotalPrice = (double) WC()->cart->get_total('edit'); 534 $comparePrice = doubleval($comparePrice); 535 if (($comparePriceMode == 'less_than' && $cartTotalPrice >= $comparePrice) || ($comparePriceMode == 'more_than' && $cartTotalPrice <= $comparePrice)) { 536 return false; 537 } 538 } 539 return true; 540 } 541 542 public static function shouldVerifyAfterCheckout($orderId) 543 { 544 if (ts_get_option('verify_on', Verification::VERIFY_AFTER_CHECKOUT) !== Verification::VERIFY_AFTER_CHECKOUT) { 545 return false; 546 } 547 $order = wc_get_order($orderId); 548 if (! $order) { return false; } 549 $orderPaymentMethod = $order->get_payment_method(); 550 $applicableMethodsData=ts_get_option('applicable_payment_methods'); 551 $paymentMethodRestrictionFlag = !($applicableMethodsData && count($applicableMethodsData)>0 && !in_array($orderPaymentMethod,$applicableMethodsData)); 649 552 $comparePriceMode = ts_get_option('compare_price_mode'); 650 553 $comparePrice = ts_get_option('compare_price'); 651 554 $isPriceChecked = true; 652 $applicableMethodsData=ts_get_option('applicable_payment_methods'); 653 if ($paymentMethod!==null){ 654 $chosen_payment_method = $paymentMethod; 655 }else{ 656 $chosen_payment_method = WC()->session->get('chosen_payment_method'); 657 } 658 659 $paymentMethodRestrictionFlag = true; 660 661 if ($applicableMethodsData && count($applicableMethodsData)>0 && !in_array($chosen_payment_method,$applicableMethodsData)) 662 { 663 664 $paymentMethodRestrictionFlag = false; 665 } 666 667 if ($comparePriceMode && $comparePrice>0) { 668 $cartTotalPrice = (double) WC()->cart->get_total('edit'); 669 $comparePrice = doubleval($comparePrice); 670 $isPriceChecked = false; 671 672 if ($comparePriceMode == 'less_than') { 673 $isPriceChecked = $comparePrice > $cartTotalPrice; 674 } 675 else { 676 $isPriceChecked = $comparePrice < $cartTotalPrice; 677 } 678 } 679 680 return (empty($categories) || ts_cart_has_products_in_categories($categories)) 681 && $isPriceChecked && $paymentMethodRestrictionFlag 682 ; 683 } 684 685 public static function shouldVerifyAfterCheckout($orderId) 686 { 687 $verifyAfterCheckout = ts_get_option('verify_on', Verification::VERIFY_AFTER_CHECKOUT) == Verification::VERIFY_AFTER_CHECKOUT; 688 689 if (! $verifyAfterCheckout) { 690 return false; 691 } 692 693 $order = wc_get_order($orderId); 694 if (! $order) { 695 return false; 696 } 697 698 $orderPaymentMethod = $order->get_payment_method(); 699 $applicableMethodsData=ts_get_option('applicable_payment_methods'); 700 701 $paymentMethodRestrictionFlag = true; 702 703 if ($applicableMethodsData && count($applicableMethodsData)>0 && !in_array($orderPaymentMethod,$applicableMethodsData)) 704 { 705 $paymentMethodRestrictionFlag = false; 706 } 707 708 $comparePriceMode = ts_get_option('compare_price_mode'); 709 $comparePrice = ts_get_option('compare_price'); 710 $isPriceChecked = true; 711 712 if ($comparePriceMode && $comparePrice>0) { 555 if ($comparePriceMode && $comparePrice > 0) { 713 556 $orderTotalPrice = (double) $order->get_total('edit'); 714 557 $comparePrice = doubleval($comparePrice); 715 $isPriceChecked = false; 716 717 if ($comparePriceMode == 'less_than') { 718 $isPriceChecked = $comparePrice > $orderTotalPrice; 719 } 720 else { 721 $isPriceChecked = $comparePrice < $orderTotalPrice; 722 } 723 } 724 558 $isPriceChecked = ($comparePriceMode == 'less_than') ? ($comparePrice > $orderTotalPrice) : ($comparePrice < $orderTotalPrice); 559 } 725 560 $categories = ts_get_option('product_categories', []); 726 727 return (empty($categories) || ts_order_has_products_in_categories($order, $categories)) 728 && $isPriceChecked && $paymentMethodRestrictionFlag 729 ; 561 return (empty($categories) || ts_order_has_products_in_categories($order, $categories)) && $isPriceChecked && $paymentMethodRestrictionFlag; 730 562 } 731 563 … … 733 565 { 734 566 $api = ts_api(); 735 736 567 try { 737 $response = $api->userClient()->updateUser($userId, [ 738 'order_id' => $orderId 739 ]); 740 568 $api->userClient()->updateUser($userId, ['order_id' => $orderId]); 741 569 return true; 742 } 743 catch (ApiException $e) { 570 } catch (ApiException $e) { 744 571 return false; 745 572 } -
trust-swiftly-verification/trunk/trustswiftly-verification.php
r3238884 r3320256 9 9 * Author: Trust Swiftly 10 10 * Author URI: https://www.trustswiftly.com 11 * Version: 1.1.1 312 * Text Domain: Trust Swiftly Verification11 * Version: 1.1.14 12 * Text Domain: trust-swiftly-verification 13 13 */ 14 14 … … 19 19 exit; 20 20 } 21 22 // Define a constant for the main plugin file path. 23 // This is crucial for other parts of the plugin, like WooCommerce block compatibility. 24 if ( ! defined( 'TS_PLUGIN_BASE_PATH' ) ) { 25 define( 'TS_PLUGIN_BASE_PATH', __FILE__ ); 26 } 27 28 if ( ! defined( 'TS_PLUGIN_VERSION' ) ) { 29 define( 'TS_PLUGIN_VERSION', '1.1.14' ); // Make sure this matches the version in the header 30 } 21 31 require_once __DIR__ . '/bootstrap.php'; 22 32 23 $aPlugins = apply_filters( 'active_plugins', get_option( 'active_plugins' )); 24 if(empty($aPlugins)){ 25 $aPlugins = []; 33 /** 34 * Begins execution of the plugin. 35 * 36 * Load the plugin only after all other plugins are loaded to ensure compatibility. 37 */ 38 add_action( 39 'plugins_loaded', 40 function () { 41 new TrustVerifyPlugin(); 42 } 43 ); 44 45 register_activation_hook( __FILE__, array( 'TrustswiftlyVerification\TrustVerifyPlugin', 'activate' ) ); 46 47 /** 48 * Adds a settings link to the plugin's action links on the plugins page. 49 * 50 * @param array $links An array of plugin action links. 51 * @return array An array of plugin action links. 52 */ 53 function ts_add_plugin_page_settings_link( $links ) { 54 $links[] = '<a href="' . admin_url( 'admin.php?page=ts-settings' ) . '">' . __( 'Settings', 'trust-swiftly-verification' ) . '</a>'; 55 return $links; 26 56 } 27 if ( in_array( 'woocommerce/woocommerce.php', $aPlugins)&& file_exists(WP_PLUGIN_DIR.'/woocommerce/woocommerce.php') ) { 28 register_activation_hook(__FILE__, array('TrustswiftlyVerification\TrustVerifyPlugin', 'activate')); 29 new TrustVerifyPlugin(); 30 add_filter('plugin_action_links_'.plugin_basename(__FILE__), 'ts_add_plugin_page_settings_link'); 31 function ts_add_plugin_page_settings_link( $links ) { 32 $links[] = '<a href="' . 33 admin_url( 'admin.php?page=ts-settings' ) . 34 '">' . __('Settings') . '</a>'; 35 return $links; 36 } 37 } 57 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ts_add_plugin_page_settings_link' ); -
trust-swiftly-verification/trunk/views/post-order-verification.php
r2794742 r3320256 1 <?php 2 /** 3 * Template for displaying the verification UI on the "Thank You" (order confirmation) page. 4 * FINAL VERSION: This template now uses the REST API for verification checks, ensuring 5 * consistency with the main checkout page and correctly handling the "already verified" state. 6 */ 7 ?> 8 1 9 <?php if (! $isVerified): ?> 2 <p id="verify_div"> 3 <?php _e('Please verify your account: ', 'trustswiftly-verifications'); ?> 4 </p> 10 <div class="ts-verification-callout ts-pulse-animation" id="ts-thank-you-verification"> 11 <p class="ts-verification-message" id="ts-thank-you-message"> 12 <?php _e('Please complete the verification to process your order:', 'trust-swiftly-verification'); ?> 13 </p> 14 <div id="verify_div" class="ts-verification-button-wrapper"> 15 <!-- The verification UI will be injected here by JavaScript --> 16 </div> 17 </div> 5 18 <?php else: ?> 6 <p class="ts-verification-status"> 7 <img src="data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='96px' height='96px' viewBox='0 0 96 96' enable-background='new 0 0 96 96' xml:space='preserve'%3E%3Cg%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' fill='%236BBE66' d='M48,0c26.51,0,48,21.49,48,48S74.51,96,48,96S0,74.51,0,48 S21.49,0,48,0L48,0z M26.764,49.277c0.644-3.734,4.906-5.813,8.269-3.79c0.305,0.182,0.596,0.398,0.867,0.646l0.026,0.025 c1.509,1.446,3.2,2.951,4.876,4.443l1.438,1.291l17.063-17.898c1.019-1.067,1.764-1.757,3.293-2.101 c5.235-1.155,8.916,5.244,5.206,9.155L46.536,63.366c-2.003,2.137-5.583,2.332-7.736,0.291c-1.234-1.146-2.576-2.312-3.933-3.489 c-2.35-2.042-4.747-4.125-6.701-6.187C26.993,52.809,26.487,50.89,26.764,49.277L26.764,49.277z'/%3E%3C/g%3E%3C/svg%3E" alt="" width="30"> 8 <?php esc_html_e('Verifications Completed', 'trustswiftly-verification'); ?> 9 </p> 19 <div class="ts-verification-callout ts-verification-success"> 20 <p class="ts-verification-message"> 21 <img src="data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Cpath fill='%2328a745' d='M48,0c26.5,0,48,21.5,48,48s-21.5,48-48,48S0,74.5,0,48S21.5,0,48,0z M42.9,63.1l-16-16c-1.2-1.2-1.2-3.1,0-4.2s3.1-1.2,4.2,0l13.8,13.8l27.2-27.2c1.2-1.2,3.1-1.2,4.2,0s1.2,3.1,0,4.2L47.1,63.1C46.5,63.7,45.8,64,45,64S43.5,63.7,42.9,63.1z'/%3E%3C/svg%3E" alt="Success" width="24" style="vertical-align: middle; margin-right: 8px;"> 22 <?php esc_html_e('Verification Completed', 'trust-swiftly-verification'); ?> 23 </p> 24 </div> 10 25 <?php endif; ?> 11 <script> 12 (function($) { 13 // Custom code here 14 $(function () { 15 TSCheckoutConfig.user_email='<?php echo $user_email?>'; 16 window.TSVerification.init(); 26 27 <?php if (! $isVerified && ! empty($user_email)): ?> 28 <script type="text/javascript"> 29 (function($) { 30 $(document).ready(function() { 31 var userEmail = <?php echo wp_json_encode($user_email); ?>; 32 var $container = $('#ts-thank-you-verification'); 33 var $placeholder = $('#verify_div'); 34 var $message = $('#ts-thank-you-message'); 35 36 if (!userEmail || $container.length === 0) { 37 return; 38 } 39 40 var config = window.TSCheckoutConfig; 41 if (typeof config === 'undefined') { 42 console.error('Trust Swiftly: Config object not found on Thank You page.'); 43 return; 44 } 45 46 // --- FINAL FIX: Use the REST API for consistency --- 47 // This mirrors the logic from checkout.js to get a reliable status. 48 49 $placeholder.html('<div class="ts-verification-spinner" style="display: flex; justify-content: center; align-items: center;"><img src="/wp-includes/images/wpspin.gif" alt="Loading..." style="width: 20px; height: 20px;"></div>'); 50 51 $.ajax({ 52 url: config.rest_url, // Use the modern REST API URL 53 method: 'POST', 54 beforeSend: function(xhr) { 55 xhr.setRequestHeader('X-WP-Nonce', config.nonce); // Use the REST API nonce 56 }, 57 data: { 58 email: userEmail, 59 // Provide context; backend might not need it, but it's good practice 60 payment_method: 'thank_you_page' 61 } 62 }).done(function(resp) { 63 $placeholder.empty(); 64 65 if (resp.success) { 66 if (resp.data.type === 'user_already_verified') { 67 // CORRECTLY handle the "already verified" state. 68 $container.removeClass('ts-pulse-animation').addClass('ts-verification-success'); 69 $message.html('<img src="data:image/svg+xml,%3Csvg version=\'1.1\' xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 96 96\'%3E%3Cpath fill=\'%2328a745\' d=\'M48,0c26.5,0,48,21.5,48,48s-21.5,48-48,48S0,74.5,0,48S21.5,0,48,0z M42.9,63.1l-16-16c-1.2-1.2-1.2-3.1,0-4.2s3.1-1.2,4.2,0l13.8,13.8l27.2-27.2c1.2-1.2,3.1-1.2,4.2,0s1.2,3.1,0,4.2L47.1,63.1C46.5,63.7,45.8,64,45,64S43.5,63.7,42.9,63.1z\'/%3E%3C/svg%3E" alt="Success" width="24" style="vertical-align: middle; margin-right: 8px;"> <?php esc_html_e('Verification Completed', 'trust-swiftly-verification'); ?>'); 70 $placeholder.remove(); 71 72 } else if (resp.data.type === 'ok' && resp.data.link) { 73 // If verification is needed, show the button. 74 var $btn = $('<a>', { 75 id: 'ts-verify-link', 76 class: 'ts-verify-link', 77 target: '_blank', 78 href: resp.data.link 79 }).css({ 80 "background-image": "url(" + config.btn_img + ")", 81 "display": "block", 82 "background-repeat": "no-repeat", 83 "background-size": "contain", 84 "margin": "10px auto 0" 85 }); 86 $placeholder.append($btn); 87 88 } else { 89 $container.hide(); 90 } 91 } else { 92 // If the API call fails or says verification is not required for this option 93 $container.hide(); 94 } 95 }).fail(function() { 96 $placeholder.empty(); 97 $message.text('A server error occurred. Please try refreshing the page.'); 17 98 }); 18 })(jQuery); 99 }); 100 })(jQuery); 19 101 </script> 102 <?php endif; ?>
Note: See TracChangeset
for help on using the changeset viewer.