feat: 接入微信小程序支付
This commit is contained in:
@@ -6,15 +6,16 @@ use axum::{
|
||||
};
|
||||
use module_runtime::{
|
||||
AnalyticsGranularity, PROFILE_RECHARGE_PAYMENT_CHANNEL_MOCK,
|
||||
RuntimeProfileFeedbackEvidenceRecord, RuntimeProfileFeedbackEvidenceSnapshot,
|
||||
RuntimeProfileFeedbackSubmissionRecord, RuntimeProfileInviteCodeRecord,
|
||||
RuntimeProfileMembershipBenefitRecord, RuntimeProfileRechargeCenterRecord,
|
||||
RuntimeProfileRechargeOrderRecord, RuntimeProfileRechargeProductRecord,
|
||||
RuntimeProfileRedeemCodeMode, RuntimeProfileRedeemCodeRecord,
|
||||
RuntimeProfileRewardCodeRedeemRecord, RuntimeProfileTaskCenterRecord,
|
||||
RuntimeProfileTaskClaimRecord, RuntimeProfileTaskConfigRecord, RuntimeProfileTaskCycle,
|
||||
RuntimeProfileTaskItemRecord, RuntimeProfileTaskStatus, RuntimeProfileWalletLedgerSourceType,
|
||||
RuntimeReferralInviteCenterRecord, RuntimeTrackingScopeKind,
|
||||
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM, RuntimeProfileFeedbackEvidenceRecord,
|
||||
RuntimeProfileFeedbackEvidenceSnapshot, RuntimeProfileFeedbackSubmissionRecord,
|
||||
RuntimeProfileInviteCodeRecord, RuntimeProfileMembershipBenefitRecord,
|
||||
RuntimeProfileRechargeCenterRecord, RuntimeProfileRechargeOrderRecord,
|
||||
RuntimeProfileRechargeProductRecord, RuntimeProfileRedeemCodeMode,
|
||||
RuntimeProfileRedeemCodeRecord, RuntimeProfileRewardCodeRedeemRecord,
|
||||
RuntimeProfileTaskCenterRecord, RuntimeProfileTaskClaimRecord, RuntimeProfileTaskConfigRecord,
|
||||
RuntimeProfileTaskCycle, RuntimeProfileTaskItemRecord, RuntimeProfileTaskStatus,
|
||||
RuntimeProfileWalletLedgerSourceType, RuntimeReferralInviteCenterRecord,
|
||||
RuntimeTrackingScopeKind,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::{Value, json};
|
||||
@@ -56,8 +57,13 @@ use spacetime_client::SpacetimeClientError;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
admin::AuthenticatedAdmin, api_response::json_success_body, auth::AuthenticatedAccessToken,
|
||||
http_error::AppError, request_context::RequestContext, state::AppState,
|
||||
admin::AuthenticatedAdmin,
|
||||
api_response::json_success_body,
|
||||
auth::AuthenticatedAccessToken,
|
||||
http_error::AppError,
|
||||
request_context::RequestContext,
|
||||
state::AppState,
|
||||
wechat_pay::{build_wechat_payment_request, current_unix_micros, map_wechat_pay_error},
|
||||
};
|
||||
|
||||
pub async fn get_profile_dashboard(
|
||||
@@ -186,14 +192,15 @@ pub async fn create_profile_recharge_order(
|
||||
let payment_channel = payload
|
||||
.payment_channel
|
||||
.unwrap_or_else(|| PROFILE_RECHARGE_PAYMENT_CHANNEL_MOCK.to_string());
|
||||
let created_at_micros = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000;
|
||||
let payment_channel = payment_channel.trim().to_string();
|
||||
let created_at_micros = current_unix_micros();
|
||||
let (center, order) = state
|
||||
.spacetime_client()
|
||||
.create_profile_recharge_order(
|
||||
user_id,
|
||||
payload.product_id,
|
||||
payment_channel,
|
||||
created_at_micros as i64,
|
||||
payment_channel.clone(),
|
||||
created_at_micros,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
@@ -203,11 +210,36 @@ pub async fn create_profile_recharge_order(
|
||||
)
|
||||
})?;
|
||||
|
||||
let wechat_mini_program_pay_params = if payment_channel
|
||||
== PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM
|
||||
{
|
||||
let identity = resolve_wechat_identity_for_payment(&state, &order.user_id)
|
||||
.await
|
||||
.map_err(|error| runtime_profile_error_response(&request_context, error))?;
|
||||
Some(
|
||||
state
|
||||
.wechat_pay_client()
|
||||
.create_mini_program_order(build_wechat_payment_request(
|
||||
order.order_id.clone(),
|
||||
order.product_title.clone(),
|
||||
order.amount_cents,
|
||||
identity,
|
||||
))
|
||||
.await
|
||||
.map_err(|error| {
|
||||
runtime_profile_error_response(&request_context, map_wechat_pay_error(error))
|
||||
})?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
CreateProfileRechargeOrderResponse {
|
||||
order: build_profile_recharge_order_response(order),
|
||||
center: build_profile_recharge_center_response(center),
|
||||
wechat_mini_program_pay_params,
|
||||
},
|
||||
))
|
||||
}
|
||||
@@ -750,6 +782,25 @@ fn runtime_profile_error_response(request_context: &RequestContext, error: AppEr
|
||||
error.into_response_with_context(Some(request_context))
|
||||
}
|
||||
|
||||
async fn resolve_wechat_identity_for_payment(
|
||||
state: &AppState,
|
||||
user_id: &str,
|
||||
) -> Result<String, AppError> {
|
||||
if let Some(identity) = state
|
||||
.wechat_auth_service()
|
||||
.get_identity_by_user_id(user_id)
|
||||
.map_err(|error| {
|
||||
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.with_message(format!("读取微信身份失败:{error}"))
|
||||
})?
|
||||
{
|
||||
return Ok(identity.provider_uid);
|
||||
}
|
||||
|
||||
Err(AppError::from_status(StatusCode::BAD_REQUEST)
|
||||
.with_message("当前账号缺少微信小程序身份,请在小程序内重新登录后再支付"))
|
||||
}
|
||||
|
||||
fn build_profile_recharge_center_response(
|
||||
record: RuntimeProfileRechargeCenterRecord,
|
||||
) -> ProfileRechargeCenterResponse {
|
||||
@@ -825,6 +876,7 @@ fn build_profile_recharge_order_response(
|
||||
status: record.status.as_str().to_string(),
|
||||
payment_channel: record.payment_channel,
|
||||
paid_at: record.paid_at,
|
||||
provider_transaction_id: record.provider_transaction_id,
|
||||
created_at: record.created_at,
|
||||
points_delta: record.points_delta,
|
||||
membership_expires_at: record.membership_expires_at,
|
||||
|
||||
Reference in New Issue
Block a user