feat(payment): 优化套餐配置和支付服务
- 简化套餐配置结构,删除冗余的 default.yaml 和 us.yaml - 优化 Apple IAP 服务和验证逻辑 - 更新套餐数据模型和协议文档 - 添加支付相关测试用例
This commit is contained in:
@@ -22,7 +22,7 @@ class TestAppleJwsVerifierInvalidInput:
|
||||
result = verifier.verify_signed_transaction(
|
||||
"not-a-jws",
|
||||
expected_bundle_id="com.meeyao.qianwen",
|
||||
expected_product_id="com.meeyao.qianwen.basic_pack",
|
||||
expected_product_id="com.meeyao.qianwen.starter_pack",
|
||||
)
|
||||
assert isinstance(result, VerificationError)
|
||||
assert result.code == "PAYMENT_TRANSACTION_INVALID"
|
||||
@@ -34,7 +34,7 @@ class TestAppleJwsVerifierInvalidInput:
|
||||
result = verifier.verify_signed_transaction(
|
||||
f"{h}.{p}.fake",
|
||||
expected_bundle_id="com.meeyao.qianwen",
|
||||
expected_product_id="com.meeyao.qianwen.basic_pack",
|
||||
expected_product_id="com.meeyao.qianwen.starter_pack",
|
||||
)
|
||||
assert isinstance(result, VerificationError)
|
||||
assert "x5c" in result.detail
|
||||
@@ -45,7 +45,7 @@ class TestAppleJwsVerifierInvalidInput:
|
||||
result = verifier.verify_signed_transaction(
|
||||
f"{h}.{p}.fake",
|
||||
expected_bundle_id="com.meeyao.qianwen",
|
||||
expected_product_id="com.meeyao.qianwen.basic_pack",
|
||||
expected_product_id="com.meeyao.qianwen.starter_pack",
|
||||
)
|
||||
assert isinstance(result, VerificationError)
|
||||
assert "x5c" in result.detail
|
||||
@@ -62,7 +62,7 @@ class TestAppleJwsVerifierInvalidInput:
|
||||
result = verifier.verify_signed_transaction(
|
||||
f"{h}.{p}.fake",
|
||||
expected_bundle_id="com.meeyao.qianwen",
|
||||
expected_product_id="com.meeyao.qianwen.basic_pack",
|
||||
expected_product_id="com.meeyao.qianwen.starter_pack",
|
||||
)
|
||||
assert isinstance(result, VerificationError)
|
||||
assert "fingerprint" in result.detail or "issuer" in result.detail or "subject" in result.detail
|
||||
|
||||
@@ -30,6 +30,7 @@ class _FakePaymentRepository:
|
||||
self.inserted_transactions: list[AppleIapTransaction] = []
|
||||
self.claim: RegisterBonusClaims | None = None
|
||||
self.claim_starter_pack_called: bool = False
|
||||
self.commit_count = 0
|
||||
|
||||
async def get_or_create_user_points_for_update(self, *, user_id: UUID) -> _FakeAccount:
|
||||
return self.account
|
||||
@@ -59,6 +60,9 @@ class _FakePaymentRepository:
|
||||
self.claim.has_purchased_starter_pack = True
|
||||
return self.claim
|
||||
|
||||
async def commit(self) -> None:
|
||||
self.commit_count += 1
|
||||
|
||||
|
||||
class _FakePointsRepository:
|
||||
def __init__(self) -> None:
|
||||
@@ -78,14 +82,17 @@ class _FakeVerifier:
|
||||
*,
|
||||
expected_bundle_id: str,
|
||||
expected_product_id: str,
|
||||
expected_environment: str,
|
||||
) -> VerifiedTransaction | VerificationError:
|
||||
del signed_transaction_info, expected_bundle_id, expected_product_id
|
||||
del expected_environment
|
||||
return self._result
|
||||
|
||||
|
||||
def _make_verified_transaction(
|
||||
*,
|
||||
transaction_id: str = "2000000123456789",
|
||||
product_id: str = "com.meeyao.qianwen.basic_pack",
|
||||
product_id: str = "com.meeyao.qianwen.starter_pack",
|
||||
environment: str = "Sandbox",
|
||||
) -> VerifiedTransaction:
|
||||
return VerifiedTransaction(
|
||||
@@ -134,7 +141,7 @@ class TestPaymentServiceProductMismatch:
|
||||
verifier=_FakeVerifier(result=_make_verified_transaction()),
|
||||
)
|
||||
request = VerifyTransactionRequest(
|
||||
productCode="basic_pack",
|
||||
productCode="starter_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.wrong_pack",
|
||||
transactionId="2000000123456789",
|
||||
signedTransactionInfo="fake_jws",
|
||||
@@ -162,8 +169,8 @@ class TestPaymentServiceVerificationFailed:
|
||||
),
|
||||
)
|
||||
request = VerifyTransactionRequest(
|
||||
productCode="basic_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.basic_pack",
|
||||
productCode="starter_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.starter_pack",
|
||||
transactionId="2000000123456789",
|
||||
signedTransactionInfo="fake_jws",
|
||||
)
|
||||
@@ -183,8 +190,8 @@ class TestPaymentServiceAlreadyGranted:
|
||||
existing = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=user_id,
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000123456789",
|
||||
original_transaction_id="2000000123456789",
|
||||
environment="Sandbox",
|
||||
@@ -202,8 +209,8 @@ class TestPaymentServiceAlreadyGranted:
|
||||
verifier=_FakeVerifier(result=_make_verified_transaction()),
|
||||
)
|
||||
request = VerifyTransactionRequest(
|
||||
productCode="basic_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.basic_pack",
|
||||
productCode="starter_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.starter_pack",
|
||||
transactionId="2000000123456789",
|
||||
signedTransactionInfo="fake_jws",
|
||||
)
|
||||
@@ -222,8 +229,8 @@ class TestPaymentServiceTransactionConflict:
|
||||
existing = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=uuid4(),
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000123456789",
|
||||
original_transaction_id="2000000123456789",
|
||||
environment="Sandbox",
|
||||
@@ -241,8 +248,8 @@ class TestPaymentServiceTransactionConflict:
|
||||
verifier=_FakeVerifier(result=_make_verified_transaction()),
|
||||
)
|
||||
request = VerifyTransactionRequest(
|
||||
productCode="basic_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.basic_pack",
|
||||
productCode="starter_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.starter_pack",
|
||||
transactionId="2000000123456789",
|
||||
signedTransactionInfo="fake_jws",
|
||||
)
|
||||
@@ -266,8 +273,8 @@ class TestPaymentServiceSuccessfulGrant:
|
||||
verifier=_FakeVerifier(result=_make_verified_transaction()),
|
||||
)
|
||||
request = VerifyTransactionRequest(
|
||||
productCode="basic_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.basic_pack",
|
||||
productCode="starter_pack",
|
||||
appStoreProductId="com.meeyao.qianwen.starter_pack",
|
||||
transactionId="2000000123456789",
|
||||
signedTransactionInfo="fake_jws",
|
||||
)
|
||||
@@ -368,6 +375,7 @@ class _FakePaymentRepoForRefund:
|
||||
self._transaction = transaction
|
||||
self.account = account or _FakeAccountForRefund()
|
||||
self.inserted_transactions: list[AppleIapTransaction] = []
|
||||
self.commit_count = 0
|
||||
|
||||
async def get_transaction_by_transaction_id(self, *, transaction_id: str) -> AppleIapTransaction | None:
|
||||
return self._transaction
|
||||
@@ -389,6 +397,9 @@ class _FakePaymentRepoForRefund:
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
async def commit(self) -> None:
|
||||
self.commit_count += 1
|
||||
|
||||
|
||||
class TestProcessRefundUnknownTransaction:
|
||||
@pytest.mark.asyncio
|
||||
@@ -407,8 +418,8 @@ class TestProcessRefundNotGranted:
|
||||
txn = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=uuid4(),
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000999999999",
|
||||
original_transaction_id="2000000999999999",
|
||||
environment="Sandbox",
|
||||
@@ -435,8 +446,8 @@ class TestProcessRefundSufficientBalance:
|
||||
txn = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=user_id,
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000999999999",
|
||||
original_transaction_id="2000000999999999",
|
||||
environment="Sandbox",
|
||||
@@ -473,8 +484,8 @@ class TestProcessRefundInsufficientBalance:
|
||||
txn = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=user_id,
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000999999998",
|
||||
original_transaction_id="2000000999999998",
|
||||
environment="Sandbox",
|
||||
@@ -509,8 +520,8 @@ class TestProcessRefundIdempotency:
|
||||
txn = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=user_id,
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000999999997",
|
||||
original_transaction_id="2000000999999997",
|
||||
environment="Sandbox",
|
||||
@@ -539,8 +550,8 @@ class TestHandleServerNotificationRefund:
|
||||
txn = AppleIapTransaction(
|
||||
id=uuid4(),
|
||||
user_id=user_id,
|
||||
product_code="basic_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.basic_pack",
|
||||
product_code="starter_pack",
|
||||
app_store_product_id="com.meeyao.qianwen.starter_pack",
|
||||
transaction_id="2000000999999001",
|
||||
original_transaction_id="2000000999999001",
|
||||
environment="Sandbox",
|
||||
|
||||
Reference in New Issue
Block a user