Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

接入Unipush #3

Open
hankeke opened this issue Apr 11, 2023 · 0 comments
Open

接入Unipush #3

hankeke opened this issue Apr 11, 2023 · 0 comments

Comments

@hankeke
Copy link
Contributor

hankeke commented Apr 11, 2023

  1. 获取推送令牌 get-token

import cloud from '@/cloud-sdk'
import * as crypto from 'crypto'
const config = cloud.shared.get('unipush.config')
import * as axios from 'axios'

const { baseUrl, appKey, masterSecret } = config

exports.main = async function (ctx) {
  const hashParam = appKey + Date.now() + masterSecret
  const param = {
    "appkey": appKey,
    "timestamp": Date.now(),
    "sign": hashSign(hashParam)
  }
  const instance = axios.default.create({
    baseURL: baseUrl
  })
  const res = await instance.post('/auth', param)
  return res.data
}


/**
 * @param {string} content
 * @return {string}
 */
function hashSign(content: string): string {
  return crypto
    .createHash('sha256')
    .update(content)
    .digest('hex')
}
  1. 个推 push-single

import cloud from '@/cloud-sdk'
import * as axios from 'axios'
const config = cloud.shared.get('unipush.config')
const { baseUrl } = config
/**
* 入参:
*  cid: 通过用户id查询到的cid
*  title: 标题 长度<= 50
*  body: 通知内容 长度 <= 256
*  click_type: url/none/startapp/payload(自定义消息内容启动应用)/intent(打开应用内特定页面)
*  url: 当click_type为url时必填
*  intent: 当click_type为intent时必填
*  channel_level: 设置通知渠道重要性(可以控制响铃,震动,浮动,闪灯等等) 0/1/2/3/4
* 
*   const body:any = {
  cid: 'c190325c12369d231bd5264c6b4de01f',
  title: '123',
  body: '222',
  click_type: 'none',
  channel_level:4
}
*/

exports.main = async function (ctx) {
 const { data: { token } } = await cloud.invoke('get-token', {})
 if (!token) return { error: '获取token失败', code: -1 }
 const requestParam: any = {
   "request_id": getRnd32(),
   "settings": {
     "ttl": -1,
     // "speed": 100,  //  个推控制下发速度在100条/秒左右
     /**
       1: 表示该消息在用户在线时推送个推通道,用户离线时推送厂商通道;
       2: 表示该消息只通过厂商通道策略下发,不考虑用户是否在线;
       3: 表示该消息只通过个推通道下发,不考虑用户是否在线;
       4: 表示该消息优先从厂商通道下发,若消息内容在厂商通道代发失败后会从个推通道下发。
      */
     "strategy": { // 通过strategy控制是推送个推通道的消息还是厂商通道的消息
       "default": 3
     }
   },
   "audience": {
     "cid": [
       body.cid
     ]
   },
   "push_message": { // 个推通道消息类容 
     "notification": {
       "title": body.title,
       "body": body.body,
       "click_type": body.click_type,
       "channel_level": body.channel_level
     }
   },
   "push_channel": { // 厂商通道内容
     "android": {
       "ups": {
         "notification": {
           "title": body.title,
           "body": body.body,
           "click_type": body.click_type,
           "channel_level": body.channel_level
         }
       }
     }
   }
 }
 if (body.click_type == 'url') {
   requestParam.push_message.url = body.url
   requestParam.push_channel.android.ups.url = body.url
 }
 if (body.click_type == 'intent') {
   requestParam.push_message.intent = body.intent
   requestParam.push_channel.android.ups.intent = body.intent
 }
 if (body.payload) {
   requestParam.push_message.notification.payload = body.payload
   requestParam.push_channel.android.ups.notification.payload = body.payload
 }
 let data;
 await axios.default.post(`${baseUrl}/push/single/cid`, requestParam, {
   headers: {
     token: token,
   },
 })
   .then(value => {
     console.log(value, 'value')
     data = {
       code: 0, message: 'success'
     }
   })
   .catch(err => {
     console.log(err, 'error')
     data = {
       code: -1, error: statusCodeMap(err.response.data.code)
     }
   })
 return data
}


/**
* 状态码相关
*/
function statusCodeMap(code) {
 switch (code) {
   case 10001:
     return "token错误/失效";
   case 30019:
     return '系统繁忙,请稍后重试';
   case 30009:
     return '推送次数超过每日推送总数限制';
   case 20001:
     return '参数不合法';
   case 10005:
     return '每分钟调用频率超限';
   case 30015:
     return 'list推送 频率超过每分钟频率限制';
   case 30002:
     return '没有推送定时任务的权限';
   case 22002:
     return '任务无效或定时任务时间不合法';
   case 10003:
     return '每分钟鉴权频率超限';
   default:
     return 0
 }
}

// 生成随机32位字符串
function getRnd32() {
 let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
 let s = ''
 for (let i = 0; i < 32; i++) {
   s += str[Math.floor(Math.random() * 32)]
 }
 return s
}
  1. 批量推 push-batch

import cloud from '@/cloud-sdk'
import * as axios from 'axios'
const config = cloud.shared.get('unipush.config')
const { baseUrl } = config
/**
 * 入参:
 *  cid: 通过用户id查询到的cid 数组,长度不大于1000
 *  title: 标题 长度<= 50
 *  body: 通知内容 长度 <= 256
 *  click_type: url/none/startapp/payload(自定义消息内容启动应用)/intent(打开应用内特定页面)
 *  url: 当click_type为url时必填
 *  intent: 当click_type为intent时必填
 *  channel_level: 设置通知渠道重要性(可以控制响铃,震动,浮动,闪灯等等) 0/1/2/3/4
 *  // const body:any = {
    //   cid: ['ad043d41d7942e985b48fdba3052ac12'],
    //   title: '123',
    //   body: '222',
    //   click_type: 'none',
    //   channel_level:0
    // }
 */
exports.main = async function (ctx) {
  const { auth, body, query } = ctx
  let taskId;
  const { code, data: { token } } = await cloud.invoke('get-token', {})
  const tokenResult = statusCodeMap(code)
  if (tokenResult) return { error: tokenResult, code: -1 }
  const createResult = await createMessageBody(body, token)
  const codeResult = statusCodeMap(createResult.code)
  if (codeResult) {
    return { error: createResult.msg, code: -1 }
  } else {
    taskId = createResult.data.taskid
  }
  const pusResult = await multiPushToList(token, taskId, body.cid)
  const pushCodeResult = statusCodeMap(pusResult)
  if (pushCodeResult) {
    return { error: pushCodeResult, code: -1 }
  }
  return { code: 0, message: 'success', taskId }

}


/**
 * 创建消息体,批量推送前置
 */
async function createMessageBody(body, token) {
  const id = getRnd32()

  const pushInfo: any = {
    "request_id": id,
    "group_name": id,
    "settings": {
      "ttl": -1, // 设置离线时间 单位ms  这个时间内的多次推送可以重复利用taskid
      "strategy": {
        "default": 3, // 表示该消息只通过厂商通道策略下发,不考虑用户是否在线;
      },
      "speed": 100,
      // "schedule_time": '' //定时推送时间戳 
    },
    "push_message": { // 个推通道消息类容 
      "notification": {
        "title": body.title,
        "body": body.body,
        "click_type": body.click_type,
        "channel_level": body.channel_level
      }
    },
    "push_channel": { // 厂商通道内容
      "android": {
        "ups": {
          "notification": {
            "title": body.title,
            "body": body.body,
            "click_type": body.click_type,
            "channel_level": body.channel_level
          }
        }
      }
    }
  }

  if (body.payload) {
    pushInfo.push_message.notification.payload = body.payload
    pushInfo.push_channel.android.ups.notification.payload = body.payload
  }

  let r;
  await axios.default.post(`${baseUrl}/push/list/message`, pushInfo, {
    headers: {
      token: token,
    }
  }).then(value => {
    r = value.data
  }).catch(err => {
    r = err.response.data
  })
  return r

}


async function multiPushToList(token, taskid, cids) {
  const multiPushParam = {
    "audience": {
      "cid": cids // cid数组,数组长度不大于1000
    },
    "taskid": taskid,
    "is_async": true
  }
  let code;
  await axios.default.post(`${baseUrl}/push/list/cid`, multiPushParam, {
    headers: {
      token: token,
    }
  })
    .then(value => {
      code = value.data.code
    })
    .catch(err => {
      code = err.response.data.code
    })
  return code
}


/**
 * 状态码相关
 */
function statusCodeMap(code) {
  switch (code) {
    case 30019:
      return '系统繁忙,请稍后重试';
    case 30009:
      return '推送次数超过每日推送总数限制';
    case 20001:
      return '参数不合法';
    case 10005:
      return '每分钟调用频率超限';
    case 30015:
      return 'list推送 频率超过每分钟频率限制';
    case 30002:
      return '没有推送定时任务的权限';
    case 22002:
      return '任务无效或定时任务时间不合法';
    case 10003:
      return '每分钟鉴权频率超限';
    default:
      return 0
  }
}

// 生成随机32位字符串
function getRnd32() {
  let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let s = ''
  for (let i = 0; i < 32; i++) {
    s += str[Math.floor(Math.random() * 32)]
  }
  return s
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant