React Native实现短信转发到微信上

缘由

都说需求来源于生活我为什么会有一个这么奇葩的需求呢?来看一个故事。

昨天为了省点手续费导航走了3公里多去找一家工行ATM机(没办法穷)然后到了以后发现ATM机在人家的园区里面,现在疫情进入要通行证,没办法一脸的无奈然后又走了2公里找到一个可以用的,结果卡插进去,输入取款金额后点击取款,原本以为一切顺利,突然屏幕上弹出一个提示该卡种不能做此种交易瞬间懵逼。
React Native实现短信转发到微信上
然后搜索发现没有开通*取现功能,打电话客服去开通,突然我就意识到我绑定的手机号码没带(万一要我手机验证码怎么办)。还好没要(偷笑)。

天天装两个手机在兜里有点笨重,于是乎就萌生了一个需求能不能把短信直接转发到我主要使用的手机上,开干。

实现效果图

React Native实现短信转发到微信上
React Native实现短信转发到微信上
React Native实现短信转发到微信上

进入正题

既然要做短信转发第一时间想到的就是Android(因为Android比较开放什么都能获取到不要IOS各种限制),了解了一下发现都要用原生代码来实现。

毕竟我们是前端就不要用纯原生的东西了,之前用Flutter写过一个小功能还行现在还有100个人左右在用,后面想想还是React比较熟悉,那就用React Native把。

我们首先需要考虑的是短信转发,我们需要先监听到短信的到来,通过我们的服务器处理。

找到一个这个库react-native-android-sms-listener可以实现,但是发现有几个问题。

  1. 退出后台以后就不在实现监听了(这要程序一直保持在前台这肯定不行)
  2. 测试过程中发先长短信拆分成几段顺序还不一致这样转发出效果很差
  3. 没有短信接收时间(虽然可用用当前时间代替)
  4. 我手机上有2张卡不知道是哪张卡来的短信

自己改了改大概实现了这些功能react-native-android-sms-listener2感兴趣的朋友可以去看看主要是这个文件SmsReceiver.java

客户端主要实现逻辑就是通过设备Id去看有没有绑定微信,没有则出现二维码绑定。

import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, PermissionsAndroid} from 'react-native';

import SmsListener from 'react-native-android-sms-listener2';
import {getUniqueId} from 'react-native-device-info';
import QRCode from 'react-native-qrcode-svg';

import axios from 'axios';

axios.defaults.baseURL = 'https://service.wx.hengkx.com';

axios.interceptors.response.use(
  response => response.data,
  error => Promise.reject(error.response.data),
);

async function requestReadSmsPermission() {
  try {
    var granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.READ_SMS,
      {
        title: '阅读短信',
        message: '需要获取阅读短信权限',
      },
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
        {
          title: '接收短信',
          message: '需要获取接收短信权限',
        },
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        console.log('RECEIVE_SMS permissions granted', granted);
      } else {
        console.log('RECEIVE_SMS permissions denied');
      }
    } else {
      console.log('sms read permissions denied');
    }
  } catch (err) {
    console.log(err);
  }
}
const App: () => React$Node = () => {
  const [url, setUrl] = useState();
  const [openId, setOpenId] = useState();
  useEffect(() => {
    requestReadSmsPermission();
    axios
      .get('/api/account/info', {params: {deviceId: getUniqueId()}})
      .then(res => {
        if (res.code === 0) {
          if (res.data.url) {
            setUrl(res.data.url);
            const interval = setInterval(async () => {
              const {data} = await axios.get('/api/account/check', {
                params: {deviceId: getUniqueId()},
              });
              if (data) {
                setUrl();
                setOpenId(data.openId);
                clearInterval(interval);
              }
            }, 1000);
          } else {
            setOpenId(res.data.openId);
          }
        }
      });
    SmsListener.addListener(message => {
      if (openId) {
        axios.post('/api/sms/receive', {
          ...message,
          openId,
          tel: message.originatingAddress,
          content: message.body,
        });
      }
    });
  }, [openId, setUrl]);

  return (
    <>
      <View style={styles.qrCodeContainer}>
        {url && (
          <>
            <QRCode value={url} size={200} bgColor="purple" fgColor="white" />
            <Text style={styles.qrCodeTip}>微信扫描二维码绑定</Text>
          </>
        )}
        {openId && <Text>已为您自动开启短信转发</Text>}
      </View>
    </>
  );
};

const styles = StyleSheet.create({
  qrCodeContainer: {
    flexDirection: 'column',
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
  },
  qrCodeTip: {
    marginTop: 10,
  },
});

export default App;

源码

上一篇:Spring Boot+Vue前后端分离微信公众号网页授权解决方案


下一篇:微信小程序登录流程四步走个人总结流程摘要!