wechat-mp-0.1.4 doesn't have any documentation.
微信公众号(包括订阅号和服务号)SDK for rust
 
 

库初始化中, 目前api还没完成, 请不要使用
关键特性
- 纯SDK, 可配合其他http server一起使用.
- 支持单/多公众号管理
- 全异步支持
实现的API
接收消息
回复消息
客服消息
自定义菜单
网页授权
todo:
example
use actix_web::{
    get, post,
    web::{self, Bytes, Data, Path, Query},
    App, HttpResponse, HttpServer, Responder, Result,
};
use log::info;
use wechat4rs::{
    errors::{WechatEncryptError, WechatError},
    CallbackMessage, EchoStrReq, MessageInfo, ReplyMessage, SaasContext, VerifyInfo, Wechat,
    WechatCallBackHandler, WechatConfig, WechatSaasResolver,
};
#[get("/wechat-callback/{saas_id}/")]
async fn echo_str(
    wechat: Data<Wechat>,
    saas_id: Path<u64>,
    verify_info: Query<VerifyInfo>,
    req: Query<EchoStrReq>,
) -> Result<String, WechatError> {
    let context = SaasContext::new(saas_id.into_inner());
    let result = wechat.handle_echo(&verify_info, &req, &context).await?;
    Ok(result)
}
#[post("/wechat-callback/{saas_id}/")]
async fn wechat_callback(
    wechat: Data<Wechat>,
    saas_id: Path<u64>,
    info: Query<VerifyInfo>,
    body: Bytes,
) -> Result<String, WechatError> {
    let request_body = String::from_utf8(body.to_vec())?;
    let context = SaasContext::new(saas_id.into_inner());
    let result = wechat
        .handle_callback(&info, &request_body, &context)         .await?;
    Ok(result)
}
use async_trait::async_trait;
struct EchoText;
#[async_trait]
impl WechatCallBackHandler for EchoText {
    async fn handler_callback(
        &self,
        _wechat: &Wechat,
        prev_result: Option<ReplyMessage>,
        message: &CallbackMessage,
    ) -> Result<Option<ReplyMessage>, WechatError> {
        if let CallbackMessage::Text {
            info,
            content,
            biz_msg_menu_id: _,
        } = message
        {
            let info = info.clone();
            return Ok(Some(ReplyMessage::Text {
                info: MessageInfo {
                    from_user_name: info.to_user_name.clone(),
                    to_user_name: info.from_user_name.clone(),
                    ..info
                },
                content: format!("hello: {}", content),
            }));
        }
        Ok(prev_result)     }
}
struct SaasResolve;
#[async_trait]
impl WechatSaasResolver for SaasResolve {
    async fn resolve_config(
        &self,
        _wechat: &Wechat,
        context: &SaasContext,
    ) -> Result<WechatConfig, WechatError> {
        let aes_key = wechat4rs::WechatConfig::decode_aes_key(
            &"znpfGFxELvUSxh0Gx4rJenvVQRrAhdTsioG08XR4z3S=".to_string(),
        )?;
        match context.id {
            1 => Ok(WechatConfig {
                key: None,
                app_id: "appid 1".into(),
                app_secret: "app id 1 secret".into(),
            }),
            2 => Ok(WechatConfig {
                key: aes_key,
                app_id: "appid 2".into(),
                app_secret: "appid 2 secret".into(),
            }),
            _ => Err(WechatError::EncryptError {
                source: WechatEncryptError::InvalidAppId,
            }),
        }
    }
}
async fn init() -> anyhow::Result<()> {
    use actix_web::middleware::Logger;
    use bb8_redis::{RedisConnectionManager, RedisPool};
    use env_logger::Env;
    use wechat4rs::token_provider::reids::RedisTokenProvider;
    use dotenv::dotenv;
    dotenv().ok();
    env_logger::from_env(Env::default().default_filter_or("info")).init();
    info!("init");
                let manager = RedisConnectionManager::new(dotenv::var("REDIS_URL")?)?;
    let pool = RedisPool::new(bb8::Pool::builder().build(manager).await?);
    let token_p = RedisTokenProvider::new(pool);
        let mut wechat = wechat4rs::Wechat::new(Box::new(SaasResolve), Box::new(token_p));
        wechat.registry_callback(Box::new(EchoText));
    let wechat = web::Data::new(wechat);
    HttpServer::new(move || {
        App::new()
            .wrap(Logger::default())
            .wrap(Logger::new("%a %{User-Agent}i"))
            .app_data(wechat.clone())
            .service(echo_str)             .service(wechat_callback)     })
    .bind("0.0.0.0:3000")?
    .run()
    .await?;
    Ok(())
}
#[actix_rt::main]
async fn main() -> Result<(), std::io::Error> {
    if let Err(err) = init().await {
        eprintln!("ERROR: {:#}", err);
        err.chain()
            .skip(1)
            .for_each(|cause| eprintln!("because: {:?}", cause));
        std::process::exit(1);
    }
    Ok(())
}