Your verification code is:
+${code}
+This code expires in 10 minutes. If you did not request this, you can ignore this email.
+`, + }) + + return NextResponse.json({ + success: true, + message: "If that email is valid, we sent a 6-digit code.", + }) + } catch (error) { + console.error("[STOREFRONT_OTP_REQUEST]", error) + return NextResponse.json({ message: "Internal Error" }, { status: 500 }) + } +} diff --git a/src/app/api/storefront-chat/otp/verify/route.ts b/src/app/api/storefront-chat/otp/verify/route.ts new file mode 100644 index 0000000..9ed41c7 --- /dev/null +++ b/src/app/api/storefront-chat/otp/verify/route.ts @@ -0,0 +1,121 @@ +import { NextResponse } from "next/server" +import { prisma } from "@/lib/prisma" +import { applyRateLimit } from "@/lib/rate-limit" +import { storefrontOtpVerifySchema } from "@/lib/api-schemas/public" +import { validationErrorResponse } from "@/lib/api-schemas/validate" +import { + hashStorefrontOtp, + STOREFRONT_SESSION_TTL_MS, +} from "@/lib/storefront-chat/otpCrypto" + +function normalizeShopDomain(input: string) { + return input + .trim() + .toLowerCase() + .replace(/^https?:\/\//i, "") + .replace(/\/$/, "") +} + +function shopVariants(cleanDomain: string) { + if (!cleanDomain) return [] + const v = new SetNo storefront chat messages yet.
diff --git a/src/app/storefront-chat/widget/page.tsx b/src/app/storefront-chat/widget/page.tsx index fb507bb..2b8b07f 100644 --- a/src/app/storefront-chat/widget/page.tsx +++ b/src/app/storefront-chat/widget/page.tsx @@ -1,7 +1,7 @@ "use client" import { useEffect, useRef, useState } from "react" -import { MessageSquare, Send } from "lucide-react" +import { Send } from "lucide-react" type WidgetMessage = { id: string @@ -34,6 +34,13 @@ export default function StorefrontChatWidgetPage() { const [sendError, setSendError] = useState+ For order status and account-specific questions, enter the email you used + at checkout. We'll send a one-time code. +
+ setVerifyEmail(e.target.value)} + placeholder="you@example.com" + className="w-full border border-slate-200 rounded-lg px-2 py-1.5 text-sm" + /> +{otpMessage}
+ ) : null} + {sessionUntil ? ( ++ Session active until {new Date(sessionUntil).toLocaleString()} +
+ ) : null} ++ Extended policy fields (AI automation) +
++ Optional detailed answers mapped to support playbooks. Same + fields can power multiple modules. +
+