com.xd.sdk.payment 7.3.4 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/Editor/Android/XDPaymentAndroidGradleProcessor.cs +33 -0
  2. package/Editor/Android/XDPaymentAndroidGradleProcessor.cs.meta +11 -0
  3. package/{Plugins → Editor}/Android.meta +1 -1
  4. package/{Plugins/Android/libs.meta → Editor.meta} +1 -1
  5. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPaymentApi.h +10 -1
  6. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPaymentParams.h +6 -6
  7. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPaymentVersion.h +3 -3
  8. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPendingPurchase.h +2 -2
  9. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDPaymentSDK-Swift.h +6 -1
  10. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDPaymentSDK.h +0 -1
  11. package/Plugins/iOS/XDPaymentSDK.framework/Info.plist +0 -0
  12. package/Plugins/iOS/XDPaymentSDK.framework/Modules/XDPaymentSDK.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  13. package/Plugins/iOS/XDPaymentSDK.framework/Modules/XDPaymentSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  14. package/Plugins/iOS/XDPaymentSDK.framework/Modules/XDPaymentSDK.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
  15. package/Plugins/iOS/XDPaymentSDK.framework/XDPaymentSDK +0 -0
  16. package/Runtime/Internal/Standalone/AliyunTrack.Payment.cs +19 -0
  17. package/Runtime/Internal/Standalone/Bean/PreCheckResponse.cs +17 -0
  18. package/Runtime/Internal/Standalone/Bean/PreCheckResponse.cs.meta +11 -0
  19. package/Runtime/Internal/Standalone/PayListener.cs +6 -0
  20. package/Runtime/Internal/Standalone/PayModule.cs +133 -51
  21. package/Runtime/Internal/Standalone/PaymentAlert.cs +1 -1
  22. package/Runtime/Internal/Standalone/PaymentFeaturesImpl.cs +24 -11
  23. package/Runtime/Internal/Standalone/PaymentPreChecker.cs +81 -0
  24. package/Runtime/Internal/Standalone/PaymentPreChecker.cs.meta +11 -0
  25. package/package.json +3 -3
  26. package/Plugins/Android/libs/XDGBridgePayment_v7_7.3.3.aar +0 -0
  27. package/Plugins/Android/libs/XDGBridgePayment_v7_7.3.3.aar.meta +0 -32
  28. package/Plugins/Android/libs/XDGPaymentUPPay_7.3.3.aar +0 -0
  29. package/Plugins/Android/libs/XDGPaymentUPPay_7.3.3.aar.meta +0 -32
  30. package/Plugins/Android/libs/XDGPayment_7.3.3.aar +0 -0
  31. package/Plugins/Android/libs/XDGPayment_7.3.3.aar.meta +0 -32
  32. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPaymentService.h +0 -47
  33. package/Plugins/iOS/XDPaymentSDK.framework/Headers/XDGPaymentService.h.meta +0 -7
@@ -0,0 +1,33 @@
1
+ using System.Collections.Generic;
2
+ using XD.SDK.Foundation.Mobile.Editor;
3
+ using XD.SDK.Foundation.Mobile.Editor.Android;
4
+
5
+ namespace XD.SDK.Payment.Editor
6
+ {
7
+ public class XDPaymentAndroidGradleProcessor : XDAndroidProjectProcessor
8
+ {
9
+ protected override List<AndroidGradleProjectConfig.Dependency> GenerateDependencies()
10
+ {
11
+ var sdkVersion = VersionCatalog.XDAndroidSdkVersion;
12
+ var result = new List<AndroidGradleProjectConfig.Dependency>
13
+ {
14
+ new AndroidGradleProjectConfig.Dependency(group: "com.xd.sdk.android", module: "payment-bridge",
15
+ version: sdkVersion),
16
+ };
17
+
18
+ var regionType = configModel?.region_type;
19
+ if (string.Equals(regionType, "global", System.StringComparison.OrdinalIgnoreCase))
20
+ {
21
+ result.Add(new AndroidGradleProjectConfig.Dependency(group: "com.xd.sdk.android", module: "payment-global",
22
+ version: sdkVersion));
23
+ }
24
+ else if (string.Equals(regionType, "cn", System.StringComparison.OrdinalIgnoreCase))
25
+ {
26
+ result.Add(new AndroidGradleProjectConfig.Dependency(group: "com.xd.sdk.android", module: "payment-cn",
27
+ version: sdkVersion));
28
+ }
29
+
30
+ return result;
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: ba3b4dfe2bea8497cb7de20d30ad31e3
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -1,5 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: 9030895ebfad41a6b8e8205b1fa5cc20
2
+ guid: d6b5b5d6638f64d669db1eb8f347300a
3
3
  folderAsset: yes
4
4
  DefaultImporter:
5
5
  externalObjects: {}
@@ -1,5 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: 8f130c4e1ca34def8668df9b3bd045f4
2
+ guid: 16a008fee316a45a69b5b38a372e28de
3
3
  folderAsset: yes
4
4
  DefaultImporter:
5
5
  externalObjects: {}
@@ -1,5 +1,5 @@
1
1
  //
2
- // XDGPaymentApi.h
2
+ // XDGPaymentAPI.h
3
3
  // TDSSDK
4
4
  //
5
5
  // Created by JiangJiahao on 2020/10/26.
@@ -19,7 +19,16 @@ static NSString * const XDG_UPLOAD_RECEIPT = @"/callback/v1/client/pay/notify";
19
19
 
20
20
  static NSString * const XDG_PAYBACK_LIST = @"/order/v1/user/repayOrders"; // 查询补款订单信息
21
21
 
22
+ static NSString * const XDG_PURCHASE_CHECK = @"/trade/v1/purchase-verification/verify"; // 登录购买凭证校验
23
+
22
24
  @interface XDGPaymentAPI : NSObject
23
25
  + (void)checkThirdPay:(NSDictionary *)params completionHandler:(XDGInitCallback)handler;
26
+
27
+ /// 登录购买凭证校验
28
+ /// - Parameters:
29
+ /// - jws: AppTransaction 的 JWS
30
+ /// - handler: 回调
31
+ + (void)purchaseCheckWithJWS:(NSString *)jws
32
+ completionHandler:(XDGHttpCallback)handler;
24
33
  @end
25
34
  NS_ASSUME_NONNULL_END
@@ -12,25 +12,25 @@ NS_ASSUME_NONNULL_BEGIN
12
12
  @interface XDGPaymentParams : NSObject
13
13
 
14
14
  /// 游戏订单 ID,可选
15
- @property(nonatomic, strong, nullable) NSString *gameOrderId;
15
+ @property(nonatomic, copy, nullable) NSString *gameOrderId;
16
16
 
17
17
  /// 商品 ID,必填
18
- @property(nonatomic, strong) NSString *productId;
18
+ @property(nonatomic, copy) NSString *productId;
19
19
 
20
20
  /// 角色 ID
21
- @property(nonatomic, strong, nullable) NSString *roleId;
21
+ @property(nonatomic, copy, nullable) NSString *roleId;
22
22
 
23
23
  /// 服务器 ID
24
- @property(nonatomic, strong, nullable) NSString *serverId;
24
+ @property(nonatomic, copy, nullable) NSString *serverId;
25
25
 
26
26
  /// 透传参数
27
- @property(nonatomic, strong, nullable) NSString *extra;
27
+ @property(nonatomic, copy, nullable) NSString *extra;
28
28
 
29
29
  /// 商品数量,默认为1,可选 1-10,恢复订单时不可用
30
30
  @property(nonatomic, assign) NSInteger quantity;
31
31
 
32
32
  /// 需要恢复的订单 ID,只在恢复订单时使用,可选
33
- @property(nonatomic, strong, nullable) NSString *pendingPurchaseToken;
33
+ @property(nonatomic, copy, nullable) NSString *pendingPurchaseToken;
34
34
 
35
35
  + (XDGPaymentParams *_Nullable)createWithDictionary:(NSDictionary *)dict;
36
36
 
@@ -5,6 +5,6 @@
5
5
  // Created by Fattycat on 2023/4/14.
6
6
  //
7
7
 
8
- #define XDGPayment_VERSION @"7.3.1"
9
- #define XDSPayment_VERSION_CODE @"7030100"
10
- // HASH e51483ce
8
+ #define XDGPayment_VERSION @"7.6.0"
9
+ #define XDSPayment_VERSION_CODE @"7060000"
10
+ // HASH 2fd78d92
@@ -6,10 +6,10 @@ NS_ASSUME_NONNULL_BEGIN
6
6
  @interface XDGPendingPurchase : NSObject
7
7
 
8
8
  /// 交易 ID
9
- @property (nonatomic, strong) NSString *pendingPurchaseToken;
9
+ @property (nonatomic, copy) NSString *pendingPurchaseToken;
10
10
 
11
11
  /// 商品 ID
12
- @property (nonatomic, strong) NSString *productId;
12
+ @property (nonatomic, copy) NSString *productId;
13
13
 
14
14
  - (NSDictionary *)toDictionary;
15
15
 
@@ -304,8 +304,9 @@ typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
304
304
 
305
305
  #if defined(__OBJC__)
306
306
 
307
- @class NSArray;
307
+ @class NSString;
308
308
  @class NSError;
309
+ @class NSArray;
309
310
  @class XDGPaymentParams;
310
311
  @class XDGOrderInfo;
311
312
  /// Objective-C 桥接类,用于调用 XDGStore 并提供 OC 友好的接口
@@ -313,6 +314,10 @@ SWIFT_CLASS("_TtC12XDPaymentSDK14XDGStoreBridge") SWIFT_AVAILABILITY(ios,introdu
313
314
  @interface XDGStoreBridge : NSObject
314
315
  /// 开始监听交易更新
315
316
  + (void)observeTransactionUpdates;
317
+ /// 获取 AppTransaction JWS(iOS 16+)
318
+ /// \param completion 成功返回 JWS,失败或低版本返回 nil
319
+ ///
320
+ + (void)fetchAppTransactionJWSWithCompletion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion;
316
321
  /// 请求商品信息 - NSArray 版本(更 OC 友好)
317
322
  /// \param identifiers 商品标识符数组
318
323
  ///
@@ -19,7 +19,6 @@ FOUNDATION_EXPORT const unsigned char XDPaymentSDKVersionString[];
19
19
  #import <XDPaymentSDK/XDGProductInfo.h>
20
20
  #import <XDPaymentSDK/XDGPendingPurchase.h>
21
21
  #import <XDPaymentSDK/XDGOrderInfo.h>
22
- #import <XDPaymentSDK/XDGPaymentService.h>
23
22
  #import <XDPaymentSDK/XDGPaymentVersion.h>
24
23
  #import <XDPaymentSDK/XDGPaymentParams.h>
25
24
  #import <XDPaymentSDK/XDGLogger+Payment.h>
@@ -51,6 +51,25 @@ namespace XD.SDK.Payment.Internal.Standalone
51
51
  CommonAliyunTrack.LogEventAsync("sdkcharge_ask_pay_period", content);
52
52
  }
53
53
 
54
+ public static void CheckThird()
55
+ {
56
+ CommonAliyunTrack.LogEventAsync("sdkcharge_check_third",
57
+ GetPaymentModuleCommonProperties("sdkcharge_check_third"));
58
+ }
59
+
60
+ public static void CheckThirdFailed(string reason)
61
+ {
62
+ var content = GetPaymentModuleCommonProperties("sdkcharge_check_third_fail");
63
+ content["reason"] = reason;
64
+ CommonAliyunTrack.LogEventAsync("sdkcharge_check_third_fail", content);
65
+ }
66
+
67
+ public static void OpenWeb()
68
+ {
69
+ CommonAliyunTrack.LogEventAsync("sdkcharge_open_web",
70
+ GetPaymentModuleCommonProperties("sdkcharge_open_web"));
71
+ }
72
+
54
73
  public static void PaymentDone()
55
74
  {
56
75
  CommonAliyunTrack.LogEventAsync("sdkcharge_done", GetPaymentModuleCommonProperties("sdkcharge_done"));
@@ -0,0 +1,17 @@
1
+ #if UNITY_EDITOR || UNITY_STANDALONE
2
+ using Newtonsoft.Json;
3
+ using XD.SDK.Common.Internal;
4
+
5
+ namespace XD.SDK.Payment.Internal.Standalone
6
+ {
7
+ internal class PreCheckResult
8
+ {
9
+ [JsonProperty("url")] public string Url { get; set; }
10
+ }
11
+
12
+ internal class PreCheckResponse : BaseResponse
13
+ {
14
+ [JsonProperty("data")] public PreCheckResult Result { get; set; }
15
+ }
16
+ }
17
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 8dccb71db48a144e7a7e3d32ca6303e7
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -70,6 +70,12 @@ namespace XD.SDK.Payment.Internal.Standalone
70
70
  AliyunTrack.PaymentFailed("user_cancel");
71
71
  throw new TaskCanceledException();
72
72
  }
73
+ else
74
+ {
75
+ CloseLoading();
76
+ AliyunTrack.PaymentFailed("fail");
77
+ throw new Exception("pay failed");
78
+ }
73
79
  }
74
80
  }
75
81
 
@@ -27,6 +27,11 @@ namespace XD.SDK.Payment.Internal.Standalone
27
27
  // 上报订单
28
28
  private readonly static string XDG_REPORT_ORDER = "callback/v1/client/pay/notify";
29
29
 
30
+ // 支付渠道预检
31
+ private readonly static string XDG_PRE_CHECK = "payment/config/v1/channel/preCheck";
32
+
33
+ private readonly static int PC_CHANNEL_TYPE = 25;
34
+
30
35
  // 查询商品
31
36
  private readonly static string XDG_QUERY_PRODUCTS = "payment/product/v1/query/game/skus";
32
37
  // 查询 silent 商品价格
@@ -54,52 +59,8 @@ namespace XD.SDK.Payment.Internal.Standalone
54
59
  double payAmount = 0,
55
60
  string extras = null)
56
61
  {
57
- Dictionary<string, object> queryParmas = new Dictionary<string, object>
58
- {
59
- { "appId", ConfigModule.AppId },
60
- { "serverId", serverId },
61
- { "roleId", roleId },
62
- { "productSkuCode", productId },
63
- { "lang", XDLocalization.GetLanguageKey() },
64
- { "platform", XDUtility.GetPlatform() },
65
- { "sign", Sign(serverId, roleId, productId, ConfigModule.ClientId) },
66
- { "eventSessionId", AliyunTrack.PaymentEventSessionId },
67
- { "account", XDGAccount.GetCurrentUser()?.UserId },
68
- { "loginType", XDGAccount.GetCurrentUser()?.LoginType },
69
- { "userLoginType", XDGAccount.GetCurrentUser()?.LoginType },
70
- { "deviceId", SystemInfo.deviceUniqueIdentifier },
71
- { "xdClientId", ConfigModule.ClientId },
72
- { "sessionUUID", CommonAliyunTrack.CurrentSessionUUId },
73
- { "sdkVer", XDGConstants.SDK_VERSION },
74
- { "os", CommonAliyunTrack.GetPlatform() },
75
- { "os_version", SystemInfo.operatingSystem }
76
- };
77
- if (!string.IsNullOrEmpty(ConfigModule.TargetCountryOrRegion))
78
- {
79
- queryParmas.Add("region", ConfigModule.TargetCountryOrRegion);
80
- }
81
-
82
- if (!string.IsNullOrEmpty(orderId))
83
- {
84
- queryParmas.Add("orderId", orderId);
85
- }
86
-
87
- if (!string.IsNullOrEmpty(productName))
88
- {
89
- queryParmas.Add("productName", productName);
90
- }
91
-
92
- if (Math.Abs(payAmount) > float.Epsilon)
93
- {
94
- queryParmas.Add("payAmount", payAmount);
95
- }
96
-
97
- if (!string.IsNullOrEmpty(extras))
98
- {
99
- queryParmas.Add("extras", extras);
100
- }
101
-
102
- return $"{ConfigModule.WebPayUrlForPC}?{XDUrlUtils.ToQueryString(queryParmas)}";
62
+ var queryParams = BuildPayUrlQueryParams(serverId, roleId, productId, orderId, productName, payAmount, extras);
63
+ return BuildUrlWithQuery(ConfigModule.WebPayUrlForPC, queryParams);
103
64
  }
104
65
 
105
66
  public static async Task<List<PayInfo>> CheckPay(CancellationToken cancellationToken = default)
@@ -118,16 +79,17 @@ namespace XD.SDK.Payment.Internal.Standalone
118
79
 
119
80
  public static async Task PayWithSteam(string productId, string serverId, string roldId, string orderId, string ext)
120
81
  {
121
- // 开始支付
122
- AliyunTrack.PaymentStart(productId, AliyunTrack.PAY_PLATFORM_STEAM, AliyunTrack.PAY_TYPE_STEAM, AliyunTrack.PAY_CHANNEL_STEAM);
123
82
  string xdOrderId = null;
124
83
  try
125
84
  {
126
85
  CreateOrderResult createOrderResult = await CreateSteamOrder(productId, serverId, roldId, orderId, ext);
86
+ xdOrderId = createOrderResult.TradeNo.ToString();
87
+ AliyunTrack.PaymentCallPage();
127
88
 
128
89
  string microTxn = await SteamUtils.Instance.GetMicroTxn(createOrderResult.TradeNo);
129
90
  AliyunTrack.ReceiveSteamOrder(createOrderResult.TradeNo.ToString());
130
91
  await ReportSteamOrder(productId, createOrderResult.TradeNo, microTxn);
92
+ AliyunTrack.PaymentDone();
131
93
  }
132
94
  catch (XDGError e)
133
95
  {
@@ -157,7 +119,7 @@ namespace XD.SDK.Payment.Internal.Standalone
157
119
  { "steamId", steamId },
158
120
  { "steamLanguage", steamLanguage },
159
121
  };
160
- if (string.IsNullOrEmpty(ext))
122
+ if (!string.IsNullOrEmpty(ext))
161
123
  {
162
124
  data["remark"] = ext;
163
125
  }
@@ -173,7 +135,6 @@ namespace XD.SDK.Payment.Internal.Standalone
173
135
  AliyunTrack.CreateOrderFailure(e.Code);
174
136
  if (e.Code == 40023 || e.Code == 42902)
175
137
  {
176
- // 防沉迷错误
177
138
  TaskCompletionSource<CreateOrderResult> tcs = new TaskCompletionSource<CreateOrderResult>();
178
139
  LocalizableString localizable = XDLocalization.GetCurrentLocalizableString();
179
140
  Dictionary<string, object> config = new Dictionary<string, object>
@@ -222,6 +183,127 @@ namespace XD.SDK.Payment.Internal.Standalone
222
183
  }
223
184
  }
224
185
 
186
+ public static async Task<string> PreCheckThirdPay(XDGPaymentParams paymentParams, string redirectUri)
187
+ {
188
+ var urlParams = BuildPayUrlQueryParams(paymentParams.ServerId, paymentParams.RoleId, paymentParams.ProductId,
189
+ paymentParams.GameOrderId, extras: paymentParams.Extra);
190
+ urlParams["env"] = "pt_sandbox_pay";
191
+
192
+ if (!string.IsNullOrEmpty(redirectUri))
193
+ {
194
+ urlParams["redirect_uri"] = redirectUri;
195
+ }
196
+
197
+ var extra = new Dictionary<string, object>
198
+ {
199
+ { "productId", paymentParams.ProductId }
200
+ };
201
+
202
+ var data = new Dictionary<string, object>
203
+ {
204
+ { "productSkuCode", paymentParams.ProductId },
205
+ { "roleId", paymentParams.RoleId },
206
+ { "serverId", paymentParams.ServerId },
207
+ { "channelType", PC_CHANNEL_TYPE },
208
+ { "extra", extra },
209
+ { "urlParams", urlParams }
210
+ };
211
+
212
+ if (!string.IsNullOrEmpty(ConfigModule.TargetCountryOrRegion))
213
+ {
214
+ data["countryCode"] = ConfigModule.TargetCountryOrRegion;
215
+ }
216
+
217
+ AliyunTrack.CheckThird();
218
+ try
219
+ {
220
+ var response = await XDHttpClient.Client.PostAsync<PreCheckResponse>(XDG_PRE_CHECK, data: data);
221
+ var url = response.Result?.Url;
222
+ if (!string.IsNullOrEmpty(url))
223
+ {
224
+ XDGLogger.Debug($"PreCheck 返回第三方支付 URL: {url}", XDGLoggerTag.Pay);
225
+ return url;
226
+ }
227
+ AliyunTrack.CheckThirdFailed("url is null or empty");
228
+ }
229
+ catch (XDGError e)
230
+ {
231
+ XDGLogger.Warn($"PreCheck 请求失败,走正常支付流程: {e.ErrorMsg}", XDGLoggerTag.Pay);
232
+ AliyunTrack.CheckThirdFailed(e.ErrorMsg);
233
+ }
234
+ return null;
235
+ }
236
+
237
+ private static Dictionary<string, object> BuildPayUrlQueryParams(string serverId, string roleId, string productId,
238
+ string orderId = null,
239
+ string productName = null,
240
+ double payAmount = 0,
241
+ string extras = null)
242
+ {
243
+ var user = XDGAccount.GetCurrentUser();
244
+ var queryParams = new Dictionary<string, object>
245
+ {
246
+ { "appId", ConfigModule.AppId },
247
+ { "serverId", serverId },
248
+ { "roleId", roleId },
249
+ { "productSkuCode", productId },
250
+ { "lang", XDLocalization.GetLanguageKey() },
251
+ { "platform", XDUtility.GetPlatform() },
252
+ { "sign", Sign(serverId, roleId, productId, ConfigModule.ClientId) },
253
+ { "eventSessionId", AliyunTrack.PaymentEventSessionId },
254
+ { "deviceId", SystemInfo.deviceUniqueIdentifier },
255
+ { "xdClientId", ConfigModule.ClientId },
256
+ { "sessionUUID", CommonAliyunTrack.CurrentSessionUUId },
257
+ { "sdkVer", XDGConstants.SDK_VERSION },
258
+ { "os", CommonAliyunTrack.GetPlatform() },
259
+ { "os_version", SystemInfo.operatingSystem }
260
+ };
261
+
262
+ if (!string.IsNullOrEmpty(user?.UserId))
263
+ {
264
+ queryParams["account"] = user.UserId;
265
+ }
266
+
267
+ if (user != null)
268
+ {
269
+ queryParams["loginType"] = user.LoginType;
270
+ queryParams["userLoginType"] = user.LoginType;
271
+ }
272
+
273
+ if (!string.IsNullOrEmpty(ConfigModule.TargetCountryOrRegion))
274
+ {
275
+ queryParams["region"] = ConfigModule.TargetCountryOrRegion;
276
+ }
277
+
278
+ if (!string.IsNullOrEmpty(orderId))
279
+ {
280
+ queryParams["orderId"] = orderId;
281
+ }
282
+
283
+ if (!string.IsNullOrEmpty(productName))
284
+ {
285
+ queryParams["productName"] = productName;
286
+ }
287
+
288
+ if (Math.Abs(payAmount) > float.Epsilon)
289
+ {
290
+ queryParams["payAmount"] = payAmount;
291
+ }
292
+
293
+ if (!string.IsNullOrEmpty(extras))
294
+ {
295
+ queryParams["extras"] = extras;
296
+ }
297
+
298
+ return queryParams;
299
+ }
300
+
301
+ private static string BuildUrlWithQuery(string url, Dictionary<string, object> queryParams)
302
+ {
303
+ var separator = url.Contains("?") ? "&" : "?";
304
+ return $"{url}{separator}{XDUrlUtils.ToQueryString(queryParams)}";
305
+ }
306
+
225
307
  public static async Task<List<SkuDetailBean>> QueryProducts(string[] productIds)
226
308
  {
227
309
  if (productIds == null || productIds.Length == 0)
@@ -259,4 +341,4 @@ namespace XD.SDK.Payment.Internal.Standalone
259
341
  }
260
342
  }
261
343
  }
262
- #endif
344
+ #endif
@@ -1,4 +1,4 @@
1
- #if (UNITY_EDITOR || UNITY_STANDALONE) && !XDSDK_DISABLE_VUPLEX
1
+ #if (UNITY_STANDALONE || (UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS)) && !XDSDK_DISABLE_VUPLEX
2
2
  using System;
3
3
  using UnityEngine;
4
4
  using UnityEngine.UI;
@@ -82,15 +82,31 @@ namespace XD.SDK.Payment.Internal.Standalone
82
82
 
83
83
  try
84
84
  {
85
+ // 对齐 iOS:PaymentStart 在最顶层只调一次,生成 eventSessionId
86
+ // 后续所有埋点(check_third、open_web、create_order 等)共用这个 sessionId
85
87
  if (SteamUtils.IsSDKSupported)
86
88
  {
87
- await PayModule.PayWithSteam(paymentParams.ProductId, paymentParams.ServerId, paymentParams.RoleId,
88
- paymentParams.GameOrderId,
89
- paymentParams.Extra);
89
+ AliyunTrack.PaymentStart(paymentParams.ProductId, paymentParams.RoleId,
90
+ AliyunTrack.PAY_PLATFORM_STEAM, AliyunTrack.PAY_TYPE_STEAM, AliyunTrack.PAY_CHANNEL_STEAM);
90
91
  }
91
92
  else
92
93
  {
93
- await PayWithWeb(paymentParams);
94
+ AliyunTrack.PaymentStart(paymentParams.ProductId, paymentParams.RoleId);
95
+ }
96
+
97
+ var checkResult = await PaymentPreChecker.CheckAndHandle(paymentParams);
98
+ if (checkResult != PaymentPreCheckResult.HandledByThird)
99
+ {
100
+ if (SteamUtils.IsSDKSupported)
101
+ {
102
+ await PayModule.PayWithSteam(paymentParams.ProductId, paymentParams.ServerId, paymentParams.RoleId,
103
+ paymentParams.GameOrderId,
104
+ paymentParams.Extra);
105
+ }
106
+ else
107
+ {
108
+ await PayWithWeb(paymentParams);
109
+ }
94
110
  }
95
111
 
96
112
  callback.Invoke(
@@ -180,24 +196,23 @@ namespace XD.SDK.Payment.Internal.Standalone
180
196
  var user = XDGAccount.GetCurrentUser();
181
197
  if (user == null)
182
198
  {
199
+ AliyunTrack.PaymentFailed("not_logged_in");
183
200
  throw XDGErrorExtensions.NotLoginError();
184
201
  }
185
202
 
186
- AliyunTrack.PaymentStart(paymentParams.ProductId, paymentParams.RoleId);
187
203
  var url = PayModule.GetPayUrl(paymentParams.ServerId, paymentParams.RoleId, paymentParams.ProductId, paymentParams.GameOrderId, "", 0,
188
204
  paymentParams.Extra);
189
- // TODO 不需要二次 Encode
190
- // url = Uri.EscapeUriString(url);
191
205
  XDGLogger.Debug("支付 pay URL: " + url, XDGLoggerTag.Pay);
192
-
206
+
193
207
  if (ConfigModule.IsGlobal)
194
208
  {
195
209
  var payListener = new PayListener();
196
210
  await payListener.Start(url);
211
+ return;
197
212
  }
198
213
  else
199
214
  {
200
- #if (UNITY_EDITOR || UNITY_STANDALONE) && !XDSDK_DISABLE_VUPLEX
215
+ #if (UNITY_STANDALONE || (UNITY_EDITOR && !UNITY_ANDROID && !UNITY_IOS)) && !XDSDK_DISABLE_VUPLEX
201
216
  var tcs = new TaskCompletionSource<object>();
202
217
 
203
218
  var data = new Dictionary<string, object>
@@ -239,8 +254,6 @@ namespace XD.SDK.Payment.Internal.Standalone
239
254
  throw new XDGError(ResponseCode.Common.Failed, "This function need vuplex enabled");
240
255
  #endif
241
256
  }
242
-
243
- throw new XDGError(ResponseCode.Common.Failed, XDLocalization.GetCurrentLocalizableString().PayFail);
244
257
  }
245
258
  }
246
259
  }
@@ -0,0 +1,81 @@
1
+ #if UNITY_EDITOR || UNITY_STANDALONE
2
+
3
+ using System;
4
+ using System.Collections.Generic;
5
+ using System.Threading.Tasks;
6
+ using XD.SDK.Common;
7
+ using XD.SDK.Common.Internal;
8
+ using XD.SDK.Common.Internal.Standalone;
9
+
10
+ namespace XD.SDK.Payment.Internal.Standalone
11
+ {
12
+ internal enum PaymentPreCheckResult
13
+ {
14
+ ContinueWithNormal,
15
+ HandledByThird
16
+ }
17
+
18
+ internal static class PaymentPreChecker
19
+ {
20
+ internal static async Task<PaymentPreCheckResult> CheckAndHandle(XDGPaymentParams paymentParams)
21
+ {
22
+ string thirdPayUrl = await PayModule.PreCheckThirdPay(paymentParams, null);
23
+ if (string.IsNullOrEmpty(thirdPayUrl))
24
+ {
25
+ return PaymentPreCheckResult.ContinueWithNormal;
26
+ }
27
+
28
+ XDGLogger.Debug($"PreCheck WebView: {thirdPayUrl}", XDGLoggerTag.Pay);
29
+ AliyunTrack.OpenWeb();
30
+
31
+ var tcs = new TaskCompletionSource<PaymentPreCheckResult>();
32
+
33
+ XDGCommon.OpenWebPage(thirdPayUrl, (actionEnum, data) =>
34
+ {
35
+ if (actionEnum != WebActionEnum.CLOSE)
36
+ {
37
+ return;
38
+ }
39
+
40
+ try
41
+ {
42
+ tcs.TrySetResult(ParseCallbackResult(data));
43
+ }
44
+ catch (Exception e)
45
+ {
46
+ tcs.TrySetException(e);
47
+ }
48
+ });
49
+
50
+ return await tcs.Task;
51
+ }
52
+
53
+ private static PaymentPreCheckResult ParseCallbackResult(Dictionary<string, object> data)
54
+ {
55
+ bool continuePay = data != null && XDDictionary.GetValue(data, "continuePay", false);
56
+ string state = data != null ? XDDictionary.GetValue(data, "state", "") : "";
57
+ return ParseCallbackResult(continuePay, state);
58
+ }
59
+
60
+ private static PaymentPreCheckResult ParseCallbackResult(bool continuePay, string state)
61
+ {
62
+ if (continuePay)
63
+ {
64
+ XDGLogger.Debug("PreCheck: continuePay=true,回退正常支付流程", XDGLoggerTag.Pay);
65
+ return PaymentPreCheckResult.ContinueWithNormal;
66
+ }
67
+
68
+ if ("success".Equals(state, StringComparison.OrdinalIgnoreCase))
69
+ {
70
+ XDGLogger.Debug("PreCheck: state=success,第三方支付成功", XDGLoggerTag.Pay);
71
+ AliyunTrack.PaymentDone();
72
+ return PaymentPreCheckResult.HandledByThird;
73
+ }
74
+
75
+ XDGLogger.Debug("PreCheck: 回调无有效状态,视为取消", XDGLoggerTag.Pay);
76
+ AliyunTrack.PaymentFailed("user_cancel");
77
+ throw XDGErrorExtensions.CancelledError("Payment Cancelled");
78
+ }
79
+ }
80
+ }
81
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: f58738a3d70524925b8f242e443cd0c8
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "com.xd.sdk.payment",
3
3
  "displayName": "XDGSDK Payment",
4
- "version": "7.3.4",
4
+ "version": "7.6.0",
5
5
  "description": "XDGSDK",
6
6
  "unity": "2019.3",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
- "com.xd.sdk.common": "7.3.4"
9
+ "com.xd.sdk.common": "7.6.0"
10
10
  }
11
- }
11
+ }
@@ -1,32 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: d80cd6109a9b149a1ae0750375bbdbbe
3
- PluginImporter:
4
- externalObjects: {}
5
- serializedVersion: 2
6
- iconMap: {}
7
- executionOrder: {}
8
- defineConstraints: []
9
- isPreloaded: 0
10
- isOverridable: 1
11
- isExplicitlyReferenced: 0
12
- validateReferences: 1
13
- platformData:
14
- - first:
15
- Android: Android
16
- second:
17
- enabled: 1
18
- settings: {}
19
- - first:
20
- Any:
21
- second:
22
- enabled: 0
23
- settings: {}
24
- - first:
25
- Editor: Editor
26
- second:
27
- enabled: 0
28
- settings:
29
- DefaultValueInitialized: true
30
- userData:
31
- assetBundleName:
32
- assetBundleVariant:
@@ -1,32 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 706f5124c3803447b8ba8453530f3464
3
- PluginImporter:
4
- externalObjects: {}
5
- serializedVersion: 2
6
- iconMap: {}
7
- executionOrder: {}
8
- defineConstraints: []
9
- isPreloaded: 0
10
- isOverridable: 1
11
- isExplicitlyReferenced: 0
12
- validateReferences: 1
13
- platformData:
14
- - first:
15
- Android: Android
16
- second:
17
- enabled: 1
18
- settings: {}
19
- - first:
20
- Any:
21
- second:
22
- enabled: 0
23
- settings: {}
24
- - first:
25
- Editor: Editor
26
- second:
27
- enabled: 0
28
- settings:
29
- DefaultValueInitialized: true
30
- userData:
31
- assetBundleName:
32
- assetBundleVariant:
@@ -1,32 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 3da1d702a3c8e4daba2a48d18627da18
3
- PluginImporter:
4
- externalObjects: {}
5
- serializedVersion: 2
6
- iconMap: {}
7
- executionOrder: {}
8
- defineConstraints: []
9
- isPreloaded: 0
10
- isOverridable: 1
11
- isExplicitlyReferenced: 0
12
- validateReferences: 1
13
- platformData:
14
- - first:
15
- Android: Android
16
- second:
17
- enabled: 1
18
- settings: {}
19
- - first:
20
- Any:
21
- second:
22
- enabled: 0
23
- settings: {}
24
- - first:
25
- Editor: Editor
26
- second:
27
- enabled: 0
28
- settings:
29
- DefaultValueInitialized: true
30
- userData:
31
- assetBundleName:
32
- assetBundleVariant:
@@ -1,47 +0,0 @@
1
- //
2
- // XDGPaymentService.h
3
- // XDGPaymentSDK
4
- //
5
- // Created by JiangJiahao on 2020/11/23.
6
- // unity 桥接
7
-
8
- #import <Foundation/Foundation.h>
9
-
10
- NS_ASSUME_NONNULL_BEGIN
11
-
12
- @interface XDGPaymentService : NSObject
13
-
14
- // 查询 queryWithProductIds :
15
- + (void)productIds:(NSArray *)productIds bridgeCallback:(void (^)(NSString *result))callback;
16
-
17
- + (void)params:(NSDictionary *)params
18
- bridgeCallback:(void (^)(NSString *result))callback;
19
-
20
- // 支付 payWithProduct
21
- + (void)orderId:(NSString *)orderId
22
- productId:(NSString *)productId
23
- roleId:(NSString *)roleId
24
- serverId:(NSString *)serverId
25
- ext:(NSString *)ext
26
- bridgeCallback:(void (^)(NSString *result))callback;
27
-
28
- + (void)queryRestoredPurchases:(void (^)(NSString *result))callback;
29
-
30
- + (void)transactionIdentifier:(NSString *)transactionIdentifier
31
- productIdentifier:(NSString *)productIdentifier
32
- orderId:(NSString *)orderId
33
- roleId:(NSString *)roleId
34
- serverId:(NSString *)serverId
35
- ext:(NSString *)ext
36
- bridgeCallback:(void (^)(NSString *result))callback;
37
-
38
- /// 不带界面的补款
39
- + (void)checkRefundStatus:(void (^)(NSString *result))callback;
40
-
41
- //带UI界面的补款
42
- + (void)checkRefundStatusWithUI:(void (^)(NSString *result))callback;
43
-
44
-
45
- @end
46
-
47
- NS_ASSUME_NONNULL_END
@@ -1,7 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 868372ba49d64c42b6c7a40866ebbfa4
3
- DefaultImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant: