Skip to content

Commit

Permalink
退款
Browse files Browse the repository at this point in the history
  • Loading branch information
xy committed Apr 11, 2022
1 parent 0a68f45 commit d574462
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ log/
*.log
*.conf
*.yml

cert/
## delete remote file
# git rm --cache filename

Expand Down
91 changes: 59 additions & 32 deletions pay/src/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use wechat_sdk::{Client, WechatResult};
use itertools::Itertools;
use wechat_sdk::Config;
use chrono::prelude::{ Utc };
use serde_json::json;
pub struct Order{
conf: Config
}
Expand All @@ -22,6 +23,21 @@ pub struct Order{
// + "\"out_trade_no\": \"1217752501201407033233388881\","
// + "\"goods_tag\": \"WXG\","
// + "\"appid\": \"wxdace645e0bc2c424\"" + "}";
/// 签名
fn gen_sign(params: &serde_json::Value,secret_key: &str) -> String {
let mut vs = vec![];
if let Some(map) = params.as_object() {
for key in map.keys().sorted() {
vs.push(format!("{}={}", key,map[key].to_string().trim_matches(&['"','"'] as &[_])));
}
vs.push(format!("{}={}", "key",secret_key));
let wait_md5_str = format!("{}",vs.join("&"));
let sign = format!("{:x}",md5::compute(&wait_md5_str)).to_uppercase();
return sign
}

format!("")
}

impl Order {
pub fn new(conf: Config) -> Self {
Expand All @@ -35,21 +51,12 @@ impl Order {
let api_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
let conf = self.conf.clone();

params["appid"] = serde_json::Value::String(conf.app_id);
params["mch_id"] = serde_json::Value::String(conf.mch_id);
params["appid"] = json!(conf.app_id);
params["mch_id"] = json!(conf.mch_id);
//api
let secret_key = conf.secret_key;

let mut vs = vec![];
if let Some(map) = params.as_object() {
for key in map.keys().sorted() {
vs.push(format!("{}={}", key,map[key].to_string().trim_matches(&['"','"'] as &[_])));
}
vs.push(format!("{}={}", "key",secret_key));
let wait_md5_str = format!("{}",vs.join("&"));
let sign = format!("{:x}",md5::compute(&wait_md5_str)).to_uppercase();
params["sign"] = serde_json::Value::String(sign);
}
params["sign"] = json!(gen_sign(&params,&secret_key));


let body = format!("<xml>{}</xml>",serde_xml_rs::to_string(&params).unwrap_or_default());
Expand All @@ -69,45 +76,33 @@ impl Order {
if trade_type == Some("APP") && prepayid.is_some() { //二次签名

let mut new_params = serde_json::Map::new();
let mut vs = vec![];

let timestamp = Utc::now().naive_local().timestamp();
new_params.insert(format!("appid"), rr.get("appid").unwrap().clone());
new_params.insert(format!("partnerid"), rr.get("mch_id").unwrap().clone());
new_params.insert(format!("prepayid"), rr.get("prepay_id").unwrap().clone());
new_params.insert(format!("package"), json!("Sign=WXPay"));
new_params.insert(format!("noncestr"), rr.get("nonce_str").unwrap().clone());
new_params.insert(format!("timestamp"), json!(timestamp));

for key in new_params.keys().sorted() {
vs.push(format!("{}={}", key,new_params[key].to_string().trim_matches(&['"','"'] as &[_])));
}
vs.push(format!("{}={}", "key",secret_key));
let wait_md5_str = format!("{}",vs.join("&"));
let sign = format!("{:x}",md5::compute(&wait_md5_str)).to_uppercase();
new_params.insert(format!("sign"), json!(sign));
new_params.insert(format!("sign"), json!(gen_sign(&json!(new_params),&secret_key)));

return Ok(serde_json::Value::Object(new_params));
}else if trade_type == Some("JSAPI") && prepayid.is_some() { //二次签名
let prepay_id = rr.get("prepay_id").unwrap().as_str().unwrap();
let mut new_params = serde_json::Map::new();
let mut vs = vec![];

let timestamp = Utc::now().naive_local().timestamp();
new_params.insert(format!("appId"), rr.get("appid").unwrap().clone());
new_params.insert(format!("timeStamp"), json!(format!("{}",timestamp)));
new_params.insert(format!("nonceStr"), rr.get("nonce_str").unwrap().clone());
new_params.insert(format!("package"), json!(format!("prepay_id={}",prepay_id)));
new_params.insert(format!("signType"), json!("MD5"));

for key in new_params.keys().sorted() {
vs.push(format!("{}={}", key,new_params[key].to_string().trim_matches(&['"','"'] as &[_])));
}
vs.push(format!("{}={}", "key",secret_key));
let wait_md5_str = format!("{}",vs.join("&"));
let sign = format!("{:x}",md5::compute(&wait_md5_str)).to_uppercase();
new_params.insert(format!("paySign"), json!(sign));
return Ok(serde_json::Value::Object(new_params));
new_params.insert(format!("paySign"), json!(gen_sign(&json!(new_params),&secret_key)));

return Ok(json!(new_params));
}

return Ok(serde_json::Value::Object(rr));
return Ok(json!(rr));
}

Ok(json!({
Expand All @@ -116,4 +111,36 @@ impl Order {
}))

}

/// 退款
pub async fn refund(&self,mut params: serde_json::Value) -> WechatResult<serde_json::Value> {
let api_url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
let conf = self.conf.clone();

params["appid"] = json!(conf.app_id);
params["mch_id"] = json!(conf.mch_id);
//api
let secret_key = conf.secret_key;

params["sign"] = json!(gen_sign(&params,&secret_key));


let body = format!("<xml>{}</xml>",serde_xml_rs::to_string(&params).unwrap_or_default());

let request = Client::new_ssl("cert/apiclient_key.pem","cert/apiclient_cert.pem");

let r = request.post(&api_url,&body).await.unwrap_or_default();

let ps = serde_xml_rs::from_str::<serde_json::Value>(&r).unwrap_or_default();

if let Some(root_doms) = ps.as_object() {
let rr: serde_json::Map<String,serde_json::Value> = root_doms.iter().map(|(i,vo)| (i.clone(),vo["$value"].clone())).collect();
return Ok(json!(rr));
}

Ok(json!({
"return_code": "FAIL",
"return_msg": "请求网络问题 请确认证书"
}))
}
}
28 changes: 27 additions & 1 deletion sdk/src/actix_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::constant::DEFAULT_USER_AGENT;
use awc::{Client as HttpClient, Connector};
use actix_web::{http::header, http::Method, web::Bytes};

use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode,SslFiletype};
use serde::Serialize;

use crate::WechatResult as Result;
Expand Down Expand Up @@ -96,6 +96,32 @@ impl Client {
charset: "utf-8".to_owned(),
}
}
// 证书
pub fn new_ssl(private_key: &str,certificate: &str) -> Self {
// disable ssl verification
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
let _ = builder
.set_alpn_protos(b"\x02h2\x08http/1.1")
.map_err(|e| log!("Can not set alpn protocol: {:?}", e));

let _ = builder.set_private_key_file(private_key,SslFiletype::PEM).map_err(|e| log!("apiclient_key.pem not find: {:?}", e));
let _ = builder.set_certificate_chain_file(certificate).map_err(|e| log!("apiclient_cert.pem not find: {:?}", e));

let connector = Connector::new()
.timeout(Duration::from_secs(5))
.openssl(builder.build());

let client = HttpClient::builder()
.connector(connector)
.add_default_header((header::USER_AGENT, DEFAULT_USER_AGENT))
.finish();

Client {
client: client,
charset: "utf-8".to_owned(),
}
}

// pub fn set_reffer(mut self, reffer: String) {
// self.client.
Expand Down
25 changes: 18 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ mod tests {
fn it_pay_ok_works() {
println!("{:?}","=======================");
//初始化 配置
let _ = wechat_sdk::Config::load(json!({
"app_id": "wx455639023de66adb",
"mch_id": "1616885139",
"secret_key": "chengduhongtuikeji20210911888888",
}));
let conf = wechat_sdk::Config::load(json!({
"app_id": "",
"mch_id": "",
"secret_key": "",
})).unwrap();

actix_rt::System::new().block_on(async {
let params = json!({
let _params = json!({
"attach": "支付测试",
"body": "testx",
"nonce_str": "1212312312",
Expand All @@ -72,7 +72,18 @@ mod tests {
"openid": "oUpe_5T08-CTL7sXr_XwchZmlQu4",
"trade_type": "JSAPI"
});


let params = json!({
"nonce_str": "1212312312",
"out_trade_no": "A_4425320788525061",
"out_refund_no": "saa1234567891",
"total_fee": 1,
"refund_fee": 1,
//"notify_url": "https://wxpay.wxutil.com/pub_v2/pay/notify.v2.php",
});
let r = Order::new(conf);
let v = r.refund(params).await;
println!("{:?}",v);
//let r = Order::create(params).await.unwrap();
//println!("{:?}",r);
});
Expand Down

0 comments on commit d574462

Please sign in to comment.