fix wechat pay request headers
This commit is contained in:
@@ -25,7 +25,9 @@ const WECHAT_PAY_PROVIDER_MOCK: &str = "mock";
|
||||
const WECHAT_PAY_PROVIDER_REAL: &str = "real";
|
||||
const WECHAT_PAY_BODY_SIGNATURE_METHOD: &str = "WECHATPAY2-SHA256-RSA2048";
|
||||
const WECHAT_PAY_PAY_SIGN_TYPE: &str = "RSA";
|
||||
const WECHAT_PAY_NOTIFY_SUCCESS: &str = "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
|
||||
const WECHAT_PAY_ACCEPT_HEADER: &str = "application/json";
|
||||
const WECHAT_PAY_CONTENT_TYPE_HEADER: &str = "application/json";
|
||||
const WECHAT_PAY_USER_AGENT: &str = "Genarrative-WechatPay/1.0";
|
||||
const WECHAT_PAY_APP_ID_MAX_CHARS: usize = 32;
|
||||
const WECHAT_PAY_MCH_ID_MAX_CHARS: usize = 32;
|
||||
const WECHAT_PAY_DESCRIPTION_MAX_CHARS: usize = 127;
|
||||
@@ -277,18 +279,17 @@ impl RealWechatPayClient {
|
||||
&nonce,
|
||||
&body,
|
||||
)?;
|
||||
let response = self
|
||||
.client
|
||||
.post(&self.jsapi_endpoint)
|
||||
.header("Authorization", authorization)
|
||||
.header("Accept", "application/json")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(body)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|error| {
|
||||
WechatPayError::RequestFailed(format!("微信支付 JSAPI 下单请求失败:{error}"))
|
||||
})?;
|
||||
let response = with_wechat_pay_jsapi_headers(
|
||||
self.client
|
||||
.post(&self.jsapi_endpoint)
|
||||
.header("Authorization", authorization),
|
||||
)
|
||||
.body(body)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|error| {
|
||||
WechatPayError::RequestFailed(format!("微信支付 JSAPI 下单请求失败:{error}"))
|
||||
})?;
|
||||
let status = response.status();
|
||||
let response_text = response.text().await.map_err(|error| {
|
||||
WechatPayError::Deserialize(format!("微信支付 JSAPI 下单响应读取失败:{error}"))
|
||||
@@ -438,7 +439,7 @@ pub async fn handle_wechat_pay_notify(
|
||||
State(state): State<AppState>,
|
||||
headers: HeaderMap,
|
||||
body: Bytes,
|
||||
) -> Result<&'static str, AppError> {
|
||||
) -> Result<StatusCode, AppError> {
|
||||
let notify = state
|
||||
.wechat_pay_client()
|
||||
.parse_notify(&headers, &body)
|
||||
@@ -449,7 +450,7 @@ pub async fn handle_wechat_pay_notify(
|
||||
trade_state = notify.trade_state.as_str(),
|
||||
"收到非成功微信支付通知"
|
||||
);
|
||||
return Ok(WECHAT_PAY_NOTIFY_SUCCESS);
|
||||
return Ok(StatusCode::NO_CONTENT);
|
||||
}
|
||||
|
||||
let paid_at_micros = notify
|
||||
@@ -476,7 +477,7 @@ pub async fn handle_wechat_pay_notify(
|
||||
"微信支付通知已确认订单入账"
|
||||
);
|
||||
|
||||
Ok(WECHAT_PAY_NOTIFY_SUCCESS)
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
pub fn map_wechat_pay_error(error: WechatPayError) -> AppError {
|
||||
@@ -532,6 +533,16 @@ fn map_wechat_pay_notify_error(error: WechatPayError) -> AppError {
|
||||
map_wechat_pay_error(error)
|
||||
}
|
||||
|
||||
fn with_wechat_pay_jsapi_headers(builder: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
|
||||
builder
|
||||
.header(reqwest::header::ACCEPT, WECHAT_PAY_ACCEPT_HEADER)
|
||||
.header(
|
||||
reqwest::header::CONTENT_TYPE,
|
||||
WECHAT_PAY_CONTENT_TYPE_HEADER,
|
||||
)
|
||||
.header(reqwest::header::USER_AGENT, WECHAT_PAY_USER_AGENT)
|
||||
}
|
||||
|
||||
fn build_mock_pay_params(order_id: &str) -> WechatMiniProgramPayParamsResponse {
|
||||
let time_stamp = OffsetDateTime::now_utc().unix_timestamp().to_string();
|
||||
let nonce_str = "mock-nonce".to_string();
|
||||
@@ -931,6 +942,40 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jsapi_order_request_sets_wechat_required_http_headers() {
|
||||
let request = with_wechat_pay_jsapi_headers(
|
||||
reqwest::Client::new()
|
||||
.post("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi")
|
||||
.header(
|
||||
"Authorization",
|
||||
"WECHATPAY2-SHA256-RSA2048 mchid=\"1900000001\"",
|
||||
),
|
||||
)
|
||||
.build()
|
||||
.expect("request should build");
|
||||
|
||||
let headers = request.headers();
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(reqwest::header::ACCEPT)
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some(WECHAT_PAY_ACCEPT_HEADER)
|
||||
);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(reqwest::header::CONTENT_TYPE)
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some(WECHAT_PAY_CONTENT_TYPE_HEADER)
|
||||
);
|
||||
assert_eq!(
|
||||
headers
|
||||
.get(reqwest::header::USER_AGENT)
|
||||
.and_then(|value| value.to_str().ok()),
|
||||
Some(WECHAT_PAY_USER_AGENT)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_mock_notify_defaults_success_state() {
|
||||
let notify =
|
||||
|
||||
Reference in New Issue
Block a user