public static async Task <(PoseBillingResult BillingResult, long Payload, string OrderId)> InAppProductProcess(InAppPurchase inAppPurchase, string appPackageName, string purchaseToken) { ProductPurchase poductPurchase = await _androidPublisher.Purchases.Products.Get(appPackageName, inAppPurchase.ProductId, purchaseToken).ExecuteAsync(); if (!long.TryParse(poductPurchase.DeveloperPayload, out long payLoad)) { return(null, 0, ""); } PoseBillingResult billingResult = new PoseBillingResult(); switch (poductPurchase.PurchaseState) { case 0: billingResult.PurchaseStateType = PosePurchaseStateType.Purchased; break; case 1: billingResult.PurchaseStateType = PosePurchaseStateType.Canceled; break; case 2: billingResult.PurchaseStateType = PosePurchaseStateType.Pending; break; } DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0); DateTime purchaseTime = origin.AddMilliseconds(poductPurchase.PurchaseTimeMillis ?? 0); billingResult.MemberRoleType = inAppPurchase.OfferRoleType; billingResult.RoleExpireTime = purchaseTime.AddDays(inAppPurchase.OfferPeriod); billingResult.ProductId = inAppPurchase.ProductId; return(billingResult, payLoad, poductPurchase.OrderId); }
public static async Task <(PoseBillingResult BillingResult, long Payload, string OrderId)> SubscriptionProcess(InAppPurchase inAppPurchase, string appPackageName, string purchaseToken) { SubscriptionPurchase subscriptionPurchase = await _androidPublisher.Purchases.Subscriptions.Get(appPackageName, inAppPurchase.ProductId, purchaseToken).ExecuteAsync(); if (!long.TryParse(subscriptionPurchase.DeveloperPayload, out long payLoad)) { return(null, 0, ""); } DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0); DateTime expireTiem = origin.AddMilliseconds(subscriptionPurchase.ExpiryTimeMillis ?? 0); PoseBillingResult billingResult = new PoseBillingResult(); billingResult.PurchaseStateType = ParseSubscriptionPurchaseState(subscriptionPurchase); billingResult.MemberRoleType = inAppPurchase.OfferRoleType; billingResult.RoleExpireTime = expireTiem; billingResult.ProductId = inAppPurchase.ProductId; return(billingResult, payLoad, subscriptionPurchase.OrderId); }
public async Task <PoseBillingResult> PurchaseAsync(string productId, ItemType itemType) { PoseBillingResult billingResult = null; var billing = CrossInAppBilling.Current; var webApiService = ShinyHost.Resolve <IWebApiService>(); var deviceInfoHelper = DependencyService.Resolve <IDeviceInfoHelper>(); try { var connected = await billing.ConnectAsync(itemType); if (!connected) { return new PoseBillingResult { PurchaseErrorType = PosePurchaseErrorType.FailStoreConnect } } ; // 서버에서 payload 얻어오기 var server_payload = await webApiService.RequestAsyncWithToken <O_E_INSERT_IN_APP_BILLING_BY_GOOGLE>(new WebRequestContext { SerializeType = SerializeType.MessagePack, MethodType = WebMethodType.POST, BaseUrl = AppConfig.PoseWebBaseUrl, ServiceUrl = BillingProxy.ServiceUrl, SegmentGroup = BillingProxy.P_E_INSERT_IN_APP_BILLING_BY_GOOGLE, NeedEncrypt = true, PostData = new I_E_INSERT_IN_APP_BILLING_BY_GOOGLE { ProductID = productId, } }); if (server_payload == null) { return new PoseBillingResult { PurchaseErrorType = PosePurchaseErrorType.ServerError } } ; //check purchases var googlePurchaseResult = await billing.PurchaseAsync(productId, itemType, server_payload.BillingPayload); if (googlePurchaseResult == null) { return new PoseBillingResult { PurchaseErrorType = PosePurchaseErrorType.FailStoreConnect } } ; // 서버 인증 using (UserDialogs.Instance.Loading(LocalizeString.Loading)) { var server_billingResult = await webApiService.RequestAsyncWithToken <O_E_UPDATE_IN_APP_BILLING_BY_GOOGLE>(new WebRequestContext { SerializeType = SerializeType.MessagePack, MethodType = WebMethodType.POST, BaseUrl = AppConfig.PoseWebBaseUrl, ServiceUrl = BillingProxy.ServiceUrl, SegmentGroup = BillingProxy.P_E_UPDATE_IN_APP_BILLING_BY_GOOGLE, NeedEncrypt = true, PostData = new I_E_UPDATE_IN_APP_BILLING_BY_GOOGLE { AppPackageName = deviceInfoHelper.AppPackageName, ProductID = googlePurchaseResult.ProductId, PurchaseToken = googlePurchaseResult.PurchaseToken, } }); billingResult = server_billingResult?.BillingResult ?? new PoseBillingResult { PurchaseErrorType = PosePurchaseErrorType.SuccessPurchaseButServerError }; //If we are on iOS we are done, else try to consume the purchase //Device.RuntimePlatform comes from Xamarin.Forms, you can also use a conditional flag or the DeviceInfo plugin //if (Device.RuntimePlatform == Device.iOS) // return result; // 소비성 상품은 컨슘 처리 if (itemType == ItemType.InAppPurchase && billingResult.PurchaseStateType == PosePurchaseStateType.Purchased) { await CrossInAppBilling.Current.ConsumePurchaseAsync(googlePurchaseResult.ProductId, googlePurchaseResult.PurchaseToken); } } } catch (InAppBillingPurchaseException pEx) { billingResult = new PoseBillingResult(); if (pEx.PurchaseError == PurchaseError.AlreadyOwned) { billingResult.PurchaseErrorType = PosePurchaseErrorType.AlreadyOwned; } } catch (Exception) { billingResult = new PoseBillingResult(); billingResult.PurchaseErrorType = PosePurchaseErrorType.UnknownError; } finally { await billing.DisconnectAsync(); } return(billingResult); }
public static async Task <O_E_CHECK_MEMBERSHIP_BY_GOOGLE> Execute(I_E_CHECK_MEMBERSHIP_BY_GOOGLE input, long userNo, int serviceRoleType) { PoseBillingResult billingResult = null; //////////////////////////////////////////////////// /// 프로모션 유저 만료 처리 /////////////////////////////////////////////////// if (serviceRoleType == (int)ServiceRoleType.Promotion) { billingResult = new PoseBillingResult() { MemberRoleType = MemberRoleType.Regular, RoleExpireTime = DateTime.UtcNow, }; // Update DB bool db_output_promo; using (var P_UPDATE_USER_ROLE = new PoseGlobalDB.Procedures.P_UPDATE_USER_ROLE()) { P_UPDATE_USER_ROLE.SetInput(new PoseGlobalDB.Procedures.P_UPDATE_USER_ROLE.Input { UserNo = userNo, LinkedTransNo = 0, RoleType = billingResult.MemberRoleType.ToString(), RoleExpireTime = billingResult.RoleExpireTime, CurrentTime = DateTime.UtcNow, }); db_output_promo = P_UPDATE_USER_ROLE.OnQuery(); if (P_UPDATE_USER_ROLE.EntityStatus != null || db_output_promo == false) { ErrorHandler.OccurException(RowCode.DB_User_Role_Update_Failed); } } // Refrash PoseToken billingResult.MemberRoleType.ToString().TryParseEnum(out ServiceRoleType promoServiceRoleType); billingResult.PoseToken = PoseCredentials.CreateToken(userNo, promoServiceRoleType); return(new O_E_CHECK_MEMBERSHIP_BY_GOOGLE { BillingResult = billingResult, }); } //////////////////////////////////////////////////// /// 결제 유저 멤버십 처리 /////////////////////////////////////////////////// // Check DB PoseGlobalDB.Procedures.P_SELECT_LINKED_BILLING.Output db_output; using (var P_SELECT_LINKED_BILLING = new PoseGlobalDB.Procedures.P_SELECT_LINKED_BILLING()) { P_SELECT_LINKED_BILLING.SetInput(userNo); db_output = P_SELECT_LINKED_BILLING.OnQuery(); if (P_SELECT_LINKED_BILLING.EntityStatus != null || db_output.Result != 0) { ErrorHandler.OccurException(RowCode.P_SELECT_LINKED_BILLING + db_output.Result); } } // Check ProductID valid if (!InAppPurchase.TryGetInAppPurchase(db_output.InAppBilling.product_id, out var inAppPurchase) || inAppPurchase.StoreType != StoreType.GooglePlay) { Log4Net.WriteLog($"Invalid Google ProudctId, UserNo: {userNo}, productId: {db_output.InAppBilling.product_id}", Log4Net.Level.ERROR); ErrorHandler.OccurException(RowCode.Invalid_Product_Id); } long linkedTransNo = 0; if (inAppPurchase.PurchaseType == InAppPurchaseType.InAppProduct) { linkedTransNo = db_output.UserRole.linked_trans_no; billingResult = new PoseBillingResult(); billingResult.MemberRoleType = inAppPurchase.OfferRoleType; billingResult.RoleExpireTime = db_output.UserRole.expire_time; billingResult.ProductId = db_output.InAppBilling.product_id; billingResult.PurchaseStateType = db_output.UserRole.expire_time > DateTime.UtcNow ? PosePurchaseStateType.Purchased : PosePurchaseStateType.Unknown; } else if (inAppPurchase.PurchaseType == InAppPurchaseType.Subscription) { var process_ret = await P_E_UPDATE_IN_APP_BILLING_BY_GOOGLE.SubscriptionProcess(inAppPurchase, input.AppPackageName, db_output.InAppBilling.purchase_token); billingResult = process_ret.BillingResult; linkedTransNo = process_ret.Payload; } // 회원등급 심사 if (billingResult.PurchaseStateType != PosePurchaseStateType.Purchased && billingResult.PurchaseStateType != PosePurchaseStateType.Grace) // 결제 유예기간.. { billingResult.MemberRoleType = MemberRoleType.Regular; linkedTransNo = 0; } // Update DB bool db_output2; using (var P_UPDATE_USER_ROLE = new PoseGlobalDB.Procedures.P_UPDATE_USER_ROLE()) { P_UPDATE_USER_ROLE.SetInput(new PoseGlobalDB.Procedures.P_UPDATE_USER_ROLE.Input { UserNo = userNo, LinkedTransNo = linkedTransNo, RoleType = billingResult.MemberRoleType.ToString(), RoleExpireTime = billingResult.RoleExpireTime, CurrentTime = DateTime.UtcNow, }); db_output2 = P_UPDATE_USER_ROLE.OnQuery(); if (P_UPDATE_USER_ROLE.EntityStatus != null || db_output2 == false) { ErrorHandler.OccurException(RowCode.DB_User_Role_Update_Failed); } } // Refrash PoseToken billingResult.MemberRoleType.ToString().TryParseEnum(out ServiceRoleType convertedServiceRoleType); billingResult.PoseToken = PoseCredentials.CreateToken(userNo, convertedServiceRoleType); return(new O_E_CHECK_MEMBERSHIP_BY_GOOGLE { BillingResult = billingResult, }); }
public static async Task <O_E_UPDATE_IN_APP_BILLING_BY_GOOGLE> Execute(I_E_UPDATE_IN_APP_BILLING_BY_GOOGLE input, long userNo) { if (input == null || string.IsNullOrEmpty(input.ProductID) || string.IsNullOrEmpty(input.AppPackageName) || string.IsNullOrEmpty(input.PurchaseToken)) { ErrorHandler.OccurException(RowCode.Invalid_InputValue); } // Check ProductID valid if (!InAppPurchase.TryGetInAppPurchase(input.ProductID, out var inAppPurchase) || inAppPurchase.StoreType != StoreType.GooglePlay) { Log4Net.WriteLog($"Invalid Google ProudctId, UserNo: {userNo}, productId: {input.ProductID}", Log4Net.Level.ERROR); ErrorHandler.OccurException(RowCode.Invalid_Product_Id); } PoseBillingResult billingResult = null; long trasNo = 0; string orderId = string.Empty; switch (inAppPurchase.PurchaseType) { case InAppPurchaseType.InAppProduct: // 소비성 상품 { var process_ret = await InAppProductProcess(inAppPurchase, input.AppPackageName, input.PurchaseToken); billingResult = process_ret.BillingResult; trasNo = process_ret.Payload; orderId = process_ret.OrderId; } break; case InAppPurchaseType.Subscription: // 구독 상품 { var process_ret = await SubscriptionProcess(inAppPurchase, input.AppPackageName, input.PurchaseToken); billingResult = process_ret.BillingResult; trasNo = process_ret.Payload; orderId = process_ret.OrderId; } break; } // 유효하지않은 PurchaseToken if (billingResult == null) { Log4Net.WriteLog($"Google PurchaseToken is Invalid, UserNo: {userNo}, productId: {input.ProductID}, purchaseToken: {input.PurchaseToken}", Log4Net.Level.ERROR); ErrorHandler.OccurException(RowCode.Invalid_Google_Receipt); } if (billingResult.PurchaseStateType == PosePurchaseStateType.Purchased) { // DB Process PoseGlobalDB.Procedures.P_UPDATE_IN_APP_BILLING.Output db_output; using (var P_UPDATE_IN_APP_BILLING = new PoseGlobalDB.Procedures.P_UPDATE_IN_APP_BILLING()) { P_UPDATE_IN_APP_BILLING.SetInput(new PoseGlobalDB.Procedures.P_UPDATE_IN_APP_BILLING.Input { UserNo = userNo, TransNo = trasNo, PurchaseState = PosePurchaseStateType.Purchased.ToString(), PurchaseToken = input.PurchaseToken, OrderId = orderId, RoleType = billingResult.MemberRoleType.ToString(), RoleExpireTime = billingResult.RoleExpireTime, CurrentTime = DateTime.UtcNow, }); db_output = P_UPDATE_IN_APP_BILLING.OnQuery(); if (P_UPDATE_IN_APP_BILLING.EntityStatus != null || db_output.Result != 0) { ErrorHandler.OccurException(RowCode.P_UPDATE_IN_APP_BILLING + db_output.Result); } } // Refrash PoseToken billingResult.MemberRoleType.ToString().TryParseEnum(out ServiceRoleType serviceRoleType); billingResult.PoseToken = PoseCredentials.CreateToken(userNo, serviceRoleType); } return(new O_E_UPDATE_IN_APP_BILLING_BY_GOOGLE { BillingResult = billingResult, }); }