최근 위챗 비밀번호 빨간봉투 기능이 출시되려는데 사장님이 갑자기 걱정이 되시더라구요. 요즘 울 파티가 너무 심해서 조심하지 않으면 10만짜리 판촉용 빨간 봉투가 두 개로 다 써버릴 것 같다고 하더군요. .... 그럼 같은 사람이 빨간 봉투를 받았는지 확인하는 함수를 만들 수 있을까요? 이 정도면 충분하지 않나요? 그는 계속해서 "톰, 성문 인식을 해주세요!"라고 말했습니다.
구체적인 과정은 다음과 같습니다.
성문 등록 사용자(최종 렌더링)
성문 로그인(최종 렌더링)
업로드 파일 식별:
pm2 스레드
성문인식 서비스 제공업체에서는 클라이언트를 이용해 직접 통화를 할 수 없고, 음성도 지원하지 않기 때문에 자체 서버 개발이 필요하다.
기술 스택 koa + co-wecaht-api + mysql + ffmpeg + pm2 + knex
참고: 서비스 제공업체는 WeChat amr 파일을 지원하지 않으므로 WeChat 오디오 amr 파일을 wav로 트랜스코딩하려면 ffmpeg를 사용해야 합니다.
다음은 일부 관련 코드입니다. .
WeChat jssdk 개발 WeChat API에 이미 익숙하다면 다음 섹션으로 건너뛰세요.
위챗 토큰 받기
var api = await new WechatAPI (
config . appid ,
config . appsecret ,
async ( ) => {
// 传入一个获取全局token的方法
var txt = await fs . readFile ( "./token/access_token.txt" , "utf8" ) ;
return JSON . parse ( txt ) ;
} ,
async token => {
// 请将token存储到全局,跨进程、跨机器级别的全局,比如写到数据库、redis等
// 这样才能在cluster模式及多机情况下使用,以下为写入到文件的示例
await fs . writeFile ( "./token/access_token.txt" , JSON . stringify ( token ) ) ;
}
) ;
참고: 토큰 파일을 읽을 수 없는 경우 해당 디렉터리에 access_token.txt와 같은 새 텍스트 파일을 수동으로 생성하십시오.
WeChat 서명 받기
var jsapi_ticket = await api . getLatestTicket ( ) ;
let nonce_str = 'abcdefg' ; // 密钥,字符串任意,可以随机生成
let timestamp = parseInt ( new Date ( ) . getTime ( ) / 1000 ) + '' ; // 时间戳
let url = ctx . request . body . url ; // 使用接口的url链接,不包含#后的内容
let str = 'jsapi_ticket=' + jsapi_ticket . ticket + '&noncestr=' + nonce_str + '×tamp=' + timestamp + '&url=' + url ;
let signature = sha1 ( str ) ;
ctx . body = {
appId : config . appid ,
timestamp : timestamp ,
nonceStr : nonce_str ,
signature : signature
}
도메인 간 요청
const Koa = require ( "koa" ) ;
const app = new Koa ( ) ;
const cors = require ( "koa-cors" ) ;
... . .
app . use (
cors ( {
origin : "http://www.xxxx.com" ,
maxAge : 5 ,
credentials : true ,
allowMethods : [ "OPTIONS" , "GET" , "POST" , "DELETE" ] ,
allowHeaders : [ 'Content-Type' , 'Accept' ]
} )
) ;
ffmpeg 트랜스코딩
const ffmpeg = require ( 'fluent-ffmpeg' ) ;
... .
var command = ffmpeg ( _delPath . amr )
. audioBitrate ( '16k' ) //16k音频采样率
. audioFrequency ( 16000 ) //16比特音频信号
. audioQuality ( 10 ) //音频质量
. on ( 'end' , function ( ) {
console . log ( 'file has been converted succesfully' ) ;
resolve ( ) ;
} )
. on ( 'error' , function ( err ) {
reject ( err . message )
console . log ( 'an error happened: ' + err . message ) ;
} )
. save ( _delPath . fix ) ;
성문 서버 제출
const rp = require ( "request-promise" ) ;
... . .
var vprData = {
method : "POST" ,
url : "http://www.xxxx.com" ,
headers : {
"cache-control" : "no-cache" ,
"x-udid" : "xxxxxx" ,
"x-session-key" : "xxxx" ,
"x-task-config" : "xxxxxx" ,
"x-request-date" : "xxxxxx" ,
"x-sdk-version" : "5.1" ,
"x-app-key" : "xxxxxxx"
} ,
formData : {
// Like <input type="file" name="file">
file : {
value : fs . createReadStream ( soundData . path ) ,
options : {
filename : soundData . name ,
contentType : soundData . type //mp3 = audio/mpeg, wav = audio/wav
}
}
}
} ;
var xml = await rp ( vprData ) ;
//xml to json
var resJson = { } ;
var parseString = require ( 'xml2js' ) . parseString ;
await new Promise ( ( resolve , reject ) => {
parseString ( xml . toString ( ) , async ( err , result ) => {
resJson = result . ResponseInfo ;
//do something
resolve ( ) ;
} ) ;
} ) ;
기술 스택 vue + vue-router + axios.
WeChat에서 길게 누르기 팝업 복사 버튼 제거
mounted ( ) {
document . oncontextmenu = function ( e ) {
e . preventDefault ( ) ;
} ;
//初始化 微信jssdk
vm . wx_init ( ) ;
}
WeChat 서명 받기 및 이벤트 등록
wx . config ( {
debug : false , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId : res . appId , // 必填,公众号的唯一标识
timestamp : res . timestamp , // 必填,生成签名的时间戳
nonceStr : res . nonceStr , // 必填,生成签名的随机串
signature : res . signature , // 必填,签名,见附录1
jsApiList : [
"onMenuShareTimeline" ,
"onMenuShareAppMessage" ,
"uploadVoice" ,
"startRecord" ,
"playVoice" ,
"stopRecord" ,
"onVoicePlayEnd"
] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
} ) ;
녹음이 정식으로 시작될 때 녹음 기능을 승인하라는 메시지가 동시에 표시되지 않도록 사전에 사용자에게 녹음 기능을 승인하라는 메시지를 표시합니다. 이때 녹음 기능 상태는 제어할 수 없습니다.
if ( ! localStorage . rainAllowRecord || localStorage . rainAllowRecord !== "true" ) {
wx . startRecord ( {
success : function ( ) {
localStorage . rainAllowRecord = "true" ;
wx . stopRecord ( ) ;
} ,
cancel : function ( ) {
alert ( "用户拒绝授权录音" ) ;
}
} ) ;
}
좋아요, 얘기는 싸구려입니다. 코드를 보여주세요.
사용방법
git clone https: //github.com/ssttm169/tom-vpr.git
cd server
npm i / yarn
npm run dev //本地开发
npm start //服务器跑
//或者
cd client
npm i / yarn
npm run dev //本地开发
npm start //服务上跑客户端