当前位置:   article > 正文

uniapp uni实人认证_uniapp实名认证

uniapp实名认证

uni实人认证依赖 目前仅支持App平台。

h5端活体人脸检测,使用的是百度云的h5人脸实名认证

使用要求

1、app端

在使用前,请确保您已注册DCloud账号,并已完成实名认证

然后需要按文档开通服务 业务开通 | uni-app官网

2、h5端

 在使用前,需要根据方案接入要求先准备好 人脸实名认证H5端方案

开发

  1. // index.vue
  2. <template>
  3. <view class="page">
  4. <button class="btn" @click="$u.throttle(livenessDetection, 1000)">
  5. 开始刷脸验证
  6. </button>
  7. </view>
  8. </template>
  9. <script>
  10. import { getVerifyToken, h5VerifyIdentifyReturn } from '@/api/user.js'
  11. import { HTTP_REQUEST_URL, H5_URL } from '@/config.js'
  12. import permision from '@/utils/js_sdk/permission.js'
  13. import store from '@/store'
  14. export default {
  15. data() {
  16. return {
  17. // 终端id
  18. orgId: 0,
  19. // 姓名
  20. legalPerson: '',
  21. // 身份证
  22. idCard: '',
  23. }
  24. },
  25. onLoad(options) {
  26. this.orgId = options.orgId || 0
  27. this.legalPerson = options.legalPerson || ''
  28. this.idCard = options.idCard || ''
  29. // #ifdef H5
  30. if (options.verify_result && options.verify_result == 1) {
  31. this.h5VerifyIdentifyReturn()
  32. }
  33. // #endif
  34. },
  35. methods: {
  36. // 检查是否开启摄像头权限
  37. checkPermissionCamera() {
  38. return new Promise(async (resolve) => {
  39. switch (uni.getSystemInfoSync().platform) {
  40. case 'android':
  41. const val = await permision.requestAndroidPermission('android.permission.CAMERA')
  42. if (val == 1) {
  43. // 已获取授权
  44. resolve()
  45. } else if (val == -1) {
  46. // 被永久拒绝授权
  47. uni.showModal({
  48. title: '温馨提示',
  49. content: '摄像头权限已经被您永久拒绝,请前往设置页面打开',
  50. showCancel: false,
  51. confirmText: '前往设置',
  52. success() {
  53. // 打开当前App的权限设置界面
  54. permision.gotoAppPermissionSetting()
  55. }
  56. })
  57. }
  58. break
  59. case 'ios':
  60. // 是不是第一次开启相机
  61. const iosFirstCamera = uni.getStorageSync('iosFirstCamera');
  62. if (iosFirstCamera) {
  63. // 判断iOS上是否给予摄像头权限,有权限返回true,否则返回false
  64. const val2 = await permision.judgeIosPermission('camera')
  65. if (val2) {
  66. resolve()
  67. } else {
  68. uni.showModal({
  69. title: '温馨提示',
  70. content: '摄像头权限已经被您拒绝,请前往设置页面打开',
  71. showCancel: false,
  72. confirmText: '前往设置',
  73. success() {
  74. // 打开当前App的权限设置界面
  75. permision.gotoAppPermissionSetting()
  76. }
  77. })
  78. }
  79. } else {
  80. uni.setStorageSync('iosFirstCamera', true);
  81. resolve()
  82. }
  83. break
  84. }
  85. })
  86. },
  87. // 活体认证
  88. async livenessDetection() {
  89. // #ifdef MP-WEIXIN
  90. uni.$u.toast('请使用app进行刷脸验证')
  91. // #endif
  92. // #ifdef APP-PLUS
  93. this.appAuth()
  94. // #endif
  95. // #ifdef H5
  96. await this.checkPermissionCamera()
  97. this.h5Auth()
  98. // #endif
  99. },
  100. // #ifdef H5
  101. // h5端实名认证
  102. async h5Auth() {
  103. uni.showLoading({
  104. title: '认证中',
  105. mask: true
  106. })
  107. // 获取verify_token
  108. const res = await getVerifyToken()
  109. const verify_token = res.verify_token
  110. const successUrl = encodeURIComponent(`${ H5_URL }/pages/register/faceDetect?verify_result=1`)
  111. const failedUrl = encodeURIComponent(`${ H5_URL }/pages/register/faceDetect?verify_result=2`)
  112. // 跳转到百度云实名认证H5页
  113. window.location.href = `https://brain.baidu.com/face/print/?token=${ verify_token }&successUrl=${ successUrl }&failedUrl=${ failedUrl }`
  114. uni.hideLoading()
  115. },
  116. // 活体检测成功后的处理
  117. async h5VerifyIdentifyReturn() {
  118. uni.showLoading({
  119. title: '获取认证结果',
  120. mask: true
  121. })
  122. await h5VerifyIdentifyReturn()
  123. this.successAfter()
  124. },
  125. // #endif
  126. // #ifdef APP-PLUS
  127. // app端实名认证
  128. appAuth() {
  129. uni.showLoading({
  130. title: '认证中',
  131. mask: true
  132. })
  133. // 1、获取实人认证设备信息
  134. const metaInfo = uni.getFacialRecognitionMetaInfo()
  135. // 2、提交姓名、身份证号、metaInfo到云函数获取certifyId
  136. uniCloud.callFunction({
  137. name: 'livenessDetection',
  138. data: {
  139. step: 1,
  140. metaInfo,
  141. legalPerson: this.legalPerson,
  142. idCard: this.idCard
  143. }
  144. }).then(res => {
  145. if (res.result.code == 500) return uni.$u.toast(res.result.msg)
  146. const certifyId = res.result.data
  147. // 3、云函数获取certifyId后,调起实人认证界面
  148. uni.startFacialRecognitionVerify({
  149. certifyId,
  150. // 刷脸圈的颜色 加上这个参数会在ios端会提示 errCode: 10013 刷脸失败
  151. // progressBarColor: '#4a9f8b;',
  152. // 认证界面UI朝向 竖屏
  153. screenOrientation: 'port',
  154. success: async (e) => {
  155. if (e.errCode != 0) return uni.$u.toast(e.errMsg)
  156. // 4、获取认证结果
  157. const certResult = await uniCloud.callFunction({
  158. name: 'livenessDetection',
  159. data: {
  160. step: 2,
  161. orgId: this.orgId,
  162. certifyId,
  163. serversUrl: HTTP_REQUEST_URL
  164. }
  165. })
  166. if (certResult.result.code == 200) {
  167. this.successAfter()
  168. } else {
  169. uni.hideLoading()
  170. uni.showModal({
  171. title: '认证失败',
  172. content: certResult.result.msg,
  173. showCancel: false
  174. })
  175. }
  176. },
  177. fail: (e) => {
  178. uni.$u.toast(e.errMsg)
  179. }
  180. })
  181. }).catch(err => {
  182. uni.$u.toast('请求云函数失败:' + JSON.stringify(err))
  183. })
  184. },
  185. // #endif
  186. // 认证成功后的处理
  187. successAfter() {
  188. // 审核状态变更为:待审核
  189. store.commit('user/set_userStatus', 1)
  190. uni.showToast({
  191. title: '认证成功',
  192. icon: 'success',
  193. mask: true
  194. })
  195. setTimeout(() => {
  196. uni.switchTab({
  197. url: '/pages/index/index'
  198. })
  199. }, 1200)
  200. }
  201. }
  202. }
  203. </script>
  204. <style lang="scss" scoped>
  205. .btn {
  206. width: 440rpx;
  207. height: 88rpx;
  208. background: $linear-color;
  209. border-radius: 44rpx;
  210. font-size: 32rpx;
  211. color: #FFFFFF;
  212. line-height: 44rpx;
  213. margin-top: 102rpx;
  214. display: flex;
  215. flex-direction: row;
  216. align-items: center;
  217. justify-content: center;
  218. }
  219. </style>

这边也贴出页面中有 import 的几个文件,可以参考下

1、改成你们自己服务端的接口地址

  1. // @/api/user.js
  2. // 获取verify_token(百度云实名认证)
  3. export function getVerifyToken() {
  4. return uni.$u.http.get('/szg-ynf/api/app/userDetail/verifyIdentify')
  5. }
  6. // 实名认证成功
  7. export function h5VerifyIdentifyReturn() {
  8. return uni.$u.http.get('/szg-ynf/api/app/userDetail/h5VerifyIdentifyReturn')
  9. }

 2、改成你们自己的接口地址

  1. // @/config.js
  2. module.exports = {
  3. // 请求域名
  4. HTTP_REQUEST_URL: 'https://xxx.xxx.com',
  5. // h5地址
  6. H5_URL: 'https://xxx.xxx.com/h5',
  7. }

3、该文件可以直接复制去使用,不用修改。这也是uniapp官方封装的

  1. // @/utils/js_sdk/permission.js
  2. /**
  3. * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
  4. */
  5. var isIos
  6. // #ifdef APP-PLUS
  7. isIos = (plus.os.name == 'iOS')
  8. // #endif
  9. // #ifdef H5
  10. // 通过webview打开的h5中也是有plus环境的
  11. isIos = uni.getSystemInfoSync().platform == 'ios'
  12. // #endif
  13. // 判断推送权限是否开启
  14. function judgeIosPermissionPush() {
  15. var result = false
  16. var UIApplication = plus.ios.import('UIApplication')
  17. var app = UIApplication.sharedApplication()
  18. var enabledTypes = 0
  19. if (app.currentUserNotificationSettings) {
  20. var settings = app.currentUserNotificationSettings()
  21. enabledTypes = settings.plusGetAttribute('types')
  22. console.log('enabledTypes1:' + enabledTypes)
  23. if (enabledTypes == 0) {
  24. console.log('推送权限没有开启')
  25. } else {
  26. result = true
  27. console.log('已经开启推送功能!')
  28. }
  29. plus.ios.deleteObject(settings)
  30. } else {
  31. enabledTypes = app.enabledRemoteNotificationTypes()
  32. if (enabledTypes == 0) {
  33. console.log('推送权限没有开启!')
  34. } else {
  35. result = true
  36. console.log('已经开启推送功能!')
  37. }
  38. console.log('enabledTypes2:' + enabledTypes)
  39. }
  40. plus.ios.deleteObject(app)
  41. plus.ios.deleteObject(UIApplication)
  42. return result
  43. }
  44. // 判断定位权限是否开启
  45. function judgeIosPermissionLocation() {
  46. var result = false
  47. var cllocationManger = plus.ios.import('CLLocationManager')
  48. var status = cllocationManger.authorizationStatus()
  49. result = (status != 2)
  50. console.log('定位权限开启:' + result)
  51. // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
  52. /* var enable = cllocationManger.locationServicesEnabled();
  53. var status = cllocationManger.authorizationStatus();
  54. console.log("enable:" + enable);
  55. console.log("status:" + status);
  56. if (enable && status != 2) {
  57. result = true;
  58. console.log("手机定位服务已开启且已授予定位权限");
  59. } else {
  60. console.log("手机系统的定位没有打开或未给予定位权限");
  61. } */
  62. plus.ios.deleteObject(cllocationManger)
  63. return result
  64. }
  65. // 判断麦克风权限是否开启
  66. function judgeIosPermissionRecord() {
  67. var result = false
  68. var avaudiosession = plus.ios.import('AVAudioSession')
  69. var avaudio = avaudiosession.sharedInstance()
  70. var permissionStatus = avaudio.recordPermission()
  71. console.log('permissionStatus:' + permissionStatus)
  72. if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
  73. console.log('麦克风权限没有开启')
  74. } else {
  75. result = true
  76. console.log('麦克风权限已经开启')
  77. }
  78. plus.ios.deleteObject(avaudiosession)
  79. return result
  80. }
  81. // 判断相机权限是否开启
  82. function judgeIosPermissionCamera() {
  83. var result = false
  84. var AVCaptureDevice = plus.ios.import('AVCaptureDevice')
  85. var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide')
  86. console.log('authStatus:' + authStatus)
  87. if (authStatus == 3) {
  88. result = true
  89. console.log('相机权限已经开启')
  90. } else {
  91. console.log('相机权限没有开启')
  92. }
  93. plus.ios.deleteObject(AVCaptureDevice)
  94. return result
  95. }
  96. // 判断相册权限是否开启
  97. function judgeIosPermissionPhotoLibrary() {
  98. var result = false
  99. var PHPhotoLibrary = plus.ios.import('PHPhotoLibrary')
  100. var authStatus = PHPhotoLibrary.authorizationStatus()
  101. console.log('authStatus:' + authStatus)
  102. if (authStatus == 3) {
  103. result = true
  104. console.log('相册权限已经开启')
  105. } else {
  106. console.log('相册权限没有开启')
  107. }
  108. plus.ios.deleteObject(PHPhotoLibrary)
  109. return result
  110. }
  111. // 判断通讯录权限是否开启
  112. function judgeIosPermissionContact() {
  113. var result = false
  114. var CNContactStore = plus.ios.import('CNContactStore')
  115. var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0)
  116. if (cnAuthStatus == 3) {
  117. result = true
  118. console.log('通讯录权限已经开启')
  119. } else {
  120. console.log('通讯录权限没有开启')
  121. }
  122. plus.ios.deleteObject(CNContactStore)
  123. return result
  124. }
  125. // 判断日历权限是否开启
  126. function judgeIosPermissionCalendar() {
  127. var result = false
  128. var EKEventStore = plus.ios.import('EKEventStore')
  129. var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0)
  130. if (ekAuthStatus == 3) {
  131. result = true
  132. console.log('日历权限已经开启')
  133. } else {
  134. console.log('日历权限没有开启')
  135. }
  136. plus.ios.deleteObject(EKEventStore)
  137. return result
  138. }
  139. // 判断备忘录权限是否开启
  140. function judgeIosPermissionMemo() {
  141. var result = false
  142. var EKEventStore = plus.ios.import('EKEventStore')
  143. var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1)
  144. if (ekAuthStatus == 3) {
  145. result = true
  146. console.log('备忘录权限已经开启')
  147. } else {
  148. console.log('备忘录权限没有开启')
  149. }
  150. plus.ios.deleteObject(EKEventStore)
  151. return result
  152. }
  153. // Android权限查询
  154. function requestAndroidPermission(permissionID) {
  155. return new Promise((resolve, reject) => {
  156. plus.android.requestPermissions(
  157. [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
  158. function(resultObj) {
  159. var result = 0
  160. for (var i = 0; i < resultObj.granted.length; i++) {
  161. var grantedPermission = resultObj.granted[i]
  162. console.log('已获取的权限:' + grantedPermission)
  163. result = 1
  164. }
  165. for (var i = 0; i < resultObj.deniedPresent.length; i++) {
  166. var deniedPresentPermission = resultObj.deniedPresent[i]
  167. console.log('拒绝本次申请的权限:' + deniedPresentPermission)
  168. result = 0
  169. }
  170. for (var i = 0; i < resultObj.deniedAlways.length; i++) {
  171. var deniedAlwaysPermission = resultObj.deniedAlways[i]
  172. console.log('永久拒绝申请的权限:' + deniedAlwaysPermission)
  173. result = -1
  174. }
  175. resolve(result)
  176. // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
  177. // if (result != 1) {
  178. // gotoAppPermissionSetting()
  179. // }
  180. },
  181. function(error) {
  182. console.log('申请权限错误:' + error.code + ' = ' + error.message)
  183. resolve({
  184. code: error.code,
  185. message: error.message
  186. })
  187. }
  188. )
  189. })
  190. }
  191. // 使用一个方法,根据参数判断权限
  192. function judgeIosPermission(permissionID) {
  193. if (permissionID == 'location') {
  194. return judgeIosPermissionLocation()
  195. } else if (permissionID == 'camera') {
  196. return judgeIosPermissionCamera()
  197. } else if (permissionID == 'photoLibrary') {
  198. return judgeIosPermissionPhotoLibrary()
  199. } else if (permissionID == 'record') {
  200. return judgeIosPermissionRecord()
  201. } else if (permissionID == 'push') {
  202. return judgeIosPermissionPush()
  203. } else if (permissionID == 'contact') {
  204. return judgeIosPermissionContact()
  205. } else if (permissionID == 'calendar') {
  206. return judgeIosPermissionCalendar()
  207. } else if (permissionID == 'memo') {
  208. return judgeIosPermissionMemo()
  209. }
  210. return false
  211. }
  212. // 跳转到**应用**的权限页面
  213. function gotoAppPermissionSetting() {
  214. if (isIos) {
  215. var UIApplication = plus.ios.import('UIApplication')
  216. var application2 = UIApplication.sharedApplication()
  217. var NSURL2 = plus.ios.import('NSURL')
  218. // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
  219. var setting2 = NSURL2.URLWithString('app-settings:')
  220. application2.openURL(setting2)
  221. plus.ios.deleteObject(setting2)
  222. plus.ios.deleteObject(NSURL2)
  223. plus.ios.deleteObject(application2)
  224. } else {
  225. // console.log(plus.device.vendor);
  226. var Intent = plus.android.importClass('android.content.Intent')
  227. var Settings = plus.android.importClass('android.provider.Settings')
  228. var Uri = plus.android.importClass('android.net.Uri')
  229. var mainActivity = plus.android.runtimeMainActivity()
  230. var intent = new Intent()
  231. intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
  232. var uri = Uri.fromParts('package', mainActivity.getPackageName(), null)
  233. intent.setData(uri)
  234. mainActivity.startActivity(intent)
  235. }
  236. }
  237. // 检查系统的设备服务是否开启
  238. // var checkSystemEnableLocation = async function () {
  239. function checkSystemEnableLocation() {
  240. if (isIos) {
  241. var result = false
  242. var cllocationManger = plus.ios.import('CLLocationManager')
  243. var result = cllocationManger.locationServicesEnabled()
  244. console.log('系统定位开启:' + result)
  245. plus.ios.deleteObject(cllocationManger)
  246. return result
  247. } else {
  248. var context = plus.android.importClass('android.content.Context')
  249. var locationManager = plus.android.importClass('android.location.LocationManager')
  250. var main = plus.android.runtimeMainActivity()
  251. var mainSvr = main.getSystemService(context.LOCATION_SERVICE)
  252. var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)
  253. console.log('系统定位开启:' + result)
  254. return result
  255. }
  256. }
  257. module.exports = {
  258. judgeIosPermission: judgeIosPermission,
  259. requestAndroidPermission: requestAndroidPermission,
  260. checkSystemEnableLocation: checkSystemEnableLocation,
  261. gotoAppPermissionSetting: gotoAppPermissionSetting
  262. }

因为uniapp 的实人认证需要配合 uniCloud服务空间使用,所以这边贴上服务空间上云函数的代码

目录结构:

  1. // index.js 云函数
  2. 'use strict'
  3. const crypto = require('crypto')
  4. exports.main = async (event, context) => {
  5. // 获取实人认证实例
  6. const frvManager = await uniCloud.getFacialRecognitionVerifyManager({ requestId: context.requestId })
  7. if (event.step == 1) {
  8. try {
  9. /**
  10. * 获取certifyId
  11. * @return certifyId 认证id,用于客户端调用认证接口及云函数获取认证结果
  12. */
  13. const result = await frvManager.getCertifyId({
  14. realName: event.legalPerson,
  15. idCard: event.idCard,
  16. metaInfo: event.metaInfo
  17. })
  18. if (result.errCode == 0) return { code: 200, data: result.certifyId, msg: '获取certifyId成功' }
  19. return { code: 500, data: '', msg: `获取certifyId失败:${ result.errMsg }` }
  20. } catch (err) {
  21. return { code: 500, data: '', msg: '请检查您填写的姓名与身份证号是否正确' }
  22. }
  23. } else {
  24. // 获取认证结果
  25. const result = await frvManager.getAuthResult({ certifyId: event.certifyId })
  26. // 认证失败
  27. if (result.authState == 'FAIL') return { code: 500, data: result.certifyId, msg: `认证失败:${ result.errMsg }` }
  28. // 认证成功
  29. // 这里改成你们服务端的认证成功后的接口地址...
  30. // 服务端的接口为了安全起见,所以进行了加密验签
  31. const url = event.serversUrl + '/szg-ynf/oauth/userDetail/verifyIdentify'
  32. // md5加密方式:orgId 时间戳 私钥
  33. const orgId = event.orgId
  34. const timestamp = new Date().getTime()
  35. const signKey = '2bba3152-0b82-bd8e-2afd-453b0d925ea4'
  36. const sign = crypto.createHash('md5').update(orgId + timestamp + signKey).digest('hex')
  37. const res = await uniCloud.httpclient.request(url, {
  38. method: 'POST',
  39. data: {
  40. orgId,
  41. timestamp,
  42. sign
  43. },
  44. contentType: 'json',
  45. dataType: 'json',
  46. rejectUnauthorized: false
  47. })
  48. return { code: res.data.code, data: res.data.data, msg: res.data.msg }
  49. }
  50. }
  1. // package.json 云函数
  2. {
  3. "name": "livenessDetection",
  4. "dependencies": {},
  5. "extensions": {
  6. "uni-cloud-verify": {}
  7. }
  8. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/280539?site
推荐阅读
相关标签
  

闽ICP备14008679号