ionic5 开发微信网页时分享失败原因总结 作者:七棵菜 日期:2022-11-30 栏目:计算机分类:1 人气:186 ionic5开发微信网页区别于传统的网页技术,这是一个单网页应用,android和ios在分享时有很大的区别。 由于微信是根据页面的地址动态生成分享签名,因此最根本的原因就是如何获得android和ios的页面地址。 #### 苹果分享 在苹果微信分享时,用户生成签名的地址不能使用`window.location.href`,尽管我们拷贝页面地址看到的结果是地址变了,但是苹果在处理单网页应用内部页面切换时,真实的地址始终是进入应用的地址,除非我们在页面切换时使用`window.location`做页面跳转。 因此处理苹果分享的问题,可以借助angular的服务单例模式,定义一个服务用来在根组件中保存入口地址,分享时只需要获取此服务保存的地址即可。 ``` import "自定义服务RouterKeeperService"; @Component({ selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.scss'] }) export class AppComponent { constructor( private platform: Platform, private routerKeeper: RouterKeeperService, ) { this.initializeApp(); } initializeApp() { this.platform.ready().then(() => { this.routerKeeper.initUrl = window.location.href; // 保存初次进入应用的地址 }); } } ``` ### android分享 在android微信分享时,我们可以直接使用`window.location.href`获取签名。 需要注意的是,微信配置一般是在页面初始化`ngInit`之后执行,但是当页面参数变化,路由地址没有变化的时候,`ngInit`是不会执行的,这就会导致初始化时的地址和当前地址不一样。 解决此问题的办法是监听路由变化,在地址变化后重新初始化微信配置。 ``` ngOnInit() { // 订阅路由变化事件 this.router.events.pipe(takeUntil(this.destroy$)).subscribe((event) => { if (event instanceof NavigationEnd) { /* 路由变化之后需要重新配置微信分享,因为关卡`url`已改变,修复`android`分享失败的问题 */ // todo 微信配置 } } }); } ``` ##### 自定义微信服务类 分享一个我自定义的微信服务类 ``` import { Injectable, Injector } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { Observable, BehaviorSubject } from 'rxjs'; import { map, filter, share } from 'rxjs/operators'; import { BaseHttpClient } from '../base/base-http-client'; import { weixinConfigApi } from '../base/api.const'; import { RouterKeeperService } from '../base/router-keeper.service'; const wx = (window as any).wx; const isWkwebview = (window as any).__wxjs_is_wkwebview; interface WeixinJavascriptAuthorization { appId: string; timestamp: string; nonceStr: string; signature: string; } interface ImageMessage { media: string; source: any; } @Injectable({ providedIn: 'root' }) export class MicroChatService { weixin = wx; // 单例模式 router: string; // 页面地址 protected photo$: BehaviorSubject<ImageMessage> = new BehaviorSubject(null); // 选择图片 debug: boolean = false; constructor(private http: BaseHttpClient, private inject: Injector, public sanitizer: DomSanitizer) {} /** * 微信配置 * @param title 分享标题 * @param description 分享描述 * @param link 分享链接 * @param image 分享图片 * @param callback 分享成功后的回调 * @param reload 是否强制重新配置分享 */ config(title: string, description: string, link: string, image: string) { const redirect = this.getShareUrl(); this.log(redirect); this.log(this.router); // 地址改变之后重新配置 if (!this.router || this.router !== redirect) { this.http.get(weixinConfigApi, {redirect}) .pipe( map(data => data.content as WeixinJavascriptAuthorization), ) .subscribe(data => { wx.config({ debug: this.debug, appId: data.appId, timestamp: data.timestamp, nonceStr: data.nonceStr, signature: data.signature, jsApiList: [ 'updateTimelineShareData', // 分享到朋友圈 'updateAppMessageShareData', // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容 'chooseImage', // 拍照或从手机相册中选图 'previewImage', // 预览图片 'uploadImage', // 上传图片 ] }); wx.ready(() => { if (title && link && image) { // 需在用户可能点击分享按钮前就先调用 /* 自定义“分享给朋友”及“分享到QQ”按钮的分享内容 */ wx.updateAppMessageShareData({ title, // 分享标题 desc: description, // 分享描述 link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: image // 分享图标 }); /* 分享到朋友圈 */ wx.updateTimelineShareData({ title: description ? description : title, // 分享标题 link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: image // 分享图标 }); } else { this.log('title is null'); } }); this.weixin = wx; this.router = redirect; }); } } getShareUrl() { const u = navigator.userAgent; // const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); if (isIOS) { // 苹果系统 return this.inject.get(RouterKeeperService).initUrl; // 获取初始路径 } else { return window.location.href; // 当前页面地址 } } /** * 分享 * deprecated */ share(title: string, description: string, link: string, image: string) { } /** * 选择图片 */ chooseImage(sourceType = ['album', 'camera']) { this.log('开始调用wxChooseImage方法'); const $this = this; this.weixin.chooseImage({ count: 1, sizeType: ['compressed'], // 压缩图 sourceType, // 可以指定来源是相册还是相机,默认二者都有 success: (data) => { const localId = data.localIds[0].toString(); // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 if (localId) { $this.uploadImage(localId); // 上传图片 } $this.photo$.next({media: '', source: false}); // 发布消息 $this.log('调用wxChooseImage方法成功'); }, fail: (res) => { $this.log(res); } }); } /** * Publishes image when it changes. * @returns 图片改变通知 */ imageChange(): Observable<ImageMessage> { return this.photo$ .pipe( filter(value => !!value), share(), ); } /** * 上传图片 * @param e 图片的localID */ uploadImage(e: string) { const $this = this; if (isWkwebview) { this.weixin.getLocalImgData({ localId: e, success: (res) => { const localData = res.localData; // localData是图片的base64数据,可以用img标签显示 if (localData) { $this.finishUpload(e, localData); } else { alert('图片有误'); } }, fail: (error) => { alert('选择图片失败(' + error + ')'); } }); } else { this.weixin.uploadImage({ localId: e, // 需要上传的图片的本地ID,由chooseImage接口获得 isShowProgressTips: 0, // 默认为1,显示进度提示 success: (res) => { const mediaId = res.serverId; // 返回图片的服务器端ID if (mediaId) { $this.finishUpload(e, mediaId); } }, fail: (error) => { alert('选择图片失败(' + error + ')'); } }); } } /** * 上传完成 * @param local 本地图片编号 * @param media 微信图片编号/base64编码的图片 */ finishUpload(local, media) { this.photo$.next({media, source: this.sanitizer.bypassSecurityTrustResourceUrl(local)}); // 发布消息 this.photo$.next(null); // 发送空消息,防止下次执行 } log(message) { if (this.debug) { // alert(message); console.log(message); } } } ``` 目前微信分享类库已经更新到`1.4.0`,加载类库时使用如下: ``` <script src="http://res2.wx.qq.com/open/js/jweixin-1.4.0.js"></script> ``` 标签: 微信分享 单网页地址 ionic微信 上一篇:如何使用mvn命令导入依赖 下一篇:利用redis实现并发超卖的问题 随便看看 2024-02-19 PHP7 运算符“??” 和“?:”的区别 2022-11-30 Linux 后台运行命令 2022-11-25 关于我们 2022-11-30 centos一键系统安装lnmp集成环境 2022-11-30 linux 生成 ssh 公钥 留言