You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Angular集成Sign In With Apple JS时,点击Continue按钮后弹窗不关闭、登录事件未触发

Angular集成Sign In With Apple JS时,点击Continue按钮后弹窗不关闭、登录事件未触发

我之前也遇到过几乎一模一样的问题,折腾了好一阵才找到几个核心排查方向和解决办法,你可以逐一试试:

1. 核心问题:回调URI不能是API接口,必须用静态前端页面

这大概率是你当前问题的根源!当开启usePopup: true时,Apple的授权流程会通过web_message模式传递结果,你的redirectURI必须指向一个能接收并转发Apple消息的静态HTML页面,而不是后端API接口(你现在填的是https://mtmdevelopmentapi.azurewebsites.net/api/Account/AppleCallback/300,这是API接口,无法处理前端的postMessage通信)。

解决方案:

  • 新建一个静态HTML页面(比如apple-callback.html),放在你的前端域名下(和Angular应用同域),内容如下:
    <!DOCTYPE html>
    <html>
    <body>
      <script type="text/javascript">
        // 接收Apple的授权结果消息,转发给父窗口后关闭弹窗
        window.addEventListener('message', function(event) {
          if (event.origin === 'https://appleid.apple.com') {
            window.opener.postMessage(event.data, event.origin);
            window.close();
          }
        });
      </script>
    </body>
    </html>
    
  • 到Apple开发者后台,把你的Redirect URI更新为这个静态页面的完整URL(比如https://your-frontend-domain.com/apple-callback.html
  • 同时修改Angular代码里的AppleID.auth.init配置,把redirectURI替换成这个新地址

2. 确认事件绑定的时机与组件生命周期清理

Angular组件的事件绑定容易出现时机问题,要确保在Apple JS SDK完全加载完成后再绑定事件,同时组件销毁时要解绑避免内存泄漏。

优化后的代码示例:

import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-apple-signin',
  templateUrl: './apple-signin.component.html'
})
export class AppleSigninComponent implements OnInit, OnDestroy {
  private boundAppleSuccessHandler: any;
  private boundAppleErrorHandler: any;

  ngOnInit(): void {
    this.loadAppleSDK();
  }

  ngOnDestroy(): void {
    // 组件销毁时解绑事件
    if (this.boundAppleSuccessHandler) {
      document.removeEventListener('AppleIDSignInOnSuccess', this.boundAppleSuccessHandler);
    }
    if (this.boundAppleErrorHandler) {
      document.removeEventListener('AppleIDSignInOnFailure', this.boundAppleErrorHandler);
    }
  }

  private loadAppleSDK(): void {
    // 动态加载Apple JS SDK,确保加载完成后再初始化和绑定事件
    const script = document.createElement('script');
    script.src = 'https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js';
    script.onload = () => {
      // 初始化Apple SDK
      AppleID.auth.init({
        clientId: 'net.membertomember.customer',
        scope: 'name email',
        redirectURI: 'https://your-frontend-domain.com/apple-callback.html', // 替换为新的静态回调页地址
        usePopup: true,
      });

      // 绑定事件
      this.boundAppleSuccessHandler = this.handleAppleSuccessResponse.bind(this);
      this.boundAppleErrorHandler = this.handleAppleErrorResponse.bind(this);
      document.addEventListener('AppleIDSignInOnSuccess', this.boundAppleSuccessHandler);
      document.addEventListener('AppleIDSignInOnFailure', this.boundAppleErrorHandler);
    };
    document.body.appendChild(script);
  }

  private handleAppleSuccessResponse(event: any) {
    console.log('授权成功:', event.detail.data);
    this.authService.AuthFromLocalStorage = event.detail.data;
    this.authService.getCustomerDetails(event.detail.data.email);
  }

  private handleAppleErrorResponse(event: any) {
    console.log('授权失败:', event.detail.error);
    if (event.detail.error === 'popup_closed_by_user') return;
    this.toast.error(event.detail.error_description, event.detail.error);
  }
}

3. 浏览器环境排查

部分浏览器(尤其是Safari)对跨域弹窗、第三方Cookie的限制很严格,可能会阻止消息传递:

  • 确保用户浏览器允许你的网站弹出窗口
  • Safari用户需要在设置中开启"允许跨域跟踪"(关闭"防止跨站跟踪"选项)
  • 检查浏览器控制台是否有跨域相关的报错

4. 检查授权请求参数

从你提供的网络请求来看,请求体里的scopes是空数组,但你初始化时设置了scope: 'name email',可以尝试把scope改成数组格式:scope: ['name', 'email'],确保权限参数正确传递。

我当时就是因为把回调URI设成了API接口,折腾了好久,换成静态回调页后马上就正常了,你先试试这个核心修改!

内容来源于stack exchange

火山引擎 最新活动