refactor: 支付链路规范化 — 统一命名/层次/传参
- 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>
This commit is contained in:
@@ -88,8 +88,9 @@ public class FlexionSDKHelper implements SDKManager.ISDKHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pay(Activity activity, String productId, String productName,
|
public void pay(Activity activity, String productId, String productPrice,
|
||||||
String productCount, String prodorderId, String appInfo) {
|
String productName, String productCount, String prodorderId,
|
||||||
|
String appInfo) {
|
||||||
Log.i(TAG, "[PAY-FLOW] pay called: productId=" + productId + " billingReady=" + billingConnected);
|
Log.i(TAG, "[PAY-FLOW] pay called: productId=" + productId + " billingReady=" + billingConnected);
|
||||||
if (billingService == null || !billingConnected) {
|
if (billingService == null || !billingConnected) {
|
||||||
Log.e(TAG, "[PAY-FLOW] billing not ready");
|
Log.e(TAG, "[PAY-FLOW] billing not ready");
|
||||||
@@ -101,11 +102,14 @@ public class FlexionSDKHelper implements SDKManager.ISDKHelper {
|
|||||||
byte[] decoded = Base64.getDecoder().decode(appInfo);
|
byte[] decoded = Base64.getDecoder().decode(appInfo);
|
||||||
JSONObject json = new JSONObject(new String(decoded, "UTF-8"));
|
JSONObject json = new JSONObject(new String(decoded, "UTF-8"));
|
||||||
JSONObject payload = new JSONObject();
|
JSONObject payload = new JSONObject();
|
||||||
payload.put("playerId", json.optString("playerId", ""));
|
payload.put("userId", json.optString("userId", ""));
|
||||||
|
payload.put("pfid", json.optString("pfid", ""));
|
||||||
payload.put("customData", json.optString("customData", ""));
|
payload.put("customData", json.optString("customData", ""));
|
||||||
|
payload.put("prodPrice", productPrice);
|
||||||
|
payload.put("prodCount", productCount);
|
||||||
developerPayload = payload.toString();
|
developerPayload = payload.toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to extract playerId/customData from appInfo: " + e.getMessage());
|
Log.w(TAG, "Failed to extract payload fields from appInfo: " + e.getMessage());
|
||||||
}
|
}
|
||||||
String finalPayload = developerPayload;
|
String finalPayload = developerPayload;
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ public class SDKTest : MonoBehaviour
|
|||||||
var purchaseInfo = new JObject();
|
var purchaseInfo = new JObject();
|
||||||
purchaseInfo["pfid"] = "TestPlayer";
|
purchaseInfo["pfid"] = "TestPlayer";
|
||||||
purchaseInfo["customData"] = "{\"test\":\"test\"}";
|
purchaseInfo["customData"] = "{\"test\":\"test\"}";
|
||||||
purchaseInfo["playerId"] = TYSdkFacade.TYAccountInfo.strUserId;
|
purchaseInfo["userId"] = TYSdkFacade.TYAccountInfo.strUserId;
|
||||||
|
|
||||||
PaymentInfo payResult = await TYSdkFacade.Instance.Pay(sku, 1, sku.ProdPrice, purchaseInfo);
|
PaymentInfo payResult = await TYSdkFacade.Instance.Pay(sku, 1, sku.ProdPrice, purchaseInfo);
|
||||||
_messageTxt.text = "\n" + $"Success : {payResult.isSuccess}";
|
_messageTxt.text = "\n" + $"Success : {payResult.isSuccess}";
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ public class SDKManager {
|
|||||||
// Channel helper
|
// Channel helper
|
||||||
public interface ISDKHelper {
|
public interface ISDKHelper {
|
||||||
void init(Activity activity);
|
void init(Activity activity);
|
||||||
void pay(Activity activity, String productId, String productName,
|
void pay(Activity activity, String productId, String productPrice,
|
||||||
String productCount, String prodorderId, String appInfo);
|
String productName, String productCount, String prodorderId,
|
||||||
|
String appInfo);
|
||||||
void queryProducts();
|
void queryProducts();
|
||||||
void consume(String token);
|
void consume(String token);
|
||||||
}
|
}
|
||||||
@@ -72,8 +73,8 @@ public class SDKManager {
|
|||||||
sdkHelper = helper;
|
sdkHelper = helper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ConsumeFlexionPurchase(String token) {
|
public static void ConsumePurchase(String token) {
|
||||||
Log.i(TAG, "ConsumeFlexionPurchase: token=" + token);
|
Log.i(TAG, "ConsumePurchase: token=" + token);
|
||||||
if (sdkHelper != null) {
|
if (sdkHelper != null) {
|
||||||
sdkHelper.consume(token);
|
sdkHelper.consume(token);
|
||||||
}
|
}
|
||||||
@@ -395,7 +396,7 @@ public class SDKManager {
|
|||||||
String productCount, String prodorderId, String appInfo,
|
String productCount, String prodorderId, String appInfo,
|
||||||
String ptype) {
|
String ptype) {
|
||||||
if (sdkHelper != null) {
|
if (sdkHelper != null) {
|
||||||
sdkHelper.pay(UnityPlayer.currentActivity, productId, productName, productCount, prodorderId, appInfo);
|
sdkHelper.pay(UnityPlayer.currentActivity, productId, productPrice, productName, productCount, prodorderId, appInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PayEventData.PayData payData = new PayEventData.PayData();
|
PayEventData.PayData payData = new PayEventData.PayData();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
@@ -90,20 +90,21 @@ namespace tysdk
|
|||||||
Debug.Log($"[FlexionPaymentVerifier] HTTP retry {attempt}/{MaxRetries}, waiting {delay.TotalSeconds}s");
|
Debug.Log($"[FlexionPaymentVerifier] HTTP retry {attempt}/{MaxRetries}, waiting {delay.TotalSeconds}s");
|
||||||
await Task.Delay(delay);
|
await Task.Delay(delay);
|
||||||
}
|
}
|
||||||
lastResult = await SendVerifyRequest(BuildRequestBody(info));
|
lastResult = await SendVerifyRequest(info);
|
||||||
if (lastResult.success) return lastResult;
|
if (lastResult.success) return lastResult;
|
||||||
Debug.LogWarning($"[FlexionPaymentVerifier] HTTP attempt {attempt + 1} failed: {lastResult.msg}");
|
Debug.LogWarning($"[FlexionPaymentVerifier] HTTP attempt {attempt + 1} failed: {lastResult.msg}");
|
||||||
}
|
}
|
||||||
return lastResult;
|
return lastResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<VerifyResult> SendVerifyRequest(string body)
|
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] Sending verification request");
|
||||||
|
|
||||||
|
var body = JsonConvert.SerializeObject(info);
|
||||||
using var req = new UnityWebRequest(VERIFY_URL, "POST");
|
using var req = new UnityWebRequest(VERIFY_URL, "POST");
|
||||||
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
|
req.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
|
||||||
req.downloadHandler = new DownloadHandlerBuffer();
|
req.downloadHandler = new DownloadHandlerBuffer();
|
||||||
@@ -139,35 +140,15 @@ namespace tysdk
|
|||||||
cts.Dispose();
|
cts.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildRequestBody(PaymentInfo info)
|
|
||||||
{
|
|
||||||
var body = new StringBuilder();
|
|
||||||
body.Append('{');
|
|
||||||
body.Append("\"purchaseJson\":").Append(Escape(info.purchaseJson)).Append(',');
|
|
||||||
body.Append("\"signature\":").Append(Escape(info.signature)).Append(',');
|
|
||||||
body.Append("\"orderId\":").Append(Escape(info.orderId)).Append(',');
|
|
||||||
body.Append("\"productId\":").Append(Escape(info.productId)).Append(',');
|
|
||||||
body.Append("\"purchaseToken\":").Append(Escape(info.purchaseToken));
|
|
||||||
body.Append('}');
|
|
||||||
return body.ToString();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private static string Escape(string s)
|
|
||||||
{
|
|
||||||
if (s == null) return "null";
|
|
||||||
return '"' + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
public void Consume(string token) { }
|
public void Consume(string token) { }
|
||||||
#elif UNITY_ANDROID
|
#elif UNITY_ANDROID
|
||||||
public void Consume(string token)
|
public void Consume(string token)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(token)) return;
|
if (string.IsNullOrEmpty(token)) return;
|
||||||
using var sdkManager = new AndroidJavaClass("com.unity3d.player.SDKManager");
|
UnityBridgeFunc.ConsumePurchase(token);
|
||||||
sdkManager.CallStatic("ConsumeFlexionPurchase", token);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ namespace tysdk
|
|||||||
|
|
||||||
if (purchaseInfo == null)
|
if (purchaseInfo == null)
|
||||||
purchaseInfo = new JObject();
|
purchaseInfo = new JObject();
|
||||||
// purchaseInfo["playerId"] = _accountInfo.strUserId;
|
|
||||||
|
|
||||||
string extraInfo = purchaseInfo.ToString(Newtonsoft.Json.Formatting.None);
|
string extraInfo = purchaseInfo.ToString(Newtonsoft.Json.Formatting.None);
|
||||||
extraInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(extraInfo));
|
extraInfo = Convert.ToBase64String(Encoding.UTF8.GetBytes(extraInfo));
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ namespace tysdk
|
|||||||
|
|
||||||
public static void Review() { }
|
public static void Review() { }
|
||||||
|
|
||||||
|
public static void ConsumePurchase(string token) { }
|
||||||
|
|
||||||
public static void FBShareLink(string title, string content, string url) { }
|
public static void FBShareLink(string title, string content, string url) { }
|
||||||
public static void MessengerShareLink(string title, string content, string url) { }
|
public static void MessengerShareLink(string title, string content, string url) { }
|
||||||
|
|
||||||
@@ -168,6 +170,14 @@ namespace tysdk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ConsumePurchase(string token)
|
||||||
|
{
|
||||||
|
using (var sdkManager = new AndroidJavaClass(SDK_CLASS))
|
||||||
|
{
|
||||||
|
sdkManager.CallStatic("ConsumePurchase", token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void UnityKnow(String productId, String productName, String productCount, String prodorderId, String appInfo)
|
public static void UnityKnow(String productId, String productName, String productCount, String prodorderId, String appInfo)
|
||||||
{
|
{
|
||||||
using (var sdkManager = new AndroidJavaClass(SDK_CLASS))
|
using (var sdkManager = new AndroidJavaClass(SDK_CLASS))
|
||||||
|
|||||||
Reference in New Issue
Block a user