优化:支付走内购的逻辑改为当pay URL为空的时候才走内购

This commit is contained in:
ivan 2026-03-29 15:31:51 +08:00
parent 4ef714453e
commit a83c76edab
2 changed files with 386 additions and 343 deletions

View File

@ -2,14 +2,14 @@
## 通用信息
| 项目 | 值 |
|------|----|
| 加密方式 | AES-128-ECB, PKCS5Padding, Base64 |
| AES Key | `liyP4LkMfP68XvCt` |
| 预发域名 | `pre-ai.petsheroai.xyz` |
| 生产域名 | `ai.petsheroai.xyz` |
| 代理入口 | `POST {baseUrl}/quester/defender/summoner` |
| 包名 | `com.petsheroai.app` |
| 项目 | 值 |
| ------- | ------------------------------------------ |
| 加密方式 | AES-128-ECB, PKCS5Padding, Base64 |
| AES Key | `liyP4LkMfP68XvCt` |
| 预发域名 | `pre-ai.petsheroai.xyz` |
| 生产域名 | `ai.petsheroai.xyz` |
| 代理入口 | `POST {baseUrl}/quester/defender/summoner` |
| 包名 | `com.petsheroai.app` |
## 加密流程
@ -7087,322 +7087,323 @@ V2 完整响应体 (解密后):
## 错误码
| code | 说明 |
|------|------|
| 0 | 成功 |
| -1 | 失败 |
| -2 | 系统错误 |
| -3 | 鉴权失败 |
| -5 | 参数错误 |
| 1001 | 积分不足 |
| 1002 | 免费次数已用完 |
| code | 说明 |
| ---- | ----------- |
| 0 | 成功 |
| -1 | 失败 |
| -2 | 系统错误 |
| -3 | 鉴权失败 |
| -5 | 参数错误 |
| 1001 | 积分不足 |
| 1002 | 免费次数已用完 |
| 1003 | 免费次数和积分均已用完 |
## 字段映射全表
| 原始字段 | V2字段 |
|----------|--------|
| User_token | knight |
| accountId | wizard |
| accountName | captain |
| activityId | warrior |
| activitys | summon |
| actualAmount | guardian |
| addCredits | awaken |
| adsTokenId | champion |
| age | transform |
| amount | hero |
| animate | ascend |
| app | sentinel |
| appFbConfig | evolve |
| appType | ranger |
| appraise | unleash |
| approveState | paladin |
| aspectRatio | quest |
| automaticRenewal | legend |
| avatar | realm |
| baseCredits | wield |
| baseUrl | destiny |
| begTime | emblem |
| bonus | forge |
| bonusCredits | conjure |
| bonusRatio | enchant |
| businessId | vanquish |
| businessType | defend |
| campaignInfo | relic |
| card | artifact |
| categoryId | insignia |
| categoryName | patrol |
| ch | crest |
| channel | lineage |
| channelType | armor |
| client | shield |
| clientId | gauntlet |
| code | helm |
| coder | mantle |
| config | charge |
| content | cloak |
| contentType | pauldron |
| count | visor |
| countId | command |
| country | vambrace |
| countryCode | navigate |
| creatTime | explore |
| createTime | discover |
| createTimeText | uncover |
| credit | reveal |
| creditPromotion | unlock |
| credits | greaves |
| creditsRecordUrl | conquer |
| cryptoInvoiceUrl | protect |
| currency | familiar |
| current | empower |
| cvcCode | companion |
| data | sidekick |
| days | species |
| department | inspire |
| desc | valor |
| description | pedigree |
| devId | ancestry |
| deviceId | origin |
| discountOff | lead |
| domain | totem |
| domains | avatar |
| dt | sigil |
| duration | cosmos |
| email | galaxy |
| enabled | nebula |
| endTime | citadel |
| event | fortress |
| expectedSize | stronghold |
| expireMonth | dominion |
| expireYear | sanctuary |
| expiresIn | soar |
| ext | nexus |
| extConfig | surge |
| extJson | vanguard |
| face | dash |
| faceIndex | leap |
| faceInfos | strike |
| face_index | parry |
| feature | dodge |
| features | scout |
| feedbackId | track |
| feedbackIds | registry |
| fileName | layer |
| fileName1 | gateway |
| fileName2 | action |
| filePath | hunt |
| filePath1 | recruit |
| filePath2 | train |
| fileUrls | inventory |
| filterCountry | blueprint |
| filterDomain | vendor |
| filterOwnerId | participant |
| filterStatus | specimen |
| filterTaskType | package |
| filterVip | quotation |
| firstName | appointment |
| firstRegister | equip |
| forcePayCenter | upgrade |
| fps | notification |
| frameIndex | unite |
| frame_index | pledge |
| freeBlurTimes | vow |
| freeTimes | decree |
| gender | venture |
| googleClientId | discourse |
| h5UrlConfig | pursue |
| hasNext | manifest |
| hash | mediation |
| hashIsZero | corpus |
| headFaceIndex | histogram |
| headImg | agent |
| headPos | bond |
| headType | arena |
| hint | traverse |
| host | initiative |
| icon | greylist |
| id | federation |
| imageCount | simplify |
| imageFaceIndex | committee |
| imageId | royalty |
| imageInfos | curate |
| img | revenue |
| imgCount | declaration |
| imgId | criterion |
| imgList | downsample |
| imgType | reconnect |
| imgUrl | reconfigure |
| index | prewarm |
| inviteBy | item |
| invitedCnt | deduce |
| isBlur | reify |
| isVip | generate |
| issuerUrl | merge |
| keepUserId | series |
| label | subscribe |
| lang | seminar |
| lastName | bazaar |
| lastUpdateTime | probe |
| link | festival |
| list | junction |
| maxLimit | architect |
| method | heap |
| methodActivitys | modify |
| methodChannels | restore |
| model | authorization |
| msg | rampart |
| name | brigade |
| needCredits | deserialize |
| needImage | assembly |
| needUndress | directive |
| needopt | allowance |
| negativePrompt | underwriter |
| note | extrapolate |
| openType | transplant |
| optimizeCountSql | harvest |
| optimizeJoinOfCountSql | seek |
| orderId | gazette |
| orders | identify |
| originAmount | curriculum |
| owner | genealogy |
| p12KeyPath | arraignment |
| packageName | folio |
| page | trophy |
| pages | coordinate |
| password | township |
| payCenterUrl | switch |
| payId | assert |
| payMethod | intercept |
| payMethods | wallet |
| payStatus | destroy |
| payTime | restart |
| payTypeList | handshake |
| payUrl | convert |
| paylink | unzip |
| paymentMethod | resource |
| paymentMethods | renew |
| permissions | sandbox |
| phone | block |
| pkg | portal |
| platform | trigger |
| previewImage | extract |
| previewVideo | preempt |
| productType | subtract |
| progress | dice |
| prompt | ledger |
| publicKey | template |
| purchaseData | merchant |
| queueCnt | revert |
| read | redact |
| receipt | attendee |
| recent | entrap |
| recentlyUsed | finalize |
| recommend | deny |
| records | intensify |
| redirectUrl | disambiguate |
| referer | digest |
| refererType | campaign |
| replyStatus | voxelize |
| requiredHeaders | remap |
| resolution | booking |
| resolution480p | reverify |
| resolution720p | preprocess |
| resulotion | theorize |
| rewardCredits | represent |
| rewardRatio | render |
| role | evaluate |
| searchCount | suspend |
| selected | deploy |
| serviceAccountEmail | alert |
| sharedSecret | comment |
| showName | mold |
| sign | resolution |
| signature | sample |
| size | heatmap |
| sort | invent |
| srcFaceImgBase64 | attachment |
| srcFaceIndex | stadium |
| srcImg | refuge |
| srcImg1 | endeavor |
| srcImg1Url | guild |
| srcImg2 | balance |
| srcImg2Url | commission |
| srcImgBase64 | profit |
| srcImgUrl | statute |
| srcVideo | compendium |
| state | listing |
| status | line |
| style | webinar |
| subBusinessType | tailor |
| subPaymentMethod | ceremony |
| subScribeValidTime | tokenize |
| subscriptionActivitys | cleanse |
| subscriptionPeriod | distribute |
| sumCredits | emit |
| sys | associate |
| t2IConfig | regulate |
| tag | constrain |
| tags | rally |
| targetId | node |
| targetInvitedCnt | authorize |
| taskId | tree |
| taskIds | privilege |
| taskType | cipher |
| taskTypes | platoon |
| templateFaceUrl | simulate |
| templateFifCredits | pause |
| templateFifDuration | decommission |
| templateFifUrl | acknowledge |
| templateName | congregation |
| templateTfCredits | pipe |
| templateTfDuration | unwrap |
| templateTfUrl | extend |
| templateType | recharge |
| templateTypes | endowment |
| templateUrl | inject |
| tgId | concession |
| tgName | defer |
| tgOrderId | insurer |
| theme | parallelize |
| title | glossary |
| token | thesis |
| total | weigh |
| totalUnreadCount | defragment |
| transactionId | chronicle |
| truePrompt | deposition |
| ts | quarto |
| type | accolade |
| types | municipality |
| unreadCountList | footprint |
| updateTime | fork |
| uploadUrl | shed |
| uploadUrl1 | bolster |
| uploadUrl2 | expound |
| url | digitize |
| user | rebalance |
| userApplePayList | gallery |
| userId | asset |
| userInfoType | frame |
| userName | terminal |
| userToken | reevaluate |
| userType | prefetch |
| username | pulse |
| usign | retrospect |
| val | journal |
| value | schema |
| verifyCode | supplier |
| videoDuration | demonstrate |
| videoFaceIndex | applicant |
| videoFrameIndex | fragment |
| videoSize | summary |
| videoUrl | promotion |
| waitTime | flowStep |
| x1 | invoke |
| x2 | sync |
| y1 | configure |
| y2 | manufacture |
| 原始字段 | V2字段 |
| ---------------------- | ------------- |
| User\_token | knight |
| accountId | wizard |
| accountName | captain |
| activityId | warrior |
| activitys | summon |
| actualAmount | guardian |
| addCredits | awaken |
| adsTokenId | champion |
| age | transform |
| amount | hero |
| animate | ascend |
| app | sentinel |
| appFbConfig | evolve |
| appType | ranger |
| appraise | unleash |
| approveState | paladin |
| aspectRatio | quest |
| automaticRenewal | legend |
| avatar | realm |
| baseCredits | wield |
| baseUrl | destiny |
| begTime | emblem |
| bonus | forge |
| bonusCredits | conjure |
| bonusRatio | enchant |
| businessId | vanquish |
| businessType | defend |
| campaignInfo | relic |
| card | artifact |
| categoryId | insignia |
| categoryName | patrol |
| ch | crest |
| channel | lineage |
| channelType | armor |
| client | shield |
| clientId | gauntlet |
| code | helm |
| coder | mantle |
| config | charge |
| content | cloak |
| contentType | pauldron |
| count | visor |
| countId | command |
| country | vambrace |
| countryCode | navigate |
| creatTime | explore |
| createTime | discover |
| createTimeText | uncover |
| credit | reveal |
| creditPromotion | unlock |
| credits | greaves |
| creditsRecordUrl | conquer |
| cryptoInvoiceUrl | protect |
| currency | familiar |
| current | empower |
| cvcCode | companion |
| data | sidekick |
| days | species |
| department | inspire |
| desc | valor |
| description | pedigree |
| devId | ancestry |
| deviceId | origin |
| discountOff | lead |
| domain | totem |
| domains | avatar |
| dt | sigil |
| duration | cosmos |
| email | galaxy |
| enabled | nebula |
| endTime | citadel |
| event | fortress |
| expectedSize | stronghold |
| expireMonth | dominion |
| expireYear | sanctuary |
| expiresIn | soar |
| ext | nexus |
| extConfig | surge |
| extJson | vanguard |
| face | dash |
| faceIndex | leap |
| faceInfos | strike |
| face\_index | parry |
| feature | dodge |
| features | scout |
| feedbackId | track |
| feedbackIds | registry |
| fileName | layer |
| fileName1 | gateway |
| fileName2 | action |
| filePath | hunt |
| filePath1 | recruit |
| filePath2 | train |
| fileUrls | inventory |
| filterCountry | blueprint |
| filterDomain | vendor |
| filterOwnerId | participant |
| filterStatus | specimen |
| filterTaskType | package |
| filterVip | quotation |
| firstName | appointment |
| firstRegister | equip |
| forcePayCenter | upgrade |
| fps | notification |
| frameIndex | unite |
| frame\_index | pledge |
| freeBlurTimes | vow |
| freeTimes | decree |
| gender | venture |
| googleClientId | discourse |
| h5UrlConfig | pursue |
| hasNext | manifest |
| hash | mediation |
| hashIsZero | corpus |
| headFaceIndex | histogram |
| headImg | agent |
| headPos | bond |
| headType | arena |
| hint | traverse |
| host | initiative |
| icon | greylist |
| id | federation |
| imageCount | simplify |
| imageFaceIndex | committee |
| imageId | royalty |
| imageInfos | curate |
| img | revenue |
| imgCount | declaration |
| imgId | criterion |
| imgList | downsample |
| imgType | reconnect |
| imgUrl | reconfigure |
| index | prewarm |
| inviteBy | item |
| invitedCnt | deduce |
| isBlur | reify |
| isVip | generate |
| issuerUrl | merge |
| keepUserId | series |
| label | subscribe |
| lang | seminar |
| lastName | bazaar |
| lastUpdateTime | probe |
| link | festival |
| list | junction |
| maxLimit | architect |
| method | heap |
| methodActivitys | modify |
| methodChannels | restore |
| model | authorization |
| msg | rampart |
| name | brigade |
| needCredits | deserialize |
| needImage | assembly |
| needUndress | directive |
| needopt | allowance |
| negativePrompt | underwriter |
| note | extrapolate |
| openType | transplant |
| optimizeCountSql | harvest |
| optimizeJoinOfCountSql | seek |
| orderId | gazette |
| orders | identify |
| originAmount | curriculum |
| owner | genealogy |
| p12KeyPath | arraignment |
| packageName | folio |
| page | trophy |
| pages | coordinate |
| password | township |
| payCenterUrl | switch |
| payId | assert |
| payMethod | intercept |
| payMethods | wallet |
| payStatus | destroy |
| payTime | restart |
| payTypeList | handshake |
| payUrl | convert |
| paylink | unzip |
| paymentMethod | resource |
| paymentMethods | renew |
| permissions | sandbox |
| phone | block |
| pkg | portal |
| platform | trigger |
| previewImage | extract |
| previewVideo | preempt |
| productType | subtract |
| progress | dice |
| prompt | ledger |
| publicKey | template |
| purchaseData | merchant |
| queueCnt | revert |
| read | redact |
| receipt | attendee |
| recent | entrap |
| recentlyUsed | finalize |
| recommend | deny |
| records | intensify |
| redirectUrl | disambiguate |
| referer | digest |
| refererType | campaign |
| replyStatus | voxelize |
| requiredHeaders | remap |
| resolution | booking |
| resolution480p | reverify |
| resolution720p | preprocess |
| resulotion | theorize |
| rewardCredits | represent |
| rewardRatio | render |
| role | evaluate |
| searchCount | suspend |
| selected | deploy |
| serviceAccountEmail | alert |
| sharedSecret | comment |
| showName | mold |
| sign | resolution |
| signature | sample |
| size | heatmap |
| sort | invent |
| srcFaceImgBase64 | attachment |
| srcFaceIndex | stadium |
| srcImg | refuge |
| srcImg1 | endeavor |
| srcImg1Url | guild |
| srcImg2 | balance |
| srcImg2Url | commission |
| srcImgBase64 | profit |
| srcImgUrl | statute |
| srcVideo | compendium |
| state | listing |
| status | line |
| style | webinar |
| subBusinessType | tailor |
| subPaymentMethod | ceremony |
| subScribeValidTime | tokenize |
| subscriptionActivitys | cleanse |
| subscriptionPeriod | distribute |
| sumCredits | emit |
| sys | associate |
| t2IConfig | regulate |
| tag | constrain |
| tags | rally |
| targetId | node |
| targetInvitedCnt | authorize |
| taskId | tree |
| taskIds | privilege |
| taskType | cipher |
| taskTypes | platoon |
| templateFaceUrl | simulate |
| templateFifCredits | pause |
| templateFifDuration | decommission |
| templateFifUrl | acknowledge |
| templateName | congregation |
| templateTfCredits | pipe |
| templateTfDuration | unwrap |
| templateTfUrl | extend |
| templateType | recharge |
| templateTypes | endowment |
| templateUrl | inject |
| tgId | concession |
| tgName | defer |
| tgOrderId | insurer |
| theme | parallelize |
| title | glossary |
| token | thesis |
| total | weigh |
| totalUnreadCount | defragment |
| transactionId | chronicle |
| truePrompt | deposition |
| ts | quarto |
| type | accolade |
| types | municipality |
| unreadCountList | footprint |
| updateTime | fork |
| uploadUrl | shed |
| uploadUrl1 | bolster |
| uploadUrl2 | expound |
| url | digitize |
| user | rebalance |
| userApplePayList | gallery |
| userId | asset |
| userInfoType | frame |
| userName | terminal |
| userToken | reevaluate |
| userType | prefetch |
| username | pulse |
| usign | retrospect |
| val | journal |
| value | schema |
| verifyCode | supplier |
| videoDuration | demonstrate |
| videoFaceIndex | applicant |
| videoFrameIndex | fragment |
| videoSize | summary |
| videoUrl | promotion |
| waitTime | flowStep |
| x1 | invoke |
| x2 | sync |
| y1 | configure |
| y2 | manufacture |
---
*本文档由 ProtocolEncTool 自动生成API 变更后请重新执行生成命令。*
***
*本文档由 ProtocolEncTool 自动生成API 变更后请重新执行生成命令。transplant*

View File

@ -1,6 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../core/adjust/adjust_events.dart';
import '../../core/api/api_config.dart';
@ -37,6 +38,11 @@ class _RechargeScreenState extends State<RechargeScreen>
/// code item Buy loading
String? _loadingProductId;
///
String? _pendingOrderId;
String? _pendingUserId;
double? _pendingPurchaseAmount;
@override
void initState() {
@ -61,6 +67,23 @@ class _RechargeScreenState extends State<RechargeScreen>
mounted) {
setState(() => _loadingProductId = null);
}
//
if (state == AppLifecycleState.resumed &&
_pendingOrderId != null &&
_pendingUserId != null &&
_pendingPurchaseAmount != null &&
mounted) {
_startOrderPolling(
orderId: _pendingOrderId!,
userId: _pendingUserId!,
purchaseAmount: _pendingPurchaseAmount!,
);
//
_pendingOrderId = null;
_pendingUserId = null;
_pendingPurchaseAmount = null;
}
}
Future<void> _fetchActivities() async {
@ -260,32 +283,48 @@ class _RechargeScreenState extends State<RechargeScreen>
: null;
final orderId = data?['federation']?.toString();
if (_isGooglePay(paymentMethod, subPaymentMethod)) {
final purchaseAmount =
(AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble();
final payUrl = data?['convert']?.toString();
final openType = data?['transplant'] as int?;
if (_shouldUseGooglePay(payUrl)) {
await _launchGooglePlayPurchase(item,
serverOrderId: orderId, userId: userId);
return;
}
final purchaseAmount =
(AdjustEvents.parsePrice(item.actualAmount) ?? 0).toDouble();
final payUrl = data?['convert']?.toString();
if (payUrl != null && payUrl.isNotEmpty) {
if (mounted) {
setState(() => _loadingProductId = null);
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => PaymentWebViewScreen(paymentUrl: payUrl),
),
);
if (mounted && orderId != null && orderId.isNotEmpty) {
_startOrderPolling(
orderId: orderId,
userId: userId,
purchaseAmount: purchaseAmount,
if (_shouldUseSystemBrowser(openType)) {
//
await launchUrl(Uri.parse(payUrl), mode: LaunchMode.externalApplication);
// didChangeAppLifecycleState
_pendingOrderId = orderId;
_pendingUserId = userId;
_pendingPurchaseAmount = purchaseAmount;
_showSnackBar(
context, 'Order created. Complete payment in the browser.');
} else {
//
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => PaymentWebViewScreen(paymentUrl: payUrl),
),
);
//
if (mounted && orderId != null && orderId.isNotEmpty) {
_startOrderPolling(
orderId: orderId,
userId: userId,
purchaseAmount: purchaseAmount,
);
}
_showSnackBar(
context, 'Order created. Complete payment in the page.');
}
_showSnackBar(
context, 'Order created. Complete payment in the page.');
}
} else {
if (mounted) {
@ -354,11 +393,14 @@ class _RechargeScreenState extends State<RechargeScreen>
poll(0);
}
/// ceremony==GooglePay resource==GOOGLEPAY
static bool _isGooglePay(String paymentMethod, String? subPaymentMethod) {
final r = paymentMethod.trim().toLowerCase();
final c = (subPaymentMethod ?? '').trim().toLowerCase();
return r == 'googlepay' || c == 'googlepay';
/// payUrl
static bool _shouldUseGooglePay(String? payUrl) {
return payUrl == null || payUrl.isEmpty;
}
/// openType 0=1==
static bool _shouldUseSystemBrowser(int? openType) {
return openType == 1;
}
/// false Google Pay