评论

云函数特约商户进件

技术小白,有坑欢迎指出~

// 云函数入口文件
var cloud = require('wx-server-sdk')
   crypto = require('crypto')
    request = require('request')
   NodeRSA = require('node-rsa')//npm安装
   Form = require('./Form.class')
      //Form 源自北望大佬https://https://developers.weixin.qq.com/community/develop/article/doc/000c24f0390ff8b5d91b2489059413
cloud.init({
  env: 'xxxxxx'
})
const db = cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
  const rq = options =>new Promise((resolve, reject) => {
    request(options, (error, response, body) => {
      if (error) {
        reject(error);
      }
      resolve(response);
    })
  })
  // 基本参数
  var mchid ='160xxxxx92'//服务商商户号
  var appId = 'wx41xxxxxxfd6' //服务商和直连商户的appId
  var APIv3Key = 'xxxxxxxxx'//服务商APIv3密钥
  var cert_Doc = 'certificates' //存在数据库的证书记录的_id
  var timeStamp = parseInt(Date.now()/1000)
  var nonce_str = Math.random().toString(36).substr(2, 13)
  var url = 'https://api.mch.weixin.qq.com'+event.url
  //证书与私钥
  var certificates = (await db.collection('a-data').doc(cert_Doc).get()).data //存在数据库的证书
  /* 证书记录json如下:
    "_id":"certificates",
    "apiclient_key":"-----BEGIN PRIVATE KEY---- xxxxxxx",//商户证书私钥
    "serial_no":"3A008xxxxxxxxxxxxxxxx335DABA0",//商户证书序列号
    "wx_publicKey":"-----BEGIN PUBLIC KEY-----xxxxxxxxx",//商户对应微信支付平台证书公钥
    "wx_serial_no":"32EDFA40A4xxxxxxxxxxx3FAFC91C",////商户对应微信支付平台证书序列号
  */
  var {serial_no} = certificates
  var {wx_serial_no} = certificates
  // 敏感信息加密
  var RSAoaep = (e)=>{
    var plaintext = crypto.publicEncrypt({
      key: certificates.wx_publicKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
    },Buffer.from(e))
    return plaintext.toString('base64')
  }
  // getHeaders
  const getHeaders = (method,meta)=>{
    var signature = new NodeRSA(certificates.apiclient_key).sign(`${method}\n${event.url}\n${timeStamp}\n${nonce_str}\n${meta}\n`, 'base64', 'utf8')
    var Authorization = `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",nonce_str="${nonce_str}",signature="${signature}",timestamp="${timeStamp}",serial_no="${serial_no}"`
    return {Authorization,"Content-Type": "application/json",Accept: "application/json","User-Agent": "xxxx.com",}
  }
   // 特约商户进件:提交申请单
  if(event.url=='/v3/applyment4sub/applyment/'){
    /*入参 upload:{
      _id:'xxx',//记录_id
      id_card_number:'xxx',/超管身份证号,注:默认法人为超管
      mobile_phone:'xxx',/超管电话
      contact_email:'xxx',//超管邮箱
      account_number:'xxx',//对公/经营者银行账户号
      post:{..}//待提交表单
    }
    */
    var {upload} = event
    var {post} = upload
    post.business_code = upload._id
    var {legal_person} = post.subject_info.business_license_info
    legal_person = RSAoaep(legal_person)
    var id_card_number = RSAoaep(upload.id_card_number)
    //超管信息
    post.contact_info.contact_name = legal_person
    post.contact_info.contact_id_number = id_card_number
    post.contact_info.mobile_phone = RSAoaep(upload.mobile_phone)
    post.contact_info.contact_email = RSAoaep(upload.contact_email)
    // 法人信息
    post.subject_info.identity_info.id_card_info.id_card_name = legal_person
    post.subject_info.identity_info.id_card_info.id_card_number = id_card_number
    //银行卡信息
    post.bank_account_info.account_name = (post.bank_account_info.bank_account_type=='BANK_ACCOUNT_TYPE_PERSONAL'?legal_person:RSAoaep(post.subject_info.business_license_info.merchant_name))
    post.bank_account_info.account_number =RSAoaep(upload.account_number)
    console.log(post)
    var method = 'POST'
    var meta = JSON.stringify(post)
    var res = await rq({url, method,
      headers:{
        ...getHeaders(method,meta),
        "Wechatpay-Serial":wx_serial_no
      },
      body:meta,
    })
    return res
  }
  // 特约商户进件:图片上传接口
  if(event.url=='/v3/merchant/media/upload'){
    var file = (await rq({method: 'GET',url:event.imgUrl,encoding: null})).body //event.imgUrl 图片地址
    var filename = `${nonce_str}${/\.\w+$/.exec(event.imgUrl)[0]}`
    var sha256 = crypto.createHash('sha256').update(file).digest('hex')
    var meta = JSON.stringify({filename,sha256})
    var form = new Form 
    form.append('file',file,filename).append('meta',meta,'meta.json')
    var method = 'POST'
    var res = await rq({url, method,
      headers:{
        ...getHeaders(method,meta),
        ...form.getHeaders(),
      },
      body:form.getBuffer(),
    })
    return JSON.parse(res.body)
  }
  // 特约商户进件:查询申请单状态
  if(event.url.indexOf('/v3/applyment4sub/applyment/business_code')>-1||event.url.indexOf('/v3/applyment4sub/applyment/applyment_id')>-1){
    var method = 'GET'
    var res = await rq({url,method,
      json:true,
      headers:{...getHeaders(method,'')}
    })
    return res.body
  }
})
点赞 3
收藏
评论

1 个评论

  • 北望沣渭
    北望沣渭
    2022-02-23

    node-rsa 包可以省掉,用如下代码替代:

    crypto.createSign('sha256WithRSAEncryption').update(`${method}\n${event.url}\n${timeStamp}\n${nonce_str}\n${meta}\n`).sign(certificates.apiclient_key, 'base64');
    
    2022-02-23
    赞同 1
    回复 1
    • 关家宝
      关家宝
      2022-02-23
      北望大佬d=====( ̄▽ ̄*)b
      2022-02-23
      回复
登录 后发表内容