话不多说? 直接上代码
1 using引用
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.Purchasing;
using Google.Play.Billing.Internal;
using Google.Play.Billing;
?2变量定义
private static IStoreController m_StoreController;
private static IExtensionProvider m_ExtensionProvider;
private AndroidJavaObject _billingClient;
private JniUtils _jniUtils;
2 初始化(登录之后调用)
/// <summary>
/// 判断是否初始化过
/// </summary>
/// <returns></returns>
private bool IsInitialized()
{
return m_StoreController != null && m_ExtensionProvider != null;
}
/// <summary>
/// 初始化方法 游戏登录后调用
/// </summary>
/// <param name="productids"> 此参数为Google后台配置的商品id列表 没有传入的商品id不能购买 </param>
public void InitializePurchasing(List<string> productids)
{
if (AssetLoadPath.GetRunPlatformType() == AssetLoadPath.RunPlatformType.Editor)
{
return;
}
if (IsInitialized())
{
return;
}
ConfigurationBuilder builder;
if (Application.platform == RuntimePlatform.Android)
{
builder = ConfigurationBuilder.Instance(GooglePlayStoreModule.Instance());
}
else
{
builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
}
//设置商品
for (int i = 0; i < productids.Count; i++)
{
builder.AddProduct(productids[i], ProductType.Consumable, new IDs { { productids[i], GooglePlay.Name } });
}
// BillingClient 连接的回调
BillingClientStateListener _billingClientStateListener = new BillingClientStateListener();
_billingClientStateListener.OnBillingServiceDisconnected += () =>
{
Debug.Log("OnBillingServiceDisconnected Service disconnected, retrying connection...");
};
_billingClientStateListener.OnBillingSetupFinished += (billingResult) =>
{
Debug.Log("OnBillingSetupFinished ");
};
// BillingClient SetUp方法的回调
PurchasesUpdatedListener purchaseUpdatedListener = new PurchasesUpdatedListener();
purchaseUpdatedListener.OnPurchasesUpdated += ParsePurchaseResult;
// 这里连接 BillingClient
_billingClient = new AndroidJavaObject(Constants.BillingClient, Constants.Version);
_billingClient.Call(Constants.BillingClientSetUpMethod, JniUtils.GetApplicationContext(), purchaseUpdatedListener, false);
_billingClient.Call(Constants.BillingClientStartConnectionMethod, _billingClientStateListener);
// 实例一个 jniUtils 里面有一些公关方法可以用
var gameObject = new GameObject("GooglePlayBillingUtil");
GooglePlayBillingUtil _util = gameObject.AddComponent<GooglePlayBillingUtil>();
_jniUtils = new JniUtils(_util);
UnityPurchasing.Initialize(this, builder);
}
/// <summary>
/// BillingClient SetUp方法的回调
/// </summary>
/// <param name="billingResult"></param>
/// <param name="javaPurchasesList"></param>
private void ParsePurchaseResult(AndroidJavaObject billingResult, AndroidJavaObject javaPurchasesList)
{
var responseCode = _jniUtils.GetResponseCodeFromBillingResult(billingResult);
var debugMessage = JniUtils.GetDebugMessageFromBillingResult(billingResult);
Debug.Log(" 确认购买的回调 ParsePurchaseResult 11111 " + responseCode + debugMessage);
if (responseCode == BillingResponseCode.Ok)
{
}
else
{
Debug.LogError(string.Format("ParsePurchaseResult Purchase failed with error code '{0}' and debug message: '{1}'", responseCode, debugMessage));
}
}
/// <summary>
/// 初始化完成的回调
/// </summary>
/// <param name="controller"></param>
/// <param name="extensions"></param>
void IStoreListener.OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
m_StoreController = controller;
m_ExtensionProvider = extensions;
//下面的三行代码看需求是否需要 具体作用可以查看官方接入文档
var _playStoreExtensions = extensions.GetExtension<Google.Play.Billing.IGooglePlayStoreExtensions>();
_playStoreExtensions.SetObfuscatedAccountId("accountId"); //向 Google Play 传递经过混淆处理的帐号 ID
_playStoreExtensions.SetObfuscatedProfileId("profileId"); //向 Google Play 传递经过混淆处理的个人资料 ID
}
/// <summary>
/// 初始化失败的回调
/// </summary>
/// <param name="error"></param>
void IStoreListener.OnInitializeFailed(InitializationFailureReason error)
{
Debug.LogError("Google Billing IAP 初始化失败 :" + error);
}
4拉起支付
/// <summary>
/// 购买商品调用
/// </summary>
/// <param name="productID"> Google后台配置的商品id </param>
public void BuyProduct(string productID)
{
if (AssetLoadPath.GetRunPlatformType() == AssetLoadPath.RunPlatformType.Editor)
{
return;
}
if (IsInitialized())
{
Product produdt = m_StoreController.products.WithID(productID);
if (produdt != null && produdt.availableToPurchase)
{
m_StoreController.InitiatePurchase(produdt);
Debug.Log(produdt.metadata.localizedPrice);
}
else
{
Debug.Log("BuyProduct Fail");
}
}
else
{
Debug.Log("BuyProductID FAIL. Not initialized.");
}
}
/// <summary>
/// 购买成功的回调
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
PurchaseProcessingResult IStoreListener.ProcessPurchase(PurchaseEventArgs args)
{
string productId = args.purchasedProduct.definition.id;
Dictionary<string, object> wrapper = (Dictionary<string, object>)MiniJson.JsonDecode(args.purchasedProduct.receipt);
string store = (string)wrapper["Store"];
string payload = (string)wrapper["Payload"];
Dictionary<string, object> gpDetails = (Dictionary<string, object>)MiniJson.JsonDecode(payload);
string gpJson = (string)gpDetails["json"];
string gpSig = (string)gpDetails["signature"];
// TODO
// 这里向服务器发包,将 gpJson 和 gpSig 发给服务器做验证
return PurchaseProcessingResult.Complete;
}
/// <summary>
/// 购买失败的回调
/// </summary>
/// <param name="product"></param>
/// <param name="failureReason"></param>
void IStoreListener.OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
Debug.LogError(string.Format("Google Billing IAP 购买失败. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}
5消耗商品
/// <summary>
/// 确认购买 消耗商品 此方法要在服务器认证成功,并且成功发货之后调用
/// 两个参数均可在购买成功的回调json内解析出
/// </summary>
/// <param name="skuId">商品id</param>
/// <param name="token">订单token</param>
public void ConsumeAsync(string productId, string token )
{
var consumeParamsBuilder = new AndroidJavaObject(Constants.ConsumeParamsBuilder);
consumeParamsBuilder.Call<AndroidJavaObject>( Constants.ConsumeParamsBuilderSetPurchaseTokenMethod, token);
var consumeResponseListener = new ConsumeResponseListener(productId);
consumeResponseListener.OnConsumeResponse += ProcessConsumePurchaseResult;
_billingClient.Call(Constants.BillingClientConsumePurchaseMethod, consumeParamsBuilder.Call<AndroidJavaObject>(Constants.BuildMethod), consumeResponseListener);
}
/// <summary>
/// 消耗商品的回调
/// </summary>
/// <param name="productId"></param>
/// <param name="billingResult"></param>
private void ProcessConsumePurchaseResult(string productId, AndroidJavaObject billingResult)
{
var responseCode = _jniUtils.GetResponseCodeFromBillingResult(billingResult);
if (responseCode == BillingResponseCode.Ok)
{
}
else
{
var debugMessage = JniUtils.GetDebugMessageFromBillingResult(billingResult);
Debug.LogError(string.Format( "Failed to finish the transaction with error code {0} and debug message: {1}. " , responseCode, debugMessage));
}
}
6漏单检查
/// <summary>
/// 漏单补发 游戏登录后调用 InitializePurchasing
/// </summary>
public void RestoreTransactions ()
{
var inAppPurchasesResult = _billingClient.Call<AndroidJavaObject>(Constants.QueryPurchasesMethod, SkuType.InApp.ToString());
var subsPurchasesResult = _billingClient.Call<AndroidJavaObject>(Constants.QueryPurchasesMethod, SkuType.Subs.ToString());
if (_jniUtils.GetResponseCodeFromQueryPurchasesResult(inAppPurchasesResult) != BillingResponseCode.Ok ||
_jniUtils.GetResponseCodeFromQueryPurchasesResult(subsPurchasesResult) != BillingResponseCode.Ok)
{
return;
}
IEnumerable<Purchase> allPurchases = _jniUtils.ParseQueryPurchasesResult(inAppPurchasesResult).Concat(_jniUtils.ParseQueryPurchasesResult(subsPurchasesResult)).ToList();
//代码执行到这里会自动调用到购买成功的回调 在回调里处理好与服务器的通信即可
foreach (Purchase purchase in allPurchases)
{
Debug.Log(" 漏单 purchase.ProductId : " + purchase.ProductId);
Debug.Log(" 漏单 purchase.JsonReceipt : " + purchase.JsonReceipt);
Debug.Log(" 漏单 purchase.PurchaseState : " + purchase.PurchaseState);
}
}
流程说明 :
登录后调用 1初始化方法?
需要拉起充值时调用 4拉起支付
充值成功之后向服务器发包验证? 服务器发货
服务器发货之后? 调用 5消耗商品
至于漏单检查,推荐也放在登录之后,在初始化之后调用?
漏单检查的作用是在支付完成之后? 如果出现断网 或者服务器关闭等情况,则服务器不会发货,这样的话,玩家是付了钱,但没收到货? 当然,用户可以自己操作后台退款,但显然这并不是最好的处理 方式
所以才有漏单检查,在登录之后检查到有未消费的订单,直接帮他消费掉就好了
希望此贴对您的开发有所帮助??
|