feat: Flexion 先验签后消费支付流程 + playerId 绑定
实现 Flexion 渠道支付验签重构:支付成功后不立即消费,将 purchaseJson/signature/purchaseToken 回调至 Unity,由服务端 SHA1withRSA 验签并校验 developerPayload.playerId 后再调用 consume。 同步更新 SDKManager 接口、UnityBridgeFunc 桥接、TYSdkModel 字段及 ExtraPluginCfgs。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,48 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.arkgame.ft"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<application android:extractNativeLibs="true" android:name="com.unity3d.player.TYApp" android:usesCleartextTraffic="true">
|
||||
<activity android:name="com.unity3d.player.TYUnityActivity"
|
||||
android:theme="@style/UnityThemeSelector">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" android:host="fishingtraveliae.onelink.me" android:pathPrefix="/jT1Q"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:host="mainactivity" android:scheme="zzft" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||
|
||||
<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="true" />
|
||||
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="true" />
|
||||
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="true" />
|
||||
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="true" />
|
||||
|
||||
</activity>
|
||||
<meta-data android:name="CHANNEL" android:value="GooglePlay" />
|
||||
</application>
|
||||
<queries>
|
||||
<provider android:authorities="com.facebook.katana.provider.PlatformProvider" /> <!-- allows app to access Facebook app features -->
|
||||
<provider android:authorities="com.facebook.orca.provider.PlatformProvider" /> <!-- allows sharing to Messenger app -->
|
||||
<intent>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.arkgame.ft.flexion" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<application android:extractNativeLibs="true" android:name="com.unity3d.player.TYApp" tools:replace="android:usesCleartextTraffic,android:fullBackupContent" android:fullBackupContent="@xml/flexion_backup_rules" android:usesCleartextTraffic="true">
|
||||
<activity android:name="com.unity3d.player.TYUnityActivity" android:theme="@style/UnityThemeSelector">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https" android:host="fishingtraveliae.onelink.me" android:pathPrefix="/jT1Q" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:host="mainactivity" android:scheme="zzft" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
|
||||
</activity>
|
||||
<!-- 渠道标识,ChannelManager 读取此值以识别 Flexion 渠道 -->
|
||||
<meta-data android:name="CHANNEL" android:value="Flexion" />
|
||||
<!-- 覆盖 gasdk 与 tuyoosdk 的 MainProcessName 冲突 -->
|
||||
<meta-data android:name="com.sensorsdata.analytics.android.MainProcessName" android:value="com.arkgame.ft.flexion" tools:replace="android:value" />
|
||||
<!-- Flexion SDK 应用标识,从 DropPoint 获取 -->
|
||||
<meta-data android:name="com.flexionmobile.fdk.apptoken" android:value="fishingtravel" />
|
||||
<!-- 告知 Flexion SDK 当前为 Unity 项目,必须声明 -->
|
||||
<meta-data android:name="com.flexionmobile.fdk.sdk-type" android:value="unity" />
|
||||
<!--
|
||||
覆盖 tuyoosdk AAR 中硬编码的 Facebook ContentProvider authority。
|
||||
AAR 原值:com.facebook.app.FacebookContentProvider162066986963808
|
||||
追加 ${applicationId}(Flexion 包名)作为后缀后,与 GP 版 authority 不同,
|
||||
两个渠道包可同时安装在同一设备上,不会触发 INSTALL_FAILED_CONFLICTING_PROVIDER。
|
||||
参考:Flexion 官方文档《Unique package name - follow-on requirements》
|
||||
|
||||
<provider
|
||||
android:name="com.facebook.FacebookContentProvider"
|
||||
android:authorities="com.facebook.app.FacebookContentProvider162066986963808.${applicationId}"
|
||||
android:exported="true"
|
||||
tools:replace="android:authorities" />
|
||||
-->
|
||||
</application>
|
||||
<queries>
|
||||
<provider android:authorities="com.facebook.katana.provider.PlatformProvider" />
|
||||
<provider android:authorities="com.facebook.orca.provider.PlatformProvider" />
|
||||
</queries>
|
||||
</manifest>
|
||||
@@ -82,9 +82,7 @@ dependencies {
|
||||
implementation 'com.applovin.mediation:vungle-adapter:7.4.2.2' // Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml:4
|
||||
implementation 'com.applovin:applovin-sdk:13.5.1' // Assets/MaxSdk/AppLovin/Editor/Dependencies.xml:4
|
||||
implementation 'com.appsflyer:af-android-sdk:6.17.3' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:5
|
||||
// Flexion: purchase-connector removed — Flexion does not use Google Play Billing.
|
||||
// Also covered by top-level `configurations.all { exclude ... }` as a safety net.
|
||||
// implementation 'com.appsflyer:purchase-connector:2.2.0' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
|
||||
implementation 'com.appsflyer:purchase-connector:2.2.0' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:8
|
||||
implementation 'com.appsflyer:unity-wrapper:6.17.7' // Assets/AppsFlyer/Editor/AppsFlyerDependencies.xml:6
|
||||
implementation 'com.google.android.ump:user-messaging-platform:2.1.0' // Assets/MaxSdk/AppLovin/Editor/Dependencies.xml:5
|
||||
// Android Resolver Dependencies End
|
||||
|
||||
@@ -1964,6 +1964,85 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &783615086
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 783615087}
|
||||
- component: {fileID: 783615089}
|
||||
- component: {fileID: 783615088}
|
||||
m_Layer: 5
|
||||
m_Name: Title
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &783615087
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 783615086}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 1451597222}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -57}
|
||||
m_SizeDelta: {x: 294.3188, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &783615088
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 783615086}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.8207547, g: 0.8207547, b: 0.8207547, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_FontData:
|
||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_FontSize: 27
|
||||
m_FontStyle: 0
|
||||
m_BestFit: 0
|
||||
m_MinSize: 0
|
||||
m_MaxSize: 61
|
||||
m_Alignment: 4
|
||||
m_AlignByGeometry: 0
|
||||
m_RichText: 1
|
||||
m_HorizontalOverflow: 0
|
||||
m_VerticalOverflow: 0
|
||||
m_LineSpacing: 1
|
||||
m_Text: GooglePlay
|
||||
--- !u!222 &783615089
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 783615086}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!1 &816060983
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -4263,6 +4342,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 783615087}
|
||||
- {fileID: 2070325009}
|
||||
- {fileID: 1044920373}
|
||||
m_Father: {fileID: 0}
|
||||
@@ -4968,6 +5048,7 @@ MonoBehaviour:
|
||||
_mfbShareLinkBtn: {fileID: 1240291501}
|
||||
_reviewBtn: {fileID: 678940591}
|
||||
_messageTxt: {fileID: 2070325010}
|
||||
_titleText: {fileID: 783615088}
|
||||
--- !u!4 &1788702880
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -5417,7 +5498,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 1}
|
||||
m_AnchorMax: {x: 0.5, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -120}
|
||||
m_AnchoredPosition: {x: 0, y: -152}
|
||||
m_SizeDelta: {x: 800, y: 100}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &2070325010
|
||||
|
||||
@@ -62,6 +62,9 @@ public class SDKTest : MonoBehaviour
|
||||
|
||||
[SerializeField]
|
||||
private Text _messageTxt;
|
||||
|
||||
[SerializeField]
|
||||
private Text _titleText;
|
||||
|
||||
void Start()
|
||||
{
|
||||
@@ -71,6 +74,7 @@ public class SDKTest : MonoBehaviour
|
||||
GContext.container.RegisterInstance<IConfig>(config);
|
||||
|
||||
Debug.Log("SDKTest Start");
|
||||
UpdateChannelTitle();
|
||||
//===============================================================================
|
||||
//====================== Test Server ===========================
|
||||
// UnityBridgeFunc.UnityResetServerUrl("https://128-hwsfsdk-sdk-test01.qijihdhk.com");
|
||||
@@ -130,6 +134,18 @@ public class SDKTest : MonoBehaviour
|
||||
UnityBridgeFunc.UnityResetServerUrl("https://128-hwsfsdk-sdk-test01.qijihdhk.com");
|
||||
}
|
||||
|
||||
private void UpdateChannelTitle()
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
using (var cls = new AndroidJavaClass("com.unity3d.player.ChannelHelpers"))
|
||||
{
|
||||
string channel = cls.GetStatic<string>("CHANNEL");
|
||||
Debug.Log($"[SDKTest] Channel from Java: {channel}");
|
||||
_titleText.text = $" {channel}";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int retryAttempt;
|
||||
|
||||
public void InitializeRewardedAds()
|
||||
@@ -161,6 +177,7 @@ public class SDKTest : MonoBehaviour
|
||||
_messageTxt.text = $"Login: {info.isSuccess}";
|
||||
if (info.isSuccess)
|
||||
{
|
||||
_messageTxt.text += $" UserId:{info.userId}";
|
||||
_messageTxt.text += $"\n{info.msg}";
|
||||
_messageTxt.text += $"\n{TYSdkFacade.TYAccountInfo.token}";
|
||||
}
|
||||
@@ -187,10 +204,23 @@ public class SDKTest : MonoBehaviour
|
||||
public async void OnPayTestBtn()
|
||||
{
|
||||
_messageTxt.text = "";
|
||||
|
||||
if (ChannelConfig.Channel.Equals("Flexion"))
|
||||
{
|
||||
sku = new SKUDetail
|
||||
{
|
||||
productId = "com.arkgame.ft.pack0199",
|
||||
ourProductId = "com.arkgame.ft.pack0199",
|
||||
price = "1.99",
|
||||
price_amount_micros = "1990000",
|
||||
title = "Flexion Test Pack",
|
||||
type = "inapp"
|
||||
};
|
||||
}
|
||||
if (sku == null){
|
||||
_messageTxt.text = "no product";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_IOS
|
||||
sku.productId = "comarkgameftpack0199";
|
||||
@@ -201,7 +231,7 @@ public class SDKTest : MonoBehaviour
|
||||
var purchaseInfo = new JObject();
|
||||
purchaseInfo["pfid"] = "TestPlayer";
|
||||
purchaseInfo["customData"] = "{\"test\":\"test\"}";
|
||||
|
||||
purchaseInfo["playerId"] = TYSdkFacade.TYAccountInfo.strUserId;
|
||||
|
||||
PaymentInfo payResult = await TYSdkFacade.Instance.Pay(sku, 1, sku.ProdPrice, purchaseInfo);
|
||||
_messageTxt.text = "\n" + $"Success : {payResult.isSuccess}";
|
||||
@@ -220,6 +250,7 @@ public class SDKTest : MonoBehaviour
|
||||
_messageTxt.text = "products count:::" + result.products.Count;
|
||||
_messageTxt.text += "\n" + result.products[0].ToString();
|
||||
sku = result.products[0];
|
||||
Debug.Log($"Sku -> {sku}");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user