uni-app 开发鸿蒙应用---使用webview做鸿蒙支付宝支付

目前工程文件:SDK template-1.3.5.tgz

uni-app 开发鸿蒙应用 | uni-app官网 (dcloud.net.cn)

实现原理:uniapp使用webview组件打开支付宝链接,此时鸿蒙端web()组件onErrorReceive回调返回错误信息【ERR_UNKNOWN_URL_SCHEME】,然后在onErrorReceive回调中做应用间跳转手动打开app

1.uniapp---web组件打开支付宝链接

<template>
	<view>
		<!-- 支付宝支付 -->
		<web-view :src="alipayUrl"></web-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				alipayUrl: '',
			}
		},
		onLoad(options) {
			let infoUrl = JSON.parse(decodeURIComponent(options.info));
			// scheme
			this.alipayUrl = 'https://ds.alipay.com/?scheme=' + encodeURIComponent(
				'alipays://platformapi/startapp?saId=10000007&qrcode=' + infoUrl);
		},
	}
</script>

<style scoped lang="scss">
</style>

 这时harmony返回错误:ERR_UNKNOWN_URL_SCHEME

2.template---做应用间跳转

harmony应用间跳转文档地址:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/canopenlink-V5

2.1 module.json页面配置querySchemes

"querySchemes": [
      "alipays", // 支付宝
      "store", // 应用商城
    ],

2.2 WebView.ets页面做应用间跳转

WebView.ets 完整代码如下

import harmonyWebView from '@ohos.web.webview'
import picker from '@ohos.file.picker';
import { BusinessError } from '@ohos.base';
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
import { bundleManager } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import OpenLinkOptions from '@ohos.app.ability.OpenLinkOptions';
import { promptAction } from '@kit.ArkUI';

const TAG: string = '[UIAbilityComponentsOpenLink]';
const DOMAIN_NUMBER: number = 0xFF00;

interface Detail {}

interface Event {
  detail: Detail
}

interface TitleUpdateEventDetail {
  title?: string
}

interface TitleUpdateEvent extends Event {
  detail: TitleUpdateEventDetail
}

@Component
export struct WebView {
  @Prop @Watch('setSrc') src: string
  onMessage?: (event: Event) => void = undefined
  onTitleUpdate?: (event: TitleUpdateEvent) => void = undefined
  onPostMessageToService?: (event: Event) => void = undefined
  exposeWebViewController?: (controller: harmonyWebView.WebviewController) => void = undefined
  controller = new harmonyWebView.WebviewController()

  aboutToAppear(): void {
    this.exposeWebViewController?.(this.controller)
  }

  build() {
    Web({
      src: this.src,
      controller: this.controller
    })
      .overScrollMode(OverScrollMode.NEVER)
      .geolocationAccess(true)
      .domStorageAccess(true)
      .imageAccess(true)
      .fileAccess(true)
      .onTitleReceive(event => {
        this.onTitleUpdate?.({
          detail: {
            title: event?.title
          }
        })
      })
      .onConsole(event => {
        if (event) {
          console.log('getMessage: ' + JSON.stringify(event.message.getMessage()))
        }
        return false
      })
      .onErrorReceive(event => {
        if (event) {
          console.error('getMessage: '+JSON.stringify(event.error.getErrorInfo()))
          console.log('url:' + event.request.getRequestUrl())
          // 判断应用是否可访问
          try {
            let link = event.request.getRequestUrl();
            let canOpen = bundleManager.canOpenLink(link);
            hilog.info(0x0000, 'testTag', 'canOpenLink successfully: %{public}s', JSON.stringify(canOpen));
            if(canOpen){
              // 应用间跳转
              let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
              let openLinkOptions: OpenLinkOptions = {
                appLinkingOnly: false
              };
              try {
                context.openLink(link, openLinkOptions)
                  .then(() => {
                    hilog.info(DOMAIN_NUMBER, TAG, 'open link success.');
                  }).catch((err: BusinessError) => {
                  hilog.error(DOMAIN_NUMBER, TAG, `open link failed. Code is ${err.code}, message is ${err.message}`);
                })
              } catch (paramError) {
                hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. Code is ${paramError.code}, message is ${paramError.message}`);
              }
            }else{
              promptAction.showToast({
                message: 'APP 未安装',
                duration: 2000,
                bottom: '500lpx'
              });
            }
          } catch (err) {
            let message = (err as BusinessError).message;
            hilog.error(0x0000, 'testTag', 'canOpenLink failed: %{public}s', message);
          }
        }
      })
      .javaScriptProxy({
        object: {
          postMessage: (data: string) => {
            if (this.onMessage) {
              this.onMessage({ detail: JSON.parse(data) })
            }
          },
          postMessageToService: (data: string) => {
            if (this.onPostMessageToService) {
              this.onPostMessageToService({ detail: JSON.parse(data) })
            }
          }
        },
        name: '__uniapp_x_',
        methodList: ['postMessage', 'postMessageToService'],
        controller: this.controller
      })
      .onGeolocationShow((event) => {

        let context = getContext(this) as common.UIAbilityContext;
        let atManager = abilityAccessCtrl.createAtManager();
        atManager.requestPermissionsFromUser(context, ["ohos.permission.APPROXIMATELY_LOCATION"]).then((data) => {
          console.info('data authResults:' + data.authResults);
        }).catch((error: BusinessError) => {
          console.error(`Failed to request permissions from user. Code is ${error.code}, message is ${error.message}`);
        })

        AlertDialog.show({
          title: '位置权限请求',
          message: '是否允许获取位置信息',
          primaryButton: {
            value: 'cancel',
            action: () => {
              if (event) {
                event.geolocation.invoke(event.origin, false, false);
              }
            }
          },
          secondaryButton: {
            value: 'ok',
            action: () => {
              if (event) {
                event.geolocation.invoke(event.origin, true, true);
              }
            }
          },
          cancel: () => {
            if (event) {
              event.geolocation.invoke(event.origin, false, false);
            }
          }
        })
      })
      .onShowFileSelector((event) => {
        // TODO 真机运行没有问题,模拟器运行后,选择图片后H5端无法获取图片信息
        const selectOptions = new picker.PhotoSelectOptions();
        const mode = event?.fileSelector.getMode();
        const acceptType = event?.fileSelector.getAcceptType();
        if (mode === 0) {
          selectOptions.maxSelectNumber = 1;
        }
        if (acceptType) {
          let type = "";
          const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg', '.webp'];
          const containsImage = imageExtensions.some((ext: string): boolean => acceptType.includes(ext));
          const videoExtensions =
            ['.mp4', '.mov', '.avi', '.mkv', '.flv', '.wmv', '.ogg', '.webm', 'mpg', 'mpeg', '.3gp', 'rm', 'rmvb',
              'm4v', 'wma', 'mts'];
          const containsVideo = videoExtensions.some((ext: string): boolean => acceptType.includes(ext));
          if (containsImage && containsVideo) {
            type = "IMAGE_VIDEO_TYPE";
          } else if (containsImage) {
            type = "IMAGE_TYPE";
          } else if (containsVideo) {
            type = "VIDEO_TYPE";
          }
          if (type) {
            selectOptions.MIMEType = picker.PhotoViewMIMETypes[type]
          }
        }
        let filePaths: Array<string> | null = null;
        const viewPicker = new picker.PhotoViewPicker();
        viewPicker.select(selectOptions).then((selectResult) => {
          filePaths = selectResult.photoUris;
          if (event) {
            event.result.handleFileList(filePaths);
          }
        }).catch((err: BusinessError) => {
          console.error(`Invoke viewPicker.select failed, code is ${err.code}, message is ${err.message}`);
        })
        return true
      })
  }

  setSrc() {
    this.controller.loadUrl(this.src)
  }
}

uni-app使用webview存在兼容性问题。根据引用的描述,webviewuni-app中的通信机制存在问题,可能无法正常接收数据。另外,web-view的bug也较为常见且没有被官方及时解决,因此一些开发者选择不使用web-view。而引用中提到的web-view是通过plus.webview.create创建的frame窗口,这种方式可以在uni-app使用。但是,引用中指出,nvue获取webview窗口的方式与普通vue的方式不同,需要进行特殊处理。 解决兼容性问题可以考虑以下几点方法: 1.避免使用web-view,在uni-app使用其他组件或技术来实现相同的功能,如使用h5标签、页面跳转等。 2.如果必须使用web-view,可以尝试使用plus.webview.create创建frame窗口的方式来解决部分兼容性问题。注意在nvue中获取webview窗口的方式需要与普通vue有所不同,可以参考引用中提到的方法进行处理。 3.及时向官方反馈发现的bug,希望能够得到官方的解决方案或修复。 综上所述,解决uni-app webview的兼容性问题可以考虑避免使用web-view、使用plus.webview.create创建frame窗口、特殊处理nvue中获取webview窗口的方式以及向官方反馈问题。具体的解决方法需要根据具体情况进行调整和选择。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [uni-app webview(非web-view)与网页的通讯方法](https://blog.csdn.net/qq_23064433/article/details/120289001)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [uniapp系列-超详细教你在uni-app+vue3里通过web-view组件传递信息打开H5页面写入localstorage并解决兼容性](https://blog.csdn.net/tangdou369098655/article/details/130234169)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值