当前位置:   article > 正文

微信小程序音视频通话_wmpfvoip.onvoipevent

wmpfvoip.onvoipevent
  1. const log = require("./log");
  2. const util = require('./util');
  3. const crypt = require('./WXBizMsgCrypt');
  4. const wmpfVoip = requirePlugin('wmpf-voip').default
  5. // 判断当前是否为设备端拉起小程序
  6. const isWmpf = (typeof wmpf !== 'undefined');
  7. // 指定接听方使用的小程序版本。formal/正式版(默认);trial/体验版;developer/开发版
  8. const miniprogramState = (() => {
  9. const accountInfo = wx.getAccountInfoSync();
  10. if(accountInfo && accountInfo.miniProgram){
  11. const platform = { develop: 'developer', trial: 'trial', release: 'formal' }
  12. return platform[accountInfo.miniProgram.envVersion]
  13. }
  14. })()
  15. console.log('miniprogramState='+miniprogramState)
  16. // 「设备接入」从微信公众平台获取的 model_id
  17. const modelId = 'DSAF58AS5F3SA2FD2SA33DS55';
  18. // 设备名称,用于授权时显示给用户
  19. const deviceName = '好宝宝';
  20. // 通话监听
  21. const onVoipEvent = () => {
  22. wmpfVoip.onVoipEvent((event) => {
  23. const eventName = event.eventName;
  24. // 定义挂断事件
  25. const filterEvent = ['hangUpVoip', 'cancelVoip', 'timeout', 'rejectVoip'];
  26. // 挂断动作向设备端发送消息通知
  27. if(eventName == 'endVoip' || filterEvent.indexOf(eventName) > -1){
  28. // 每次通话只能推送一次挂断信息
  29. if(event.groupId && wx.getStorageSync('currcall') != event.groupId){
  30. sendMsgDevice('EndVoip');
  31. wx.setStorageSync('currcall', event.groupId)
  32. log.info('通知设备关闭小程序')
  33. }
  34. }
  35. // 通话记录参数
  36. const callData = {
  37. groupId: event.groupId,
  38. params: {
  39. eventName: eventName, data: event.data
  40. },
  41. }
  42. // 挂断上报通话记录
  43. filterEvent.indexOf(eventName) > -1 && updateCallRecord(callData)
  44. // 为避免上面几种情况执行异常,在结束通话时再次上报,延迟执行是为了避免并发
  45. if(eventName == 'endVoip'){
  46. setTimeout(() => {
  47. updateCallRecord(callData);
  48. }, 1500)
  49. }
  50. // 非通话中,打印调试
  51. (eventName != 'calling') && log.info(`onVoipEvent`, event);
  52. // 设备打微信,微信端插件通话页面 onShow
  53. if(eventName == 'callPageOnShow' && !isWmpf){
  54. setUIConfig(1)
  55. }
  56. })
  57. }
  58. // 设置通话结束跳转地址
  59. const setVoipEndPagePath = (recordId) => {
  60. if(!isWmpf){
  61. wmpfVoip.setVoipEndPagePath({
  62. url: '/pages/call/index',
  63. key: 'Call',
  64. })
  65. }
  66. }
  67. /**
  68. * 小程序传递消息给设备
  69. * @param {*} command
  70. */
  71. const sendMsgDevice = (command) => {
  72. if(isWmpf){
  73. wmpf.Channel.invoke({
  74. command: command,
  75. success: function(res) {
  76. wx.setStorageSync(command+'_invoke', 1)
  77. setTimeout(() => {
  78. wx.removeStorageSync(command+'_invoke');
  79. }, 1000)
  80. log.info('wmpf.Channel.invoke success:', res.data)
  81. },
  82. fail: function(res){
  83. log.error('wmpf.Channel.invoke fail:', res);
  84. }
  85. })
  86. }
  87. }
  88. /**
  89. * 微信打设备
  90. * @param {拨打方用户 openId} openid
  91. * @param {拨打对方用户信息 name:拨打方名字,仅显示用;roomType:voice音频房间,video音视频房间;voipToken:从设备获取的 pushToken} contact
  92. */
  93. const wechatCallDevice = (contact) => {
  94. wx.showLoading({title: '呼叫中',mask: true}), setTimeout(() => {wx.hideLoading()}, 3000)
  95. const initByCaller = async (config, data) => {
  96. log.info('====>通话请求参数', data, config)
  97. setUIConfig(2);
  98. const { groupId, isSuccess, errCode, errMsg } = await wmpfVoip.initByCaller(data)
  99. wx.hideLoading();
  100. if (isSuccess) {
  101. requestCallVoip(groupId, data.roomType, 0, config);
  102. const callPagePlugin = 'plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin'
  103. wx.redirectTo({
  104. url: `${callPagePlugin}?isCaller=1&roomType=${data.roomType}&groupId=${groupId}`,
  105. })
  106. } else {
  107. log.error('拨打请求失败:errCode='+errCode+';errMsg='+errMsg, config, data)
  108. if(errCode == 14){
  109. return wx.showToast({title: '手机微信拨打硬件设备模式,voipToken 错误',icon: 'error'})
  110. }
  111. wx.showToast({title: '拨打失败',icon: 'error'})
  112. }
  113. }
  114. const init = () => {
  115. checkDeviceAuth(contact.deviceId, ()=>{
  116. getCallConfigParams(contact.id, contact.relId, (config) => {
  117. initByCaller(config, {
  118. caller: {
  119. id: config.openid, name: config.name
  120. },
  121. listener: {
  122. id: config.deviceId
  123. },
  124. roomType: contact.roomtype,
  125. voipToken: config.pushToken,
  126. businessType: 2,
  127. miniprogramState: miniprogramState,
  128. })
  129. })
  130. })
  131. }
  132. // 通话结束延长1秒才能再次拉起通话,0.2秒检查一次
  133. const checkCallEnd = () => {
  134. if(wx.getStorageSync('EndVoip_invoke')){
  135. setTimeout(() => {
  136. checkCallEnd();
  137. }, 200)
  138. }else{
  139. init()
  140. }
  141. }
  142. checkCallEnd();
  143. }
  144. /**
  145. * 设备拨打微信
  146. */
  147. const deviceCallWechat = () => {
  148. const { query } = wmpfVoip.getPluginEnterOptions()
  149. log.info('====>设备拨打微信传参:', query)
  150. setUIConfig(query.isCaller === '1' ? 3 : 4);
  151. if(query.isPreLaunch == 'false' && query.isCaller === '1' && query.contactId){
  152. var contactId = query.contactId;
  153. var relId = query.deviceId;
  154. if(query.isRecord == '1'){
  155. contactId = -2;
  156. relId = query.contactId;
  157. }
  158. wx.setStorageSync('token', query.token);
  159. getCallConfigParams(contactId, relId, (config) => {
  160. wmpfVoip.initByCaller({
  161. caller: {
  162. id: query.deviceId
  163. },
  164. listener: {
  165. id: config.openid,name: config.name
  166. },
  167. roomType: query.roomType,
  168. voipToken: query.voipToken,
  169. businessType: 1,
  170. miniprogramState: miniprogramState,
  171. }).then((res)=>{
  172. log.info('===========>设备打微信initByCaller success', res);
  173. res.isSuccess && requestCallVoip(res.groupId, query.roomType, 1, config);
  174. if(!res.isSuccess){
  175. if(res.errCode == 9){
  176. wx.showToast({title: '未授权设备无法使用通话功能',icon: 'error'})
  177. }
  178. if(res.errCode == 13){
  179. // 传递参数给设备处理
  180. sendMsgDevice('VoipTokenErr13');
  181. }
  182. sendMsgDevice('errorEnd');
  183. }
  184. }).catch((e) => {
  185. sendMsgDevice('errorEnd');
  186. log.error('==========>设备打微信initByCaller fail', e);
  187. })
  188. }, () => {
  189. sendMsgDevice('errorEnd');
  190. })
  191. }
  192. }
  193. /**
  194. * 获取通话配置参数
  195. * @param {通讯录id} contactId
  196. */
  197. const getCallConfigParams = (contactId, relId, callback, errback) => {
  198. util.rqt({
  199. url: '/eeop/wechatcall/getCallConfig',
  200. data: {
  201. id: contactId,appid: crypt.appid,relId: relId
  202. },
  203. callBack(res){
  204. const encryptOpenid = res.data.encryptOpenid;
  205. if(!encryptOpenid){
  206. errback && errback();
  207. log.error('获取配置参数openid失败', res.data);
  208. return;
  209. }
  210. res.data.openid = crypt.decrypt(encryptOpenid.TimeStamp, encryptOpenid.Nonce, encryptOpenid.Encrypt, encryptOpenid.MsgSignature);
  211. callback && callback(res.data);
  212. },
  213. errCallBack(res){
  214. errback && errback();
  215. log.error('请求后台配置出现异常', res);
  216. }
  217. })
  218. }
  219. /**
  220. * 拨打电话
  221. */
  222. const requestCallVoip = (groupId, roomType, callWay, config) => {
  223. updateCallRecord({
  224. groupId: groupId,
  225. userId: config.userId,
  226. deviceId: config.deviceId,
  227. callType: (roomType == 'video' ? 1 : 0),
  228. callWay: callWay,
  229. params: {
  230. eventName: 'startVoip'
  231. }
  232. })
  233. }
  234. const updateCallRecord = (data) => {
  235. util.rqt({
  236. url: '/eeop/wechatcall/updateCallRecord',
  237. method: 'POST',
  238. data: data,
  239. callBack(res){
  240. log.info('上报通话返回结果', res, data);
  241. },
  242. errCallBack(res){
  243. log.error('上报通话数据返回异常', res, data)
  244. }
  245. })
  246. }
  247. /**
  248. * 添加联系人
  249. * @param {*} options
  250. * @param {*} callback
  251. */
  252. const addContact = (options, callback) => {
  253. if(!options.deviceId || !options.code){
  254. return wx.showToast({title: '扫描失败',icon: 'none'})
  255. }
  256. checkDeviceAuth(options.deviceId, () => {
  257. util.rqt({
  258. url: '/eeop/wechatcall/bind',
  259. data: options,
  260. callBack(res){
  261. open('添加成功', true);
  262. },
  263. errCallBack(res){
  264. if(res.code == 3010){
  265. return open('二维码已过期', false);
  266. }
  267. open(res.msg, false);
  268. }
  269. })
  270. const open = (content, status) => {
  271. wx.showToast({
  272. title: content, icon: 'none',
  273. success(res){
  274. setTimeout(() => {
  275. callback && callback(status);
  276. }, 1500)
  277. }
  278. })
  279. }
  280. })
  281. }
  282. /**
  283. * 更新token
  284. */
  285. const updatePushToken = () => {
  286. // 根据设备deviceId更新token信息到后台服务器
  287. const updatePushToken = (deviceId, pushToken) => {
  288. util.rqt({
  289. url: '/eeop/wechatcall/pushToken',
  290. data: {
  291. deviceId: deviceId,pushToken: pushToken
  292. },
  293. callBack(result){
  294. log.info('=====>设备端拉起小程序时向后台请求更新token返回结果callBack:deviceId='+deviceId+';pushToken='+pushToken, result);
  295. },
  296. errCallBack(result){
  297. log.info('=====>设备端拉起小程序时向后台请求更新token返回结果errCallBack:deviceId='+deviceId+';pushToken='+pushToken, result);
  298. }
  299. });
  300. }
  301. // 获取pushToken
  302. const getWmpfPushToken = (deviceId) => {
  303. log.info('=====>获取pushToken', deviceId);
  304. wmpf.getWmpfPushToken({
  305. success(res){
  306. log.info('=====>wmpf.getWmpfPushToken success', res);
  307. const pushToken = res.token;
  308. if(pushToken && pushToken != 'undefined'){
  309. updatePushToken(deviceId, pushToken);
  310. }
  311. },
  312. fail(res){
  313. log.error('=====>wmpf.getWmpfPushToken fail', res);
  314. }
  315. })
  316. }
  317. // 获取设备deviceId
  318. const { query } = wmpfVoip.getPluginEnterOptions()
  319. log.info('设备拉起小程序获取参数:', query);
  320. query.token && wx.setStorageSync('token', query.token);
  321. query.deviceId && getWmpfPushToken(query.deviceId);
  322. }
  323. /**
  324. * 检测是否授权
  325. * @param {用户信息} contact
  326. */
  327. const checkDeviceAuth = (deviceId, callback) => {
  328. const requestDeviceVoIP = (snTicket) => {
  329. wx.hideLoading();
  330. wx.requestDeviceVoIP({
  331. sn: deviceId, // 向用户发起通话的设备 sn(需要与设备注册时一致)
  332. snTicket: snTicket, // 获取的 snTicket
  333. modelId: modelId, // 「设备接入」从微信公众平台获取的 model_id
  334. deviceName: deviceName, // 设备名称,用于授权时显示给用户
  335. success(res) {
  336. callback && callback();
  337. log.info(`requestDeviceVoIP success:`, res)
  338. },
  339. fail(err) {
  340. if(err.errCode == 10021){
  341. wx.showModal({
  342. title: '是否要打开设置页面',
  343. content: '需要获取您的音视频通话授权信息,请到小程序的设置中打开授权',
  344. success(res) {
  345. res.confirm && wx.openSetting()
  346. }
  347. })
  348. }
  349. log.error(`requestDeviceVoIP fail:`, err)
  350. },
  351. })
  352. }
  353. const getSnTicket = () => {
  354. util.rqt({
  355. url: '/eeop/wechatcall/setting/getSnTicket',
  356. data: {
  357. deviceId: deviceId
  358. },
  359. callBack(res){
  360. requestDeviceVoIP(res.data.snTicket)
  361. },
  362. errCallBack(res){
  363. log.error(`getSnTicket fail:`, err)
  364. }
  365. })
  366. }
  367. util.checkWechatVersion('2.30.3') && wx.getDeviceVoIPList({
  368. success(res) {
  369. log.info('当前用户授权的设备:', res.list)
  370. const isAuth = res.list.some(element => {
  371. return element.sn == deviceId && element.status == 1;
  372. })
  373. if(isAuth){
  374. callback && callback()
  375. }else{
  376. getSnTicket();
  377. }
  378. }
  379. })
  380. }
  381. /**
  382. * 自定义UI相关配置
  383. * @param {拨打场景: 1设备打微信,微信端接听,微信端设置;2微信打设备,微信端设置;3设备打微信,设备端设置;4微信打设备,设备端接听,设备端设置} scene
  384. */
  385. const setUIConfig = (scene) => {
  386. return;
  387. // 显示设备端
  388. var UI_1 = {
  389. cameraRotation: 0, // caller的视频画面旋转角度,有效值为 0, 90, 180, 270。默认 0
  390. aspectRatio: 3/4, // 纵横比,caller的视频画面会进行适配比例,有效值 数字。默认 4/3
  391. horMirror: false, // 横向镜像,boolean 值,默认 false
  392. vertMirror: false, // 竖直镜像,同上
  393. enableToggleCamera: false, // 是否支持切换摄像头,false 则不显示「摄像头开关」按钮。默认false 【该配置项在wmpf无效,wmpf默认开摄像头,且不显示开关按钮】
  394. }
  395. // 显示微信端
  396. var UI_2 = {
  397. cameraRotation: 0,
  398. aspectRatio: 4/3,
  399. horMirror: false,
  400. vertMirror: false,
  401. enableToggleCamera: false,
  402. }
  403. if(scene == 1){
  404. wmpfVoip.setUIConfig({
  405. btnText: null,
  406. callerUI: UI_1,
  407. listenerUI: UI_2
  408. })
  409. }
  410. if(scene == 2){
  411. wmpfVoip.setUIConfig({
  412. btnText: null,
  413. callerUI: UI_1,
  414. listenerUI: UI_2
  415. })
  416. }
  417. if(scene == 3){
  418. wmpfVoip.setUIConfig({
  419. btnText: null,
  420. callerUI: UI_1,
  421. listenerUI: UI_2
  422. })
  423. }
  424. if(scene == 4){
  425. wmpfVoip.setUIConfig({
  426. btnText: null,
  427. callerUI: UI_2,
  428. listenerUI: UI_1
  429. })
  430. }
  431. }
  432. module.exports = {
  433. isWmpf, updatePushToken, wechatCallDevice, deviceCallWechat, checkDeviceAuth, onVoipEvent, setVoipEndPagePath, addContact
  434. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/686943
推荐阅读
相关标签
  

闽ICP备14008679号