alipay-rs

支付宝api文档: https://opendocs.alipay.com/apis/

签名方法为 RSA2,采用支付宝提供的 RSA签名&验签工具 生成秘钥时,秘钥的格式必须为 PKCS1,秘钥长度推荐 2048。所以在支付宝管理后台请注意配置 RSA2(SHA256)密钥。

Usage

```toml

[dependencies] alipay-rs = {git = "https://github.com/chenhuaiyuan/alipay-rs"}

已在原先的alipay-rs库中删除AlipayParam宏,需要添加struct-map库来实现AlipayParam宏,如果未使用到AlipayParam宏可以不添加

struct-map = {git = "https://github.com/chenhuaiyuan/struct-map"}

or

alipay-rs = "0.3" struct-map = "0.1"

```

example

以单笔转账接口为例:

```rust

...

// 接口参数

[derive(Serialize, Debug)]

struct Transfer { outbizno: String, transamount: String, productcode: String, bizscene: String, payeeinfo: PayeeInfo, }

[derive(Serialize, Debug)]

struct PayeeInfo { identity: String, identity_type: String, name: String, }

async fn fundtransfer() { let transfer = Transfer { outbizno: format!("{}", Local::now().timestamp()), transamount: String::from("0.1"), productcode: String::from("TRANSACCOUNTNOPWD"), bizscene: String::from("DIRECTTRANSFER"), payeeinfo: PayeeInfo { identity: String::from("343938938@qq.com"), identitytype: String::from("ALIPAYLOGONID"), name: String::from("陈怀远"), }, }; let client = alipayrs::Client::new( "20210xxxxxxxxxxx", includestr!("../私钥.txt"), Some(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")), Some(includestr!("../alipayRootCert.crt")) ); let data:serdejson::Value = client .post("alipay.fund.trans.uni.transfer", transfer) .await.unwrap(); println!("{:?}", data); }

async fn neofundtransfer() { let transfer = Transfer { outbizno: format!("{}", Local::now().timestamp()), transamount: String::from("0.1"), productcode: String::from("TRANSACCOUNTNOPWD"), bizscene: String::from("DIRECTTRANSFER"), payeeinfo: PayeeInfo { identity: String::from("343938938@qq.com"), identitytype: String::from("ALIPAYLOGONID"), name: String::from("陈怀远"), }, }; let client = alipayrs::Client::neo( "20210xxxxxxxxxxx", "私钥.txt", Some("appCertPublicKey20210xxxxxxxxxxx.crt"), Some("alipayRootCert.crt") ); let data:serdejson::Value = client .post("alipay.fund.trans.uni.transfer", transfer) .await.unwrap(); println!("{:?}", data); } ```

支付宝的所有接口都可以使用client.post函数访问,如果接口没有参数,可以使用client.noparampost函数。 默认的公共参数包含:appid,charset,signtype,format,version,method,timestamp,sign,如果想修改参数值,可以通过client.setpublicparams函数设置。

```rust

...

// 需要修改或添加公共参数必须添加AlipayParam宏

[derive(AlipayParam)]

struct PublicParams { appid: String, method: Option, charset: String, signtype: String, sign: Option, timestamp: Option, version: String, }

...

let publicparams = PublicParams { appid: "20210xxxxxxxxxxx".toowned(), method: None, charset: "utf-8".toowned(), signtype: "RSA2".toowned(), sign: None, timestamp: None, version: "1.0".toowned(), }; // 公共参数值为None或参数名不存在于公共参数会被过滤掉 client.setpublicparams(publicparams);

...

```

如果需要添加公共参数,可通过client.addpublicparams函数设置, 具体可以看看example中的image_upload。

```rust ...

[derive(AlipayParam)]

struct ImageUpload { imagetype: String, imagename: String, }

...

let image = ImageUpload { imagetype: "png".toowned(), imagename: "test".toowned(), };

...

client.addpublicparams(image);

```

alipay api有图片视频等资源上传的接口,可以通过post_file接口进行资源上传

```rust

[derive(AlipayParam)]

struct Image { imagetype: String, imagename: String, } let file = std::fs::read("./test.png").unwrap(); let image = Image { imagetype: "png".toowned(), imagename: "test".toowned(), }; let client = ...; client.addpublicparams(image); // postfile参数: // method 接口名称 // key 文件参数名 // filename 文件名 // filecontent 文件内容 let data:serdejson::Value = client.postfile("alipay.offline.material.image.upload", "imagecontent", "test.png", file.as_ref()).await.unwrap(); println!("{:?}", data); ```

多线程

默认没有实现Send特性,所以只支持在单线程中调用,无法进行多线程共享。如果想要在多线程中使用,请添加multithreading feature,并将default-features设置为false。

```toml [dependencies] alipay-rs = {version = "0.3", features = ["multithreading"], default-features = false}

```

mutlithreading example

```rust

......

async fn refquery(client: &alipayrs::Client) { let query = QueryParam { operation: "ITEMPAGEQUERY".toowned(), pagenum: 1, pagesize: 10, itemidlist: None, };

let data:serde_json::Value = client
    .post("alipay.open.mini.item.page.query", query)
    .await.unwrap();
println!("{:?}", data);

}

async fn reffundtransfer(client: &alipayrs::Client) { let transfer = Transfer { outbizno: format!("{}", Local::now().timestamp()), transamount: String::from("0.1"), productcode: String::from("TRANSACCOUNTNOPWD"), bizscene: String::from("DIRECTTRANSFER"), payeeinfo: PayeeInfo { identity: String::from("343938938@qq.com"), identitytype: String::from("ALIPAYLOGONID"), name: String::from("陈怀远"), }, }; let data:serde_json::Value = client .post("alipay.fund.trans.uni.transfer", transfer) .await.unwrap(); println!("{:?}", data); }

......

let client = alipayrs::Client::new( "20210xxxxxxxxxxx", includestr!("../私钥.txt"), Some(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")), Some(include_str!("../alipayRootCert.crt")) );

let cli = Arc::new(client); let cliclone = cli.clone(); tokio::spawn(async move { refquery(&cliclone).await; }).await.unwrap(); tokio::spawn(async move { reffund_transfer(&cli.clone()).await; }).await.unwrap(); ```