- ISDKHelper.pay() 增加 productPrice 参数,与 UnityKnowNew 签名对齐 - FlexionSDKHelper: prodPrice/prodCount 从参数直接写入 developerPayload - playerId → userId 统一命名 (SDKTest/Java payload) - pfId → pfid 统一小写 (服务端 JSON key) - PaymentInfo 序列化替代 StringBuilder 手拼 JSON - FlexionPaymentVerifier.Consume 走 UnityBridgeFunc.ConsumePurchase 桥接层 - UnityBridgeFunc 新增 ConsumePurchase 通用方法,移除渠道特定方法 - SDKManager.ConsumeFlexionPurchase → ConsumePurchase 通用化 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
212 lines
7.5 KiB
C#
212 lines
7.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json.Linq;
|
|
using UnityEngine;
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace tysdk
|
|
{
|
|
public partial class TYSdkFacade
|
|
{
|
|
/*================================================
|
|
|
|
____ _
|
|
| _ \ __ _ _ _ _ __ ___ ___ _ __ | |_
|
|
| |_) / _` | | | | '_ ` _ \ / _ \ '_ \| __|
|
|
| __/ (_| | |_| | | | | | | __/ | | | |_
|
|
|_| \__,_|\__, |_| |_| |_|\___|_| |_|\__|
|
|
|___/
|
|
=================================================*/
|
|
|
|
private bool _payFirstNegativeHandled;
|
|
|
|
public async Task<PaymentInfo> Pay(SKUDetail prod, int count, float usdprice, JObject purchaseInfo)
|
|
{
|
|
if (!IsLoggedIn) return new PaymentInfo() { code = "-1", msg = "未登录" };
|
|
|
|
var orderId = System.Guid.NewGuid().ToString();
|
|
|
|
if (purchaseInfo == null)
|
|
purchaseInfo = new JObject();
|
|
|
|
string extraInfo = purchaseInfo.ToString(Newtonsoft.Json.Formatting.None);
|
|
extraInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(extraInfo));
|
|
Debug.Log("[TYSdk] extraInfo: " + extraInfo);
|
|
var prodId = prod.ProdID;
|
|
var prodPrice = usdprice.ToString();
|
|
var prodName = prod.title;
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
await Task.Yield();
|
|
var result = new PaymentInfo()
|
|
{
|
|
code = "0",
|
|
msg = "success",
|
|
count = count,
|
|
orderId = orderId,
|
|
productId = prodId,
|
|
price = prodPrice
|
|
};
|
|
|
|
|
|
return result;
|
|
#elif UNITY_ANDROID
|
|
|
|
var pType = ChannelConfig.PayType;
|
|
var task = TYSDKCallbackManager.Instance.RegisterCallback<PaymentInfo>(TimeSpan.FromSeconds(90));
|
|
try
|
|
{
|
|
UnityBridgeFunc.UnityKnowNew(prodId, prodPrice, prodName, count.ToString(), orderId, extraInfo, pType);
|
|
var result = await task;
|
|
result.count = count;
|
|
result.orderId = orderId;
|
|
result.productId = prodId;
|
|
result.price = prodPrice;
|
|
result.Check(orderId, prodId);
|
|
return result;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogWarning($"[TYSdkFacade::Pay] Faild {e.Message}");
|
|
return new PaymentInfo(){code = "-1"};
|
|
}
|
|
finally
|
|
{
|
|
_payFirstNegativeHandled = false;
|
|
}
|
|
|
|
|
|
#elif UNITY_IOS
|
|
var task = TYSDKCallbackManager.Instance.RegisterCallback<PaymentInfo>(TimeSpan.FromSeconds(30));
|
|
UnityBridgeFunc.UnityKnow(_accountInfo.strUserId, prodId, prodPrice, prodName, count.ToString(), orderId, extraInfo);
|
|
|
|
try{
|
|
var result = await task;
|
|
result.count = count;
|
|
result.orderId = orderId;
|
|
result.productId = prodId;
|
|
result.price = prodPrice;
|
|
return result;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Debug.LogWarning($"[TYSdkFacade::Pay] Faild {e.Message}");
|
|
return new PaymentInfo(){code = "-1"};
|
|
}
|
|
finally
|
|
{
|
|
_payFirstNegativeHandled = false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
public void PayResult(string json)
|
|
{
|
|
Debug.Log("[TYSdkFacade] pay callback:" + json);
|
|
var jresult = JObject.Parse(json);
|
|
var result = new PaymentInfo();
|
|
result.code = jresult["code"].ToString();
|
|
result.msg = jresult["errStr"].ToString();
|
|
result.purchaseJson = jresult["purchaseJson"]?.ToString();
|
|
result.signature = jresult["signature"]?.ToString();
|
|
result.purchaseToken = jresult["purchaseToken"]?.ToString();
|
|
if (result.code == "-1")
|
|
{
|
|
if (!_payFirstNegativeHandled)
|
|
{
|
|
_payFirstNegativeHandled = true;
|
|
TYSDKCallbackManager.Instance.ResetCallbackTimeout<PaymentInfo>(TimeSpan.FromSeconds(5));
|
|
Debug.Log("[TYSdkFacade] pay failed (first time): reset timeout to 5s, waiting next pay callback");
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("[TYSdkFacade] pay failed: waiting next pay callback");
|
|
}
|
|
return;
|
|
}
|
|
var verifier = PaymentVerifierFactory.GetVerifier();
|
|
if (verifier != null && !string.IsNullOrEmpty(result.purchaseJson))
|
|
{
|
|
_VerifyPurchase(result, verifier);
|
|
}
|
|
else
|
|
{
|
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
|
}
|
|
}
|
|
|
|
private async void _VerifyPurchase(PaymentInfo result, IPaymentVerifier verifier)
|
|
{
|
|
TYSDKCallbackManager.Instance.ResetCallbackTimeout<PaymentInfo>(TimeSpan.FromSeconds(60));
|
|
try
|
|
{
|
|
var verifyResult = await verifier.Verify(result);
|
|
if (verifyResult.success)
|
|
{
|
|
result.verified = true;
|
|
if (!string.IsNullOrEmpty(result.purchaseToken))
|
|
{
|
|
verifier.Consume(result.purchaseToken);
|
|
}
|
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[TYSdkFacade] Payment verification failed: " + verifyResult.msg);
|
|
result.code = "-1";
|
|
result.msg = "verification_failed: " + verifyResult.msg;
|
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError("[TYSdkFacade] Verification exception: " + e.Message);
|
|
result.code = "-1";
|
|
result.msg = "verification_error: " + e.Message;
|
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
|
}
|
|
}
|
|
|
|
public async Task<ProductListInfo> GetSKUList()
|
|
{
|
|
if (!IsLoggedIn) return new ProductListInfo() { code = -1, msg = "未登录" };
|
|
|
|
#if UNITY_EDITOR
|
|
await Task.Yield();
|
|
|
|
var result = new ProductListInfo();
|
|
return result;
|
|
#elif UNITY_ANDROID || UNITY_IOS
|
|
var task = TYSDKCallbackManager.Instance.RegisterCallback<ProductListInfo>();
|
|
UnityBridgeFunc.GetSKUList();
|
|
var result = await task;
|
|
return result;
|
|
#endif
|
|
}
|
|
|
|
public void SKUListResult(string json)
|
|
{
|
|
Debug.Log("[TYSdkFacade] GetSKUList callback");
|
|
var jresult = JObject.Parse(json);
|
|
int code = int.Parse(jresult["code"].ToString());
|
|
var result = new ProductListInfo();
|
|
if (code == 0)
|
|
{
|
|
string productStr = jresult["respObj"].ToString();
|
|
result.code = code;
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
var jsonObjList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<SKUDetail>>(productStr);
|
|
result.products = jsonObjList;
|
|
#elif UNITY_IOS && !UNITY_EDITOR
|
|
result.ReadSKUFromJson(productStr);
|
|
#endif
|
|
}
|
|
|
|
TYSDKCallbackManager.Instance.TryTriggerCallback(result);
|
|
}
|
|
}
|
|
}
|