alipay-rs

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

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

这是一个简单的alipay SDK,只需要创建client,然后通过client的post方法请求Alipay api即可。

Note

```text

新版本与之前版本不兼容,但之前代码只需少量修改就可继续使用。

```

```rust // 老代码,v0.3版本之前写法 let client = alipayrs::Client::new( "20210xxxxxxxxxxx", includestr!("../私钥.txt"), Some(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")), Some(include_str!("../alipayRootCert.crt")) );

// 新代码,v0.3版本之后写法 let config = alipayrs::Config::builder() .appid("20210xxxxxxxxxxx") .publickey(includestr!("../公钥.txt")) .privatekey(includestr!("../私钥.txt")) .appcertsn(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")) .alipayrootcertsn(includestr!("../alipayRootCert.crt")) .finish(); let mut client = config.get_client();

// or

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

Usage

```toml

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

or

alipay-rs = "0.3"

```

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 config = alipayrs::Config::builder() .appid("20210xxxxxxxxxxx") .publickey(includestr!("../公钥.txt")) .privatekey(includestr!("../私钥.txt")) .appcertsn(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")) .alipayrootcertsn(includestr!("../alipayRootCert.crt")) .finish(); let mut client = config.getclient(); 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, charset: String, signtype: String, version: String, }

...

let publicparams = PublicParams { appid: "20210xxxxxxxxxxx".toowned(), charset: "utf-8".toowned(), signtype: "RSA2".toowned(), version: "1.0".to_owned(), };

// 也可以通过vec, hashmap, array, tuple来设置公共参数 let publicparams = ("appid", "20210xxxxxxxxxxx"); let publicparams = [("imagetype", "png"), ("imagename", "test")]; let publicparams = vec![("imagetype", "png"), ("imagename", "test")]; let publicparams = HashMap::from([("imagetype", "png"), ("image_name", "test")]);

client.setpublicparams(public_params);

...

```

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 mut 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); ```

多线程

由于client是可写入的,不允许在多线程中共享,所以在多线程中我们可以先创建config,通过config在多线程中共享我们需要的数据,再通过config在线程中创建client。

mutlithreading example

```rust

......

async fn refquery(client: &mut 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: &mut 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 config = alipayrs::Config::builder() .appid("20210xxxxxxxxxxx") .publickey(includestr!("../公钥.txt")) .privatekey(includestr!("../私钥.txt")) .appcertsn(includestr!("../appCertPublicKey20210xxxxxxxxxxx.crt")) .alipayrootcertsn(includestr!("../alipayRootCert.crt")) .finish();

let conf = Arc::new(config); let confclone = conf.clone(); tokio::spawn(async move { let mut client = confclone.getclient(); refquery(&mut client).await; }).await.unwrap(); tokio::spawn(async move { let mut client = conf.clone().getclient(); reffund_transfer(&mut client).await; }).await.unwrap(); ```