Shopify客户账号创建与认证流程技术咨询
Shopify客户账号认证问题解决方案
一、Legacy模式下添加邮箱验证逻辑
当前你的customerCreate mutation创建账号后直接激活,是因为Legacy模式默认不强制邮箱验证。要实现邮箱验证后激活,需按以下步骤调整:
1. 店铺后台开启邮箱验证
进入Shopify后台的设置 > 客户账户 > 账户验证,勾选「要求客户验证邮箱地址」。开启后,创建账号时Shopify会自动发送验证邮件,客户点击链接后账号才会正式激活。
2. 代码层面适配未验证状态
首先在你的customerCreate mutation中添加emailVerified字段,用于判断账号是否已验证:
/// Mutation to create a customer with email verification status const String customerCreateMutation = r''' mutation MyMutation($firstName: String, $lastName: String, $email: String!, $password: String!, $acceptsMarketing: Boolean, $phone: String) { customerCreate(input: {firstName: $firstName, lastName: $lastName, email: $email, password: $password, acceptsMarketing: $acceptsMarketing, phone: $phone}) { customer{ acceptsMarketing emailVerified # 添加字段判断邮箱是否验证 addresses(first: 10) { edges { node { address1 address2 city company country countryCodeV2 firstName id lastName latitude longitude name phone province provinceCode zip } } } createdAt defaultAddress { address1 address2 city company country countryCodeV2 firstName id lastName latitude longitude name phone province zip provinceCode } tags displayName email firstName id lastName phone } customerUserErrors { code field message } } } ''';
然后调整createUserWithEmailAndPassword方法,拦截未验证的账号,禁止直接获取token:
Future<void> createUserWithEmailAndPassword({ required String email, required String password, String? phone, String? firstName, String? lastName, bool? acceptsMarketing, }) async { final MutationOptions _options = MutationOptions( document: gql(customerCreateMutation), variables: { 'firstName': firstName, 'lastName': lastName, 'email': email, 'password': password, 'acceptsMarketing': acceptsMarketing ?? false, 'phone': phone, }, ); final QueryResult result = await _graphQLClient!.mutate(_options); checkForError( result, key: 'customerCreate', errorKey: 'customerUserErrors', ); final customerData = (result.data!['customerCreate'] ?? const {})['customer']; final isEmailVerified = customerData['emailVerified'] ?? false; if (!isEmailVerified) { // 提示用户查收邮箱验证链接,此时账号未激活,不执行后续token操作 throw Exception('请查收邮箱完成验证后再登录'); } // 验证通过后再获取token并保存用户信息 final shopifyUser = ShopifyUser.fromGraphJson(customerData); final AccessTokenWithExpDate accessTokenWithExpDate = await _createAccessToken(email, password); await _setShopifyUser(accessTokenWithExpDate, shopifyUser); }
二、无密码(一次性验证码)模式认证流程实现
Shopify的无密码登录模式无需预先创建账号,用户通过邮箱接收验证码完成登录,未注册的邮箱会自动生成账号。完整流程如下:
1. 店铺后台配置无密码登录
进入设置 > 客户账户 > 登录选项,选择「通过邮箱发送一次性验证码」,关闭密码登录选项。
2. 核心API调用流程
步骤1:向邮箱发送验证码
调用customerAccessTokenCreate mutation触发验证码发送:
mutation SendOTP($email: String!) { customerAccessTokenCreate(input: {email: $email, sendEmail: true}) { customerUserErrors { code field message } } }
步骤2:验证验证码并获取token/创建账号
用户输入验证码后,调用同个mutation验证并获取身份凭证,未注册的邮箱会自动创建账号:
mutation VerifyOTP($email: String!, $otp: String!) { customerAccessTokenCreate(input: {email: $email, otp: $otp}) { customerAccessToken { accessToken expiresAt } customer { id email displayName firstName lastName phone } customerUserErrors { code field message } } }
步骤3:刷新过期token(可选)
token过期时,使用customerAccessTokenRenew mutation刷新:
mutation RenewToken($accessToken: String!) { customerAccessTokenRenew(customerAccessToken: $accessToken) { customerAccessToken { accessToken expiresAt } customerUserErrors { code field message } } }
3. Dart代码实现示例
// 发送验证码到指定邮箱 Future<void> sendOTP(String email) async { final MutationOptions options = MutationOptions( document: gql(r''' mutation SendOTP($email: String!) { customerAccessTokenCreate(input: {email: $email, sendEmail: true}) { customerUserErrors { code field message } } } '''), variables: {'email': email}, ); final QueryResult result = await _graphQLClient!.mutate(options); checkForError(result, key: 'customerAccessTokenCreate', errorKey: 'customerUserErrors'); } // 验证验证码,完成登录/账号创建 Future<ShopifyUser> verifyOTP(String email, String otp) async { final MutationOptions options = MutationOptions( document: gql(r''' mutation VerifyOTP($email: String!, $otp: String!) { customerAccessTokenCreate(input: {email: $email, otp: $otp}) { customerAccessToken { accessToken expiresAt } customer { id email displayName firstName lastName phone } customerUserErrors { code field message } } } '''), variables: {'email': email, 'otp': otp}, ); final QueryResult result = await _graphQLClient!.mutate(options); checkForError(result, key: 'customerAccessTokenCreate', errorKey: 'customerUserErrors'); final data = result.data!['customerAccessTokenCreate']; final accessTokenData = data['customerAccessToken']; final userData = data['customer']; final accessTokenWithExpDate = AccessTokenWithExpDate( accessToken: accessTokenData['accessToken'], expiresAt: DateTime.parse(accessTokenData['expiresAt']), ); final shopifyUser = ShopifyUser.fromGraphJson(userData); await _setShopifyUser(accessTokenWithExpDate, shopifyUser); return shopifyUser; }
内容的提问来源于stack exchange,提问作者Mujtaba Farhan
相关产品推荐
相关产品推荐

