Merge branch 'master' of https://git.genarrative.world/GenarrativeAI/Genarrative
This commit is contained in:
@@ -1069,10 +1069,47 @@ pub fn build_runtime_profile_recharge_order_id(
|
||||
created_at_micros: i64,
|
||||
product_id: &str,
|
||||
) -> String {
|
||||
format!(
|
||||
"recharge:{}",
|
||||
build_runtime_profile_recharge_wallet_ledger_id(user_id, created_at_micros, product_id)
|
||||
)
|
||||
// 微信支付 v3 的 out_trade_no 只接受较短的字母、数字和部分符号。
|
||||
// 订单号同时作为本地 profile_recharge_order 主键,因此统一使用可支付渠道兼容的紧凑格式。
|
||||
let timestamp = encode_runtime_profile_recharge_order_base36(created_at_micros.unsigned_abs());
|
||||
let hash = hash_runtime_profile_recharge_order_key(user_id, product_id, created_at_micros);
|
||||
format!("rcg{timestamp}{:010x}", hash & 0x0000_0003_ffff_ffff)
|
||||
}
|
||||
|
||||
fn encode_runtime_profile_recharge_order_base36(mut value: u64) -> String {
|
||||
const DIGITS: &[u8; 36] = b"0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
if value == 0 {
|
||||
return "0".to_string();
|
||||
}
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
while value > 0 {
|
||||
buffer.push(DIGITS[(value % 36) as usize] as char);
|
||||
value /= 36;
|
||||
}
|
||||
buffer.iter().rev().collect()
|
||||
}
|
||||
|
||||
fn hash_runtime_profile_recharge_order_key(
|
||||
user_id: &str,
|
||||
product_id: &str,
|
||||
created_at_micros: i64,
|
||||
) -> u64 {
|
||||
let mut hash = 14_695_981_039_346_656_037u64;
|
||||
for byte in user_id
|
||||
.trim()
|
||||
.as_bytes()
|
||||
.iter()
|
||||
.copied()
|
||||
.chain([b':'])
|
||||
.chain(product_id.trim().as_bytes().iter().copied())
|
||||
.chain([b':'])
|
||||
.chain(created_at_micros.to_le_bytes())
|
||||
{
|
||||
hash ^= u64::from(byte);
|
||||
hash = hash.wrapping_mul(1_099_511_628_211);
|
||||
}
|
||||
hash
|
||||
}
|
||||
|
||||
pub fn resolve_runtime_profile_points_recharge_delta(
|
||||
|
||||
@@ -242,6 +242,14 @@ pub fn build_runtime_profile_recharge_center_get_input(
|
||||
Ok(RuntimeProfileRechargeCenterGetInput { user_id })
|
||||
}
|
||||
|
||||
pub fn build_runtime_profile_recharge_order_get_input(
|
||||
order_id: String,
|
||||
) -> Result<RuntimeProfileRechargeOrderGetInput, RuntimeProfileFieldError> {
|
||||
let order_id =
|
||||
normalize_required_string(order_id).ok_or(RuntimeProfileFieldError::MissingOrderId)?;
|
||||
Ok(RuntimeProfileRechargeOrderGetInput { order_id })
|
||||
}
|
||||
|
||||
pub fn build_runtime_profile_recharge_order_create_input(
|
||||
user_id: String,
|
||||
product_id: String,
|
||||
|
||||
@@ -1060,6 +1060,12 @@ pub struct RuntimeProfileRechargeCenterGetInput {
|
||||
pub user_id: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct RuntimeProfileRechargeOrderGetInput {
|
||||
pub order_id: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct RuntimeProfileRechargeOrderCreateInput {
|
||||
|
||||
@@ -733,9 +733,13 @@ mod tests {
|
||||
build_runtime_profile_recharge_wallet_ledger_id("user-1", 200, "points_60"),
|
||||
"user-1:200:points_60"
|
||||
);
|
||||
assert_eq!(
|
||||
build_runtime_profile_recharge_order_id("user-1", 200, "points_60"),
|
||||
"recharge:user-1:200:points_60"
|
||||
let order_id = build_runtime_profile_recharge_order_id("user-1", 200, "points_60");
|
||||
assert!(order_id.starts_with("rcg"));
|
||||
assert!(order_id.len() <= 32);
|
||||
assert!(
|
||||
order_id
|
||||
.chars()
|
||||
.all(|ch| ch.is_ascii_lowercase() || ch.is_ascii_digit())
|
||||
);
|
||||
assert_eq!(
|
||||
build_runtime_profile_redeem_code_usage_id("GIFT", "user-1", 300, 2),
|
||||
|
||||
Reference in New Issue
Block a user