update:更新tysdk 默认修改
This commit is contained in:
@@ -25,4 +25,5 @@ public class ConfigManager {
|
|||||||
public static final String PAY_TYPE_CALLBACK_FUNCTION_NAME = "SKUListResult";
|
public static final String PAY_TYPE_CALLBACK_FUNCTION_NAME = "SKUListResult";
|
||||||
public static final String FCM_NOTICE_FUNCTION_NAME = "FCMCallback";
|
public static final String FCM_NOTICE_FUNCTION_NAME = "FCMCallback";
|
||||||
public static final String FCM_REALNAME_CALLBACK_FUNCTION_NAME = "RealNameCallback";
|
public static final String FCM_REALNAME_CALLBACK_FUNCTION_NAME = "RealNameCallback";
|
||||||
|
public static final String INIT_CALLBACK_FUNCTION_NAME = "InitResult";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,12 +126,26 @@ public class SDKManager {
|
|||||||
TYUnityActivity.setSdkInited();
|
TYUnityActivity.setSdkInited();
|
||||||
SDKAPI.getIns().onActivityStart(activity);
|
SDKAPI.getIns().onActivityStart(activity);
|
||||||
SDKAPI.getIns().onActivityResume(activity);
|
SDKAPI.getIns().onActivityResume(activity);
|
||||||
|
notifyInitResult(true, "ok");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("initSDK Exception " + e);
|
System.out.println("initSDK Exception " + e);
|
||||||
|
notifyInitResult(false, e.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void notifyInitResult(boolean success, String msg) {
|
||||||
|
try {
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
result.put("code", success ? 0 : 1);
|
||||||
|
result.put("msg", msg);
|
||||||
|
UnityPlayer.UnitySendMessage(ConfigManager.UNITY_FACADE_NAME,
|
||||||
|
ConfigManager.INIT_CALLBACK_FUNCTION_NAME, result.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG, "notifyInitResult error: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Login / Callbacks (shared)
|
// Login / Callbacks (shared)
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using asap.core;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
@@ -10,122 +11,181 @@ namespace tysdk
|
|||||||
{
|
{
|
||||||
public interface IPaymentVerifier
|
public interface IPaymentVerifier
|
||||||
{
|
{
|
||||||
Task<VerifyResult> Verify(PaymentInfo info);
|
Task<PaymentVerifyResult> VerifyAsync(PaymentInfo info);
|
||||||
void Consume(string token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VerifyResult
|
public interface IPurchaseConsumer
|
||||||
|
{
|
||||||
|
Task<PurchaseConsumeResult> ConsumeAsync(string token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PaymentVerifyResult
|
||||||
|
{
|
||||||
|
public bool success;
|
||||||
|
public string msg;
|
||||||
|
public string orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FlexionOrderResult
|
||||||
|
{
|
||||||
|
public int code { get; set; }
|
||||||
|
public string info { get; set; }
|
||||||
|
public string orderId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PurchaseConsumeResult
|
||||||
{
|
{
|
||||||
public bool success;
|
public bool success;
|
||||||
public string msg;
|
public string msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PaymentVerifierFactory
|
public class PaymentProcessor
|
||||||
{
|
{
|
||||||
public static IPaymentVerifier GetVerifier()
|
public IPaymentVerifier verifier;
|
||||||
|
public IPurchaseConsumer consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PaymentProcessorFactory
|
||||||
|
{
|
||||||
|
private static PaymentProcessor _processor;
|
||||||
|
private static string _cachedChannel;
|
||||||
|
|
||||||
|
public static PaymentProcessor GetProcessor()
|
||||||
{
|
{
|
||||||
return ChannelConfig.Channel switch
|
var channel = ChannelConfig.Channel;
|
||||||
|
if (_processor != null && _cachedChannel == channel)
|
||||||
|
return _processor;
|
||||||
|
|
||||||
|
_processor = channel switch
|
||||||
{
|
{
|
||||||
"Flexion" => new RetryablePaymentVerifier(new FlexionPaymentVerifier()),
|
"Flexion" => new PaymentProcessor
|
||||||
"Dummy" => new RetryablePaymentVerifier(new DummyPaymentVerifier()),
|
{
|
||||||
|
verifier = new RetryingPaymentVerifier(new FlexionPaymentVerifier()),
|
||||||
|
consumer = new FlexionPurchaseConsumer()
|
||||||
|
},
|
||||||
|
"Dummy" => new PaymentProcessor
|
||||||
|
{
|
||||||
|
verifier = new RetryingPaymentVerifier(new FakePaymentVerifier()),
|
||||||
|
consumer = new FakePurchaseConsumer()
|
||||||
|
},
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
|
_cachedChannel = channel;
|
||||||
|
return _processor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RetryablePaymentVerifier : IPaymentVerifier
|
public class RetryingPaymentVerifier : IPaymentVerifier
|
||||||
{
|
{
|
||||||
private readonly IPaymentVerifier _inner;
|
private readonly IPaymentVerifier _inner;
|
||||||
private const int MaxRetries = 2;
|
private const int MaxRetries = 2;
|
||||||
private static readonly TimeSpan RetryInterval = TimeSpan.FromSeconds(2);
|
private static readonly TimeSpan RetryInterval = TimeSpan.FromSeconds(2);
|
||||||
|
|
||||||
public RetryablePaymentVerifier(IPaymentVerifier inner)
|
public RetryingPaymentVerifier(IPaymentVerifier inner)
|
||||||
{
|
{
|
||||||
_inner = inner;
|
_inner = inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<VerifyResult> Verify(PaymentInfo info)
|
public async Task<PaymentVerifyResult> VerifyAsync(PaymentInfo info)
|
||||||
{
|
{
|
||||||
VerifyResult lastResult = null;
|
PaymentVerifyResult lastResult = null;
|
||||||
for (int attempt = 0; attempt <= MaxRetries; attempt++)
|
for (int attempt = 0; attempt <= MaxRetries; attempt++)
|
||||||
{
|
{
|
||||||
if (attempt > 0)
|
if (attempt > 0)
|
||||||
{
|
{
|
||||||
Debug.Log($"[RetryableVerifier] Flow retry {attempt}/{MaxRetries}, waiting {RetryInterval.TotalSeconds}s");
|
Debug.Log($"[RetryingPaymentVerifier] Retry {attempt}/{MaxRetries}, waiting {RetryInterval.TotalSeconds}s");
|
||||||
await Task.Delay(RetryInterval);
|
await Task.Delay(RetryInterval);
|
||||||
}
|
}
|
||||||
lastResult = await _inner.Verify(info);
|
|
||||||
|
lastResult = await _inner.VerifyAsync(info);
|
||||||
if (lastResult.success) return lastResult;
|
if (lastResult.success) return lastResult;
|
||||||
Debug.LogWarning($"[RetryableVerifier] Flow attempt {attempt + 1} failed: {lastResult.msg}");
|
|
||||||
|
Debug.LogWarning($"[RetryingPaymentVerifier] Attempt {attempt + 1} failed: {lastResult.msg}");
|
||||||
}
|
}
|
||||||
return lastResult;
|
return lastResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Consume(string token) => _inner.Consume(token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FlexionPaymentVerifier : IPaymentVerifier
|
public class FlexionPaymentVerifier : IPaymentVerifier
|
||||||
{
|
{
|
||||||
// TODO: 替换为实际游戏服务端验签 URL
|
private const string DEFAULT_PAY_VERIFY_URL = "http://192.168.9.91:7036/api/FlexionCallback";
|
||||||
private const string VERIFY_URL = "https://YOUR_GAME_SERVER/api/pay/verify";
|
|
||||||
|
private readonly string _verifyUrl;
|
||||||
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(30);
|
private static readonly TimeSpan Timeout = TimeSpan.FromSeconds(30);
|
||||||
private const int MaxRetries = 2;
|
|
||||||
private static readonly TimeSpan RetryBackoff = TimeSpan.FromSeconds(2);
|
public FlexionPaymentVerifier()
|
||||||
|
{
|
||||||
|
var config = GContext.container.Resolve<IConfig>();
|
||||||
|
_verifyUrl = config.Get<string>("PAY_VERIFY_URL", DEFAULT_PAY_VERIFY_URL);
|
||||||
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
public async Task<VerifyResult> Verify(PaymentInfo info)
|
public async Task<PaymentVerifyResult> VerifyAsync(PaymentInfo info)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[FlexionPaymentVerifier] Editor placeholder: auto success");
|
Debug.LogWarning("[FlexionPaymentVerifier] Editor placeholder: auto success");
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
return new VerifyResult { success = true, msg = "editor_placeholder" };
|
return new PaymentVerifyResult { success = true, msg = "editor_placeholder" };
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public async Task<VerifyResult> Verify(PaymentInfo info)
|
public async Task<PaymentVerifyResult> VerifyAsync(PaymentInfo info)
|
||||||
{
|
|
||||||
VerifyResult lastResult = null;
|
|
||||||
for (int attempt = 0; attempt <= MaxRetries; attempt++)
|
|
||||||
{
|
|
||||||
if (attempt > 0)
|
|
||||||
{
|
|
||||||
var delay = TimeSpan.FromSeconds(RetryBackoff.TotalSeconds * attempt);
|
|
||||||
Debug.Log($"[FlexionPaymentVerifier] HTTP retry {attempt}/{MaxRetries}, waiting {delay.TotalSeconds}s");
|
|
||||||
await Task.Delay(delay);
|
|
||||||
}
|
|
||||||
lastResult = await SendVerifyRequest(info);
|
|
||||||
if (lastResult.success) return lastResult;
|
|
||||||
Debug.LogWarning($"[FlexionPaymentVerifier] HTTP attempt {attempt + 1} failed: {lastResult.msg}");
|
|
||||||
}
|
|
||||||
return lastResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<VerifyResult> SendVerifyRequest(PaymentInfo info)
|
|
||||||
{
|
{
|
||||||
var cts = new CancellationTokenSource(Timeout);
|
var cts = new CancellationTokenSource(Timeout);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Debug.Log("[FlexionPaymentVerifier] Sending verification request");
|
Debug.Log($"[FlexionPaymentVerifier] VerifyAsync start: url={_verifyUrl}");
|
||||||
|
Debug.Log($"[FlexionPaymentVerifier] Verify fields: orderId={info.orderId} productId={info.productId}" +
|
||||||
|
$" hasPurchaseJson={!string.IsNullOrEmpty(info.purchaseJson)} hasSignature={!string.IsNullOrEmpty(info.signature)}" +
|
||||||
|
$" purchaseToken={info.purchaseToken}");
|
||||||
|
|
||||||
var body = JsonConvert.SerializeObject(info);
|
var body = JsonConvert.SerializeObject(info);
|
||||||
using var req = new UnityWebRequest(VERIFY_URL, "POST");
|
Debug.Log("[FlexionPaymentVerifier] Request body: " + body);
|
||||||
|
|
||||||
|
using var req = new UnityWebRequest(_verifyUrl, "POST");
|
||||||
|
req.certificateHandler = new BypassCertificateHandler();
|
||||||
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
|
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
|
||||||
req.downloadHandler = new DownloadHandlerBuffer();
|
req.downloadHandler = new DownloadHandlerBuffer();
|
||||||
req.SetRequestHeader("Content-Type", "application/json");
|
req.SetRequestHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<VerifyResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
var tcs = new TaskCompletionSource<PaymentVerifyResult>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
cts.Token.Register(() => tcs.TrySetResult(new VerifyResult { success = false, msg = "timeout" }));
|
cts.Token.Register(() => tcs.TrySetResult(new PaymentVerifyResult { success = false, msg = "timeout" }));
|
||||||
|
|
||||||
req.SendWebRequest().completed += _ =>
|
req.SendWebRequest().completed += _ =>
|
||||||
{
|
{
|
||||||
if (req.result == UnityWebRequest.Result.Success)
|
if (req.result == UnityWebRequest.Result.Success)
|
||||||
{
|
{
|
||||||
Debug.Log("[FlexionPaymentVerifier] Response: " + req.downloadHandler.text);
|
var respText = req.downloadHandler.text;
|
||||||
// TODO: 按实际服务端响应格式解析
|
Debug.Log("[FlexionPaymentVerifier] Response: " + respText);
|
||||||
tcs.TrySetResult(new VerifyResult { success = true, msg = "ok" });
|
var orderResult = JsonConvert.DeserializeObject<FlexionOrderResult>(respText);
|
||||||
|
if (orderResult == null)
|
||||||
|
{
|
||||||
|
tcs.TrySetResult(new PaymentVerifyResult { success = false, msg = "parse_error" });
|
||||||
|
}
|
||||||
|
else if (orderResult.code == 0)
|
||||||
|
{
|
||||||
|
tcs.TrySetResult(new PaymentVerifyResult
|
||||||
|
{ success = true, msg = orderResult.info, orderId = orderResult.orderId });
|
||||||
|
}
|
||||||
|
else if (orderResult.code == 1)
|
||||||
|
{
|
||||||
|
tcs.TrySetResult(new PaymentVerifyResult
|
||||||
|
{ success = true, msg = orderResult.info, orderId = orderResult.orderId });
|
||||||
|
}
|
||||||
|
else if (orderResult.code == 2)
|
||||||
|
{
|
||||||
|
tcs.TrySetResult(new PaymentVerifyResult
|
||||||
|
{ success = true, msg = orderResult.info, orderId = orderResult.orderId });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// -1: 公钥/签名/玩家验证失败, -2: 写入失败, -3: 数据解析错误
|
||||||
|
tcs.TrySetResult(new PaymentVerifyResult
|
||||||
|
{ success = false, msg = orderResult.info ?? $"code={orderResult.code}" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[FlexionPaymentVerifier] Failed: " + req.error);
|
Debug.LogWarning("[FlexionPaymentVerifier] Failed: " + req.error);
|
||||||
tcs.TrySetResult(new VerifyResult { success = false, msg = req.error });
|
tcs.TrySetResult(new PaymentVerifyResult { success = false, msg = req.error });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +194,7 @@ namespace tysdk
|
|||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError("[FlexionPaymentVerifier] Exception: " + e.Message);
|
Debug.LogError("[FlexionPaymentVerifier] Exception: " + e.Message);
|
||||||
return new VerifyResult { success = false, msg = e.Message };
|
return new PaymentVerifyResult { success = false, msg = e.Message };
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -142,30 +202,57 @@ namespace tysdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FlexionPurchaseConsumer : IPurchaseConsumer
|
||||||
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
public void Consume(string token) { }
|
public async Task<PurchaseConsumeResult> ConsumeAsync(string token)
|
||||||
#elif UNITY_ANDROID
|
|
||||||
public void Consume(string token)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(token)) return;
|
await Task.Yield();
|
||||||
|
return new PurchaseConsumeResult { success = true, msg = "editor_placeholder" };
|
||||||
|
}
|
||||||
|
#elif UNITY_ANDROID
|
||||||
|
public async Task<PurchaseConsumeResult> ConsumeAsync(string token)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(token))
|
||||||
|
return new PurchaseConsumeResult { success = false, msg = "empty_token" };
|
||||||
|
|
||||||
UnityBridgeFunc.ConsumePurchase(token);
|
UnityBridgeFunc.ConsumePurchase(token);
|
||||||
|
await Task.Yield();
|
||||||
|
return new PurchaseConsumeResult { success = true, msg = "consume_requested" };
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
public async Task<PurchaseConsumeResult> ConsumeAsync(string token)
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
return new PurchaseConsumeResult { success = false, msg = "unsupported_platform" };
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DummyPaymentVerifier : IPaymentVerifier
|
public class FakePaymentVerifier : IPaymentVerifier
|
||||||
{
|
{
|
||||||
public async Task<VerifyResult> Verify(PaymentInfo info)
|
public async Task<PaymentVerifyResult> VerifyAsync(PaymentInfo info)
|
||||||
{
|
{
|
||||||
Debug.Log("[DummyPaymentVerifier] Verifying purchase: " + info.orderId);
|
Debug.Log("[FakePaymentVerifier] Verifying purchase: " + info.orderId);
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
return new VerifyResult { success = true, msg = "dummy_ok" };
|
return new PaymentVerifyResult { success = true, msg = "fake_ok" };
|
||||||
}
|
|
||||||
|
|
||||||
public void Consume(string token)
|
|
||||||
{
|
|
||||||
Debug.Log("[DummyPaymentVerifier] Consume: " + token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FakePurchaseConsumer : IPurchaseConsumer
|
||||||
|
{
|
||||||
|
public async Task<PurchaseConsumeResult> ConsumeAsync(string token)
|
||||||
|
{
|
||||||
|
Debug.Log("[FakePurchaseConsumer] Consume: " + token);
|
||||||
|
await Task.Yield();
|
||||||
|
return new PurchaseConsumeResult { success = true, msg = "fake_ok" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BypassCertificateHandler : CertificateHandler
|
||||||
|
{
|
||||||
|
protected override bool ValidateCertificate(byte[] certificateData) => true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ namespace tysdk
|
|||||||
|
|
||||||
private int LoginTimeoutSeconds => ChannelConfig.LoginTimeoutSeconds;
|
private int LoginTimeoutSeconds => ChannelConfig.LoginTimeoutSeconds;
|
||||||
|
|
||||||
|
public static bool IsSdkInited { get; private set; }
|
||||||
|
public static event System.Action<bool, string> OnInitComplete;
|
||||||
|
|
||||||
// ================== Init ==================
|
// ================== Init ==================
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
@@ -138,6 +141,16 @@ namespace tysdk
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InitResult(string json)
|
||||||
|
{
|
||||||
|
var data = Newtonsoft.Json.Linq.JObject.Parse(json);
|
||||||
|
var code = (int)data["code"];
|
||||||
|
var msg = (string)data["msg"];
|
||||||
|
IsSdkInited = code == 0;
|
||||||
|
UnityEngine.Debug.Log($"[TYSdkFacade] InitResult: code={code} msg={msg}");
|
||||||
|
OnInitComplete?.Invoke(IsSdkInited, msg);
|
||||||
|
}
|
||||||
|
|
||||||
// Called from Java SDKManager.InitSDK to sync channel
|
// Called from Java SDKManager.InitSDK to sync channel
|
||||||
public void SetChannelFromNative(string ch)
|
public void SetChannelFromNative(string ch)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ namespace tysdk
|
|||||||
result.purchaseJson = jresult["purchaseJson"]?.ToString();
|
result.purchaseJson = jresult["purchaseJson"]?.ToString();
|
||||||
result.signature = jresult["signature"]?.ToString();
|
result.signature = jresult["signature"]?.ToString();
|
||||||
result.purchaseToken = jresult["purchaseToken"]?.ToString();
|
result.purchaseToken = jresult["purchaseToken"]?.ToString();
|
||||||
|
result.userId = _accountInfo?.strUserId;
|
||||||
if (result.code == "-1")
|
if (result.code == "-1")
|
||||||
{
|
{
|
||||||
if (!_payFirstNegativeHandled)
|
if (!_payFirstNegativeHandled)
|
||||||
@@ -127,10 +128,10 @@ namespace tysdk
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var verifier = PaymentVerifierFactory.GetVerifier();
|
var processor = PaymentProcessorFactory.GetProcessor();
|
||||||
if (verifier != null && !string.IsNullOrEmpty(result.purchaseJson))
|
if (processor?.verifier != null && !string.IsNullOrEmpty(result.purchaseJson))
|
||||||
{
|
{
|
||||||
_VerifyPurchase(result, verifier);
|
_VerifyPurchase(result, processor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -138,18 +139,24 @@ namespace tysdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void _VerifyPurchase(PaymentInfo result, IPaymentVerifier verifier)
|
private async void _VerifyPurchase(PaymentInfo result, PaymentProcessor processor)
|
||||||
{
|
{
|
||||||
TYSDKCallbackManager.Instance.ResetCallbackTimeout<PaymentInfo>(TimeSpan.FromSeconds(60));
|
TYSDKCallbackManager.Instance.ResetCallbackTimeout<PaymentInfo>(TimeSpan.FromSeconds(60));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var verifyResult = await verifier.Verify(result);
|
var verifyResult = await processor.verifier.VerifyAsync(result);
|
||||||
if (verifyResult.success)
|
if (verifyResult.success)
|
||||||
{
|
{
|
||||||
result.verified = true;
|
result.verified = true;
|
||||||
if (!string.IsNullOrEmpty(result.purchaseToken))
|
if (!string.IsNullOrEmpty(verifyResult.orderId))
|
||||||
|
result.serverOrderId = verifyResult.orderId;
|
||||||
|
if (processor.consumer != null && !string.IsNullOrEmpty(result.purchaseToken))
|
||||||
{
|
{
|
||||||
verifier.Consume(result.purchaseToken);
|
var consumeResult = await processor.consumer.ConsumeAsync(result.purchaseToken);
|
||||||
|
if (!consumeResult.success)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[TYSdkFacade] Purchase consume failed: " + consumeResult.msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ namespace tysdk
|
|||||||
|
|
||||||
public bool verified;
|
public bool verified;
|
||||||
|
|
||||||
|
// Server-side order ID returned from verification
|
||||||
|
public string serverOrderId;
|
||||||
|
|
||||||
|
// Player ID for server-side verification
|
||||||
|
public string userId;
|
||||||
|
|
||||||
public bool Check(string orderId, string productId)
|
public bool Check(string orderId, string productId)
|
||||||
{
|
{
|
||||||
confirmed = orderId == this.orderId && productId == this.productId;
|
confirmed = orderId == this.orderId && productId == this.productId;
|
||||||
|
|||||||
Reference in New Issue
Block a user