小程序走过的坑坑

背景:项目均使用小程序跨平台框架Taro,Taro-UI进行开发

图片上传

背景:用户实名认证需要上传头像和身份证图像提交至后台审核,上传的身份证信息前端需要走OCR识别姓名和身份证号反填至输入框,提交后的头像信息走face++进行人脸识别。

问题1: 直接上传的图片一般较大,导致face识别时间长(face文档上写的,说图片大小太大会影响识别时长),超过3s后服务端会直接报超时而不返回正确结果

解决方案: 服务端设置超时时间大于3s,前端做图片压缩处理

问题2: 小程序提供的压缩图片API压缩图片越压缩越大

解决方案:Taro的压缩图片方法也是调用小程序提供的压缩方案,使用效果并不理想,基本上都是越压越大(百度和微信都是这样),网上说只有ios下才有效果,但我试了下ios和安卓的都不行,这时就要另谋出路,一是考虑使用其他第三方压缩组件,二是通过canvas将图片绘制,然后通过小程序包装的canvasToTempFilePath方法再导出一份图片,导出时降低图片质量,以达到质量变小的效果。这里我们主要使用第二种方式

核心代码

  // 压缩图片
  async compressImg(localPath){
    const imgInfo = await Taro.getImageInfo({ src: localPath.path })
    console.log('imgInfo', imgInfo)
    if (imgInfo) {
      const { width, height, path} = imgInfo
      const ctx = Taro.createCanvasContext('myCanvas')
      ctx.clearRect(0, 0, width, height);
      return new Promise((resolve, reject) => {
        //设置canvas画布的宽高和图片本身一致,原来一直写死画布的宽高导致绘制出的图片各种被截断
        this.setState({
          height: height,
          width: width
        }) 
        ctx.drawImage(path, 0, 0,  width, height)
        ctx.draw(false, () => {
          Taro.canvasToTempFilePath({
            fileType: 'jpg',  // 图片质量目前仅对 jpg 有效,所以这个地方设为jpg格式
            quality: 0.4, // 写1的话大小和原图差不多,有时候也会比原图还大
            canvasId: 'myCanvas', // 画布标识
            fail: e => {
              reject(e)
            },
            success (res) {
              resolve(res)
            },
          })
        })
      })
    }
  }
  render() {
    const { width, height } = this.state
    return (
      <Canvas canvasId='myCanvas' style={{ height: height + 'px', width: width + 'px', position: 'fixed', top: '-999px', left: '-999px'  } }></Canvas>
    )
  }

画布不能使用 display: 'none'的属性进行隐藏,会找不到对应canvas节点;画布的宽高我这里是根据图片的宽高来的,如果想缩成固定比例,比如width=100,那高度就是height=Math.trunc(100*图片高度/图片宽度),设置在drawImage的dWidth和dHeight中。

问题3:百度小程序的用户弹框在开发工具中未弹起

解决方案:基本思路是获取当前用户授权信息看是否对相机进行了授权,已授权直接进行图片选择,未授权则拉起小程序的授权设置引导用户进行授权,代码如下

    try {
      const cameraAuth = (await Taro.getSetting()).authSetting['scope.camera']
      if (cameraAuth === false) {
        await Taro.openSetting()
        return
      }
      if (!cameraAuth) {
        await Taro.authorize({ scope: 'scope.camera' })
      }
    } catch (e) {
      Layer.toast('请允许百度授权调起相机')
      return
    }

因为用了taro框架的授权方法,并未察觉微信和百度在这部分的差异,这个在微信和百度的真机下没有问题,正常运行,但是在百度的开发工具里,引导用户打开权限设置时,没有允许相机的选项,查了下百度的配置,是通过getSetting拿授权信息时出现了问题

授权出参差异
getSetting拿到授权信息百度微信
用户未操作授权状态{
  authSetting: {
    scope.address: falses,
    cope.camera: falses,
    cope.faceVerify: false
  }
}
{
  authSetting: {
    
  }
}
用户点击拒绝{
  authSetting: {
    scope.address: falses,
    cope.camera: falses,
    cope.faceVerify: false
  }
}
{
  authSetting: {
    scope.address: falses,
    cope.camera: falses,
    cope.faceVerify: false
  }
}
用户点击通过{
  authSetting: {
    scope.address: true,
    cope.camera: true,
    cope.faceVerify: true
  }
}
{
  authSetting: {
    scope.address: true,
    cope.camera: true,
    cope.faceVerify: true
  }
}

主要差异在于百度用户首次进入和用户拒绝时,简单的通过true或者false是无法判断用户是首次进入还是曾经拒绝过,所以我们暂不通过getSetting去判断,直接改成一下模式

const Authorize = async (scope, errTip, isAlert) => {
    return new Promise((resolve, reject) => {
      Taro.authorize({
        scope: scope,
        success: (res) => {
          console.log('权限res', res)
          Layer.hideLoading()
          resolve(true)
        },
        fail: (err) => {
          console.log('权限err', err)
          Layer.hideLoading()
          isAlert ? Layer.confirm(errTip || '请在权限管理中开启权限', {
            title: '',
            confirmText: '确定',
            success: ({ confirm }) => {
              confirm ? Taro.openSetting({
                fail: (error) => {
                  console.log('openSetting err', error)
                  reject(false)
                },
                success: (resp)=> {
                  let r = resp && resp.authSetting['scope.camera']
                  console.log('resp', !!r)
                  r ? resolve(!!r) : reject(!!r)
                }
              }) : reject(false)
            }
          })
          :
          Layer.toast(errTip || '请在权限管理中开启权限')
        }
      })
    })
  return false
}

 

对于openSetting,这里只显示用户曾经操作过的授权信息,用户未处理任何授权操作的情况下,此处没有信息。

 

对接钱包

问题1:小程序里跳转钱包的H5的页面无法打开,提示“页面iframe不支持引用非业务域名,https://pay.56qq.com,请重新配置”

解决方案:在小程序开放平台-开发-开发设置里设置业务域名(注意区分业务域名和服务器域名),平台对这些域名的修改有次数限制,请提前整理提前配置,并找运维将对应生成的序列文件配置在对应服务器下。如果这些地方都配好了还是不行(我们当时的表现是在真机微信开发调试模式下能正常打开,关闭调试就不行),请钱包的同学确认钱包项目使用的微信sdk的协议是否与报错的协议一致(http/https)。

 

问题2:跳转钱包链接需要带token

解决方案:小程序有跳钱包的入口,开始的时候就只给了一个跳转链接,以为跳过去就好,联调的时候才发现还需要token,然而并没有人告诉我这个token是怎么来的,后来找了一圈,原来还要调一个拿钱包token的接口(文档已找到https://wiki.amh-group.com/pages/viewpage.action?pageId=65711940),当时找的代码,并没有找到文档,拿到token传过去后钱包显示用户token信息不准确,然后又是漫长的找人翻代码发现请求头中对client-info有要求,需要配置正确的AppId

 

 

 

 

 

微信 第一次打开,查看授权信息getSetting,没有任何用户授权,没有kay-value,拒绝或同意后getSetting的数据会显示key-value,拒绝false 同意true(在没有授权被拒绝的时候调用openSetting是没有权限配置的)

百度 第一次打开或者N次打开,没有任何用户授权,依然显示所有授权项,所以没有办法判断是用户第一次进来没有授权信息还是说已经弹过授权框但被用户拒绝

https://smartprogram.baidu.com/docs/develop/api/open/authorize_list/

https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html#scope-%E5%88%97%E8%A1%A8

共同点:如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调

 

关于开发权限

问题1:涉及到登录,获取用户手机号,授权开启摄像头,获取用户当前地理位置等敏感数据时,调用各端API是需要权限的,不然开发的流程一定会受阻(等到时候再找人开就很麻烦,因为权限申请提交后审核还需要时间,申请后还可能会被打回重新申请)

解决方案:各个端的大后台都会有对应的认证,审核流程,请自行根据需要提前申请

微信:https://developers.weixin.qq.com/miniprogram/product/renzheng.html

支付宝:https://opensupport.alipay.com/support/helpcenter/144/201602497709?ant_source=zsearch&ant_source=manual&recommend=c465eca9838580e8a81fa7a718c7d06a

百度:没找着,自行翻阅文档

字节跳动:待定

 

 

关于登录

各端的登录流程如下

 

差异

各端的流程基本如此,一个最大的差异在于一键登录时API的调用,百度和微信对按钮的属性值保持一致,支付宝则自有一套属性,这个地方在实现时是区分开写的。

 scope

open-type

onGetphonenumber

onGetAuthorize

百度,微信

phoneNumber

‘getPhoneNumber’

回调方法-
支付宝phoneNumber

‘getAuthorize’

-回调方法,在

my.getPhoneNumber中返回

 

关于样式

在样式上的差异,微信和百度的表现还算老实,主要还是支付宝,避坑的建议是少用绝对定位,多考虑flex布局,我这边涉及的样式改动不算大,所以没有典型的案例分享。

打包过大无法上传

解决:

我们的项目打包用webpack 我们可以使用它的插件进行打包压缩,,没有装工具的自行进行安装

npm i --save-dev terser-webpack-plugin

/config/index.js

import TerserPlugin from "terser-webpack-plugin"

const config = {
    mini: {
      webpackChain(chain, webpack) {
        chain.mode("production");
        chain.optimization.minimize(true);
        chain.plugin("terser").use(TerserPlugin, [
          {
            cache: true,
            extractComments: false,
            terserOptions: {
              output: {
                comments: false
              }
            }
          }
        ]);
      }
  }
}

坑:

这样打包过后包小了不少,但是本地的debugger会失效,所以在等到需要打包的时候再加上这一段吧

Taro组件

问题1

input输入框的属性maxLength无效

https://taro-docs.jd.com/taro/docs/components/forms/input/

解决方案

3.0之前maxLength用着没问题,后来属性值无效了,比对着原生input对这个属性的定义,我发现,是大小写出了问题,改成maxlength就好了,,,

 

未完待续。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值