Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] offerToken is required for constructing ProductDetailsParams #2726

Open
talha-irshad-kodexo opened this issue Apr 16, 2024 · 0 comments

Comments

@talha-irshad-kodexo
Copy link

talha-irshad-kodexo commented Apr 16, 2024

Please use the Discussion board if you want to get some help. Please use issues to report bugs.

Description

I am using the requestPurchase method of this package and its working fine on IOS but in android, it is giving error saying "offerToken is required for constructing ProductDetailsParams"

Expected Behavior

The inapp purchase works fine

Screenshots

jkikmZ

Environment:

  • react-native-iap: 12.10.8
  • react-native: 0.72.6
  • Platforms (iOS, Android, emulator, simulator, device): Device Google Pixel 3XL android 12

To Reproduce
Steps to reproduce the behavior:

  1. Initialize package using initConnection function
  2. Fetch skus
  3. call the requestPurchase function and provide skus in it
  4. It gives this error

[Optional] Additional Context

this is my code:

async buyProductMethod(inApp_plan_id, isRecurring) {
    try {
      this.setState({isLoading: true});
      isPurchaseRunning = true;
      const offerToken =
        this.state.skuObjs?.subscriptions?.[0]?.subscriptionOfferDetails?.[0]
          ?.offerToken;
      console.log('this.state.skuObjs-------------->', offerToken);
      let skuObj = {};
      if (Platform.OS === 'android') {
        skuObj.skus = [inApp_plan_id];
      } else {
        skuObj.sku = inApp_plan_id;
      }
      // requestPurchase({...skuObj}).then((data) => {
      requestPurchase({...skuObj})
        .then(data => {
          //for both for rec and non rec in ios and android.
          console.log("buyProductMethod", data);
          this.setState({isLoading: false});
        })
        .catch(err => {
          Alert.alert("Error",err?.message)
          this.setState({isLoading: false});
        });
      // requestPurchase({sku:inApp_plan_id}).then((data) => {
      //   //for both for rec and non rec in ios and android.
      //   console.log("buyProductMethod", data);
      //   this.setState({isLoading: false});
      // }).catch(err=>{
      //   Alert.alert("Error",err?.message)
      //   this.setState({isLoading: false});
      // });
    } catch (err) {
      console.log("BUY_ERROR", err);
      console.warn(err.code, err.message);
      isPurchaseRunning = false;
    }
  }

Content of the whole file:

//import libraries
import React, { PureComponent } from "react";
import {
  View,
  Text,
  TouchableOpacity,
  Image,
  ImageBackground,
  ScrollView,
  BackHandler,
  Platform,
  ActivityIndicator,
  Alert,
} from "react-native";
import Colors from "../../common/colorsFonts/Colors";
import Styles from "./Styles";
import Constants, { diff1x, diff2x, diff3x } from "../../utils/Constant";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import * as Actions from "./SubscriptionAction";
//import Loader from "../../components/loader";
import String from "../../common/String";
import LocalStorage, { getData, storeData } from "../../apiHelper/LocalStorage";
import { NavigationActions, StackActions } from "@react-navigation/native";
import PaymentPopup from "../../components/PaymentPopup";
import moment from "moment";
import WarningInfo from "../../components/WarningInfo";
// import { EventRegister } from 'react-native-event-listeners';
import Toast from "react-native-simple-toast";
import {
  BaseUrl,
  SUBSCRIPTION_LIST,
  IN_APP_LOG,
  AndroidValidReceiptUrl,
  ClientId,
  PURCHASE_IN_APP_SUBSCRIPTION,
  SecretKey,
  RefreshToken,
  IosInAppSecretPassword,
  ACCOUNT_STATUS,
  IN_APP_UPDATE_SUBSCRIPTION,
} from "../../apiHelper/Config";
import NavigationService from "../../appNavigation/NavigationService";
import {
  requestPurchase,
  getProducts,
  InAppPurchase,
  PurchaseError,
  SubscriptionPurchase,
  finishTransaction,
  purchaseErrorListener,
  purchaseUpdatedListener,
  getSubscriptions,
  initConnection,
  flushFailedPurchasesCachedAsPendingAndroid,
  getAvailablePurchases,
  validateReceiptIos,
} from "react-native-iap";
import Images from "../../common/Images";

var subscriptionListArr = [],
  isPayment = "",
  isPayment_In_app = "",
  isPaySuccess = "",
  receiptAccessToken = "",
  activePlanData = null,
  purchaseData = null,
  plan_amount = null;

let purchaseUpdateSubscription;
let purchaseErrorSubscription;
let inAppStoreData;
let isPurchaseRunning = false;

// create a component
class Subscription extends PureComponent {
  purchaseUpdateSubscription = null;
  purchaseErrorSubscription = null;

  constructor(props) {
    super(props);
    this.state = {
      subscriptionImg: "",
      selectionSection: -1,
      selectionRow: -1,
      receipt: "",
      isPaymentPopup: false,
      item_id: null,
      // Plan_amount: null,
      planType: null,
      inApp_rec_Plan_id: null,
      inApp_non_rec_Plan_id: null,
      infoAlert: false,
      infoAlertMsg: "",
      infoKey: "",
      isRecurring: "",
      isDataAvailable: false,
      subsData: [],
      showText: true,
      foundInactive: false,
      isLoading: false,
      planFor: "",
      is_recurring: "",
      skuObjs: null,
    };

    //console.log("Props Here ....", props);
  }

  /* Life cycle methods */
  UNSAFE_componentWillMount() {
    this.setImage();
    LocalStorage.getStoreInAppData((storeData) => {
      inAppStoreData = JSON.parse(storeData);
      //console.log('inAppStoreData ', inAppStoreData)
    });
  }

  /* Call account status api */
  async getAccountStatusApi() {
    if (Constants.NETWORK_CHECK == true) {
      let url = BaseUrl() + ACCOUNT_STATUS;
      await fetch(url, {
        method: "GET",
        headers: {
          accept: "application/json",
          "access-token": Constants.ACCESS_TOKEN,
          "app-version": Constants.appDisplayVersion,
          "device-app-version": Constants.version,
          Authorization: `Bearer ${Constants.ACCESS_TOKEN}`,
        },
      })
        .then((response) => response.json())
        .then((responseJson) => {
          if (responseJson.success) {
            LocalStorage.saveUserActivePlan(responseJson.data);
          } else {
            LocalStorage.saveUserActivePlan(null);
          }
        })
        .catch((error) => {});
    } else {
      setTimeout(() => {
        this.setState({
          infoAlert: true,
          infoAlertMsg: String.NO_INTERNET_CONN,
        });
      }, 500);
    }
  }

  async componentDidMount() {
    try {
      await initConnection();
      //console.log('result', result);
      //await RNIap.consumeAllItemsAndroid();
      if (Platform.OS === "android") {
        await flushFailedPurchasesCachedAsPendingAndroid();
      }
    } catch (err) {
      console.warn(err.code, err.message);
    }

    this._getReceiptValidAndroidToken();
    BackHandler.addEventListener("hardwareBackPress", this.handleBackPress);
    this.getAccountStatusApi();
    if (Constants.NETWORK_CHECK == true) {
      this.callSubscriptionApi();
      // this.getUpdatePurchase();
    } else {
      setTimeout(() => {
        this.setState({
          infoAlert: true,
          infoAlertMsg: String.NO_INTERNET_CONN,
        });
      }, 500);
    }

    this.purchaseUpdateSubscription = purchaseUpdatedListener(
      async (purchase: InAppPurchase | SubscriptionPurchase) => {
        console.log("purchase ", purchase);
        if (plan_amount != null) {
          purchaseData = purchase;
          this.requestInAppPurchase(this.state.is_recurring, purchase, "");
          // console.log("buy_product_transaction_data_success", purchase)
          this._transactionLogApi(
            "buy_product_transaction_data_success",
            purchase
          );
        }
        // const receipt = purchase.transactionReceipt;
        // if (receipt) {
        // 	try {
        // 		const ackResult = await finishTransaction(purchase);
        // 	} catch (ackErr) {
        // 		console.warn('ackErr', ackErr);
        // 	}
        // }
      }
    );

    this.purchaseErrorSubscription = purchaseErrorListener(
      (error: PurchaseError) => {
        console.log("--------->",error)
        plan_amount = null;
        purchaseData = null;
        isPurchaseRunning = false;
        (isPayment_In_app = ""),
          // console.log("buy_product_transaction_data_failed", error)
          this._transactionLogApi("buy_product_transaction_data_failed", error);
      }
    );
  }

  async getFinishTransaction() {
    const receipt = purchaseData.transactionReceipt;
    if (receipt) {
      console.log("receipt",receipt)
      try {
        const ackResult = await finishTransaction({purchase: purchaseData});
        purchaseData = null;
      } catch (ackErr) {
        console.warn("ackErr", ackErr);
      }
    }
  }

  UNSAFE_componentWillReceiveProps(newProps) {
    // this.setState({ isLoading: false });
    setTimeout(() => {
      this.setState({ isLoading: false });
    }, 1000);

    if (newProps != null && newProps.data.data) {
      if (newProps.data.data.success == true) {
        if (isPayment == "yes" || isPayment_In_app == "yes") {
          isPurchaseRunning = false;
          plan_amount = null;
          LocalStorage.saveUserActivePlan(newProps.data.data.data);
          // console.log("api_call_for_new_subsription_success", newProps.data.data.data)
          this._transactionLogApi(
            "api_call_for_new_subsription_success",
            newProps.data.data.data
          );

          setTimeout(() => {
            if (isPayment == "yes") {
              this.setState({
                infoAlert: true,
                infoAlertMsg: newProps.data.data.message,
                infoKey: "paymentSuccess",
                isRecurring: newProps.data.data.data.recurring,
              });
            }
          }, 500);
          // isPayment = 'no'; isPayment_In_app = 'no';
          this.getFinishTransaction();
        } else {
          //For Stripe key.
          // stripe.setOptions({
          // 	publishableKey: newProps.data.data.stripeKey,
          // });
          subscriptionListArr = newProps.data.data.data;
          newProps.data.data.data.map((val) => {
            val.plan_detail.map((x) => {
              this.state.subsData.push(x);
            });
          });
          if (this.state.subsData.length == 0) {
            this.setState({ isDataAvailable: false, showText: false });
          } else if (this.state.subsData.length == 1) {
            this.state.subsData.map((val) => {
              if (val.status == "inactive") {
                this.setState({
                  foundInactive: true,
                  isDataAvailable: true,
                  showText: true,
                });
              } else {
                this.setState({
                  foundInactive: false,
                  isDataAvailable: true,
                  showText: true,
                });
              }
            });
          } else {
            this.setState({ isDataAvailable: true, showText: true });
          }
          // this._getReceiptValidAndroidToken();
          this.getUpdatePurchaseAtSubscription();
        }
      } else {
        if (newProps.data.data.success == false) {
          isPurchaseRunning = false;
          plan_amount = null;
          purchaseData = null;
          if (isPayment_In_app == "yes") {
            // console.log("api_call_for_new_subscription_failed", 'subscription api failed')
            this._transactionLogApi(
              "api_call_for_new_subscription_failed",
              "subscription api failed"
            );
          }
          setTimeout(() => {
            if (newProps.data.data.code == 401) {
              this.setState({
                infoAlert: true,
                infoAlertMsg: newProps.data.data.errors.message,
                infoKey: "401",
              });
            } else if (newProps.data.data.code == 403) {
              this.setState({
                infoAlert: true,
                infoAlertMsg: newProps.data.data.errors.message,
                infoKey: "updateApp",
              });
            } else {
              this.setState({
                infoAlert: true,
                infoAlertMsg: newProps.data.data.errors.message,
              });
            }
          }, 500);
        }
      }
    }
  }

  componentWillUnmount() {
    if (this.purchaseUpdateSubscription) {
      this.purchaseUpdateSubscription.remove();
      this.purchaseUpdateSubscription = null;
    }

    if (this.purchaseErrorSubscription) {
      this.purchaseErrorSubscription.remove();
      this.purchaseErrorSubscription = null;
    }
    isPayment = "no";
    isPayment_In_app = "no";
    plan_amount = null;
    purchaseData = null;
    isPurchaseRunning = false;
    // RNIap.endConnection();
    if (purchaseUpdateSubscription) {
      purchaseUpdateSubscription.remove();
      purchaseUpdateSubscription = null;
    }
    if (purchaseErrorSubscription) {
      purchaseErrorSubscription.remove();
      purchaseErrorSubscription = null;
    }
    BackHandler.removeEventListener("hardwareBackPress", this.handleBackPress);
  }
  /*=========== End life cycle methods =============*/

  /* Calculate 24 hours */
  is24HoursCompleted = (key) => {
    getData(key).then((dateTime) => {
      let hours;
      if (dateTime != null) {
        // dateTimeFormat = 'YYYY/MM/DD HH:MM:SS'
        hours = moment().diff(moment(dateTime), "hours");
        if (hours >= 24) {
          return true;
        } else {
          return false;
        }
      } else {
        return true;
      }
    });
  };

  backToScreen() {
    if (Platform.OS == "ios" && isPurchaseRunning) {
      Toast.show(String.paymentRequestProcess);
    } else {
      if (
        this.props?.route.params != null ||
        this.props?.route.params != undefined
      ) {
        var param = {
          isFrom: "subscription",
          isPayment: isPaySuccess,
        };
        isPaySuccess = "";
        Constants.removeSideMenuBlur();
        this.props?.route.params.returnData(param);
        this.props?.navigation.goBack();
      } else {
        Constants.removeSideMenuBlur();
        NavigationService.reset("DrawerStack");
        // EventRegister.emit('isPayment', true);
      }
    }
  }

  /* Android back press */
  handleBackPress = () => {
    //console.log(" handleBackPress  at subscription screen ");
    if (
      this.props?.route.params != null ||
      this.props?.route.params != undefined
    ) {
      var param = {
        isFrom: "subscription",
        isPayment: isPaySuccess,
      };
      isPaySuccess = "";
      Constants.removeSideMenuBlur();
      this.props?.route.params.returnData(param);
      this.props?.navigation.goBack();
      return true;
    } else {
      return true;
    }
  };

  /* Get updated purchase */
  getUpdatePurchaseAtSubscription() {
    LocalStorage.getUserActivePlan((data) => {
      activePlanData = JSON.parse(data);
      this.activePlanStatusAtSubscription();
    });
  }

  /* Active plan for inApp purchase */
  async activePlanStatusAtSubscription() {
    // IOS
    let productItem = null;
    let isAutoRenew = "no";

    // IOS & Android
    var getAllPurchases = [];
    let currentDate = moment().format("x");
    //console.log('currentDate ', currentDate)
    //console.log('subscription screen =====================')

    try {
      getAllPurchases = await getAvailablePurchases();
      console.log(" getAllPurchases ", getAllPurchases);
    } catch (err) {
      console.warn(err);
    }

    // If user didn't purchase subscription
    if (getAllPurchases.length > 0) {
      var finalPurchaseItem = null;
      const sortedAvailablePurchases = getAllPurchases.sort(
        (a, b) => b.transactionDate - a.transactionDate
      );
      //console.log(' sortedAvailablePurchases ', sortedAvailablePurchases);
      finalPurchaseItem = sortedAvailablePurchases[0];
      let subscriptionObj = null;

      if (Platform.OS == "ios") {
        if (finalPurchaseItem != null) {
          const receiptBody = {
            "receipt-data": finalPurchaseItem.transactionReceipt,
            password: IosInAppSecretPassword,
          };
          let receiptResult = null;
          try {
            receiptResult = await validateReceiptIos({
              receiptBody,
              isTest: Constants.isTestEnvironment
            });
            const sortedReceiptInfo = receiptResult.latest_receipt_info.sort(
              (a, b) => b.purchase_date_ms - a.purchase_date_ms
            );
            productItem = sortedReceiptInfo[0];

            if (this.state.subsData.length > 0) {
              let commonID = productItem.product_id;
              subscriptionObj = this.state.subsData.filter(function (item) {
                return (
                  item.ios_plan_id === commonID ||
                  item.android_rec_plan_id === commonID ||
                  item.android_plan_id === commonID ||
                  item.ios_rec_plan_id === commonID
                );
              });

              console.log("result at subscription ", subscriptionObj);
            }

            receiptResult.pending_renewal_info.map((item, index) => {
              if (finalPurchaseItem.productId == item.product_id) {
                isAutoRenew = item.auto_renew_status == "1" ? "yes" : "no";
              }
            });

            console.log("productItem", productItem);

            if (productItem.expires_date_ms >= currentDate) {
              LocalStorage.setStoreInAppData(productItem);
              if (this.is24HoursCompleted("subscription_one")) {
                this._transactionLogApi(
                  "subscription_valid_receipt_success",
                  productItem
                );
                storeData(
                  "subscription_one",
                  moment().format("YYYY/MM/DD HH:mm:ss")
                );
              }
            }
          } catch (error) {
            if (productItem.expires_date_ms >= currentDate) {
              this._transactionLogApi(
                "subscription_valid_receipt_failed",
                finalPurchaseItem.transactionReceipt
              );
            }
          }
        }

        if (
          activePlanData == null &&
          productItem != null &&
          productItem.expires_date_ms >= currentDate
        ) {
          let pObject = {
            productItem: productItem,
            isAutoRenew: isAutoRenew,
            activePlanData: "null",
          };
          if (this.is24HoursCompleted("subscription_two")) {
            this._transactionLogApi(
              "subscription_active_plan_in_store_not_in_db",
              pObject
            );
            storeData(
              "subscription_two",
              moment().format("YYYY/MM/DD HH:mm:ss")
            );
          }
        }
      }

      var start_date = null;
      var validity_date = null;
      var transaction_id = null;
      var recurring_id = null;
      var product_id = null;
      var auto_renew_status = null;
      var androidReceipt = null;

      // iOS IAP Update Receipt
      if (
        Platform.OS == "ios" &&
        productItem != null &&
        productItem.expires_date_ms >= currentDate
      ) {
        var dateStart = JSON.parse(productItem.purchase_date_ms);
        start_date = moment(dateStart).format("YYYY-MM-DD");
        var dateStr = JSON.parse(productItem.expires_date_ms);
        validity_date = moment(dateStr).format("YYYY-MM-DD");

        recurring_id = productItem.original_transaction_id;
        transaction_id = productItem.transaction_id;
        product_id = productItem.product_id;

        if (Constants.NETWORK_CHECK == true) {
          this.getUpdateInAppApi(
            subscriptionObj,
            productItem.transaction_id,
            isAutoRenew,
            validity_date,
            start_date,
            productItem.product_id,
            productItem.original_transaction_id,
            finalPurchaseItem.transactionReceipt
          );
        } else {
          setTimeout(() => {
            this.setState({
              infoAlert: true,
              infoAlertMsg: String.NO_INTERNET_CONN,
            });
          }, 500);
        }
      }

      // Android IAP Update Receipt
      if (Platform.OS == "android" && finalPurchaseItem != null) {
        //console.log(" All listing this.state.subsData: ", this.state.subsData);
        if (this.state.subsData.length > 0) {
          let commonID = finalPurchaseItem.productId;
          subscriptionObj = this.state.subsData.filter(function (item) {
            return (
              item.ios_plan_id === commonID ||
              item.android_rec_plan_id === commonID ||
              item.android_plan_id === commonID ||
              item.ios_rec_plan_id === commonID
            );
          });

          //console.log('result', subscriptionObj)
        }

        //console.log('finalPurchaseItem 22', finalPurchaseItem)
        var jsonData = JSON.parse(finalPurchaseItem.transactionReceipt);
        let url =
          "https://www.googleapis.com/androidpublisher/v3/applications/" +
          jsonData.packageName +
          "/purchases/subscriptions/" +
          jsonData.productId +
          "/tokens/" +
          jsonData.purchaseToken;
        fetch(url, {
          method: "GET",
          headers: {
            Authorization: "Bearer " + receiptAccessToken,
          },
        })
          .then((response) => response.json())
          .then((responseJson) => {
            if (responseJson) {
              //console.log('response android json : ', responseJson)
              if (responseJson.error) {
              } else {
                // console.log("responseJson android_recipt", responseJson);
                androidReceipt = responseJson;
                if (responseJson.expiryTimeMillis >= currentDate) {
                  if (this.is24HoursCompleted("subscription_three")) {
                    this._transactionLogApi(
                      "subscription_valid_reciept_success",
                      responseJson
                    );
                    storeData(
                      "subscription_three",
                      moment().format("YYYY/MM/DD HH:mm:ss")
                    );
                  }
                  var dateStr = JSON.parse(responseJson.expiryTimeMillis);
                  validity_date = moment(dateStr).format("YYYY-MM-DD");
                  var dateStart = JSON.parse(responseJson.startTimeMillis);
                  start_date = moment(dateStart).format("YYYY-MM-DD");

                  transaction_id = responseJson.orderId;
                  recurring_id = finalPurchaseItem.transactionId;
                  product_id = finalPurchaseItem.productId;
                  var recurringStatus = responseJson.autoRenewing;
                  auto_renew_status = recurringStatus == false ? "no" : "yes";
                  // if (recurring_id && auto_renew_status) {
                  this.getUpdateInAppApi(
                    subscriptionObj,
                    transaction_id,
                    auto_renew_status,
                    validity_date,
                    start_date,
                    product_id,
                    recurring_id,
                    finalPurchaseItem.transactionReceipt
                  );
                  // }
                } else {
                  if (
                    activePlanData == null &&
                    finalPurchaseItem != null &&
                    responseJson.expiryTimeMillis >= currentDate
                  ) {
                    var dateStart = JSON.parse(responseJson.startTimeMillis);
                    start_date = moment(dateStart).format("YYYY-MM-DD");
                    var dateStr = JSON.parse(responseJson.expiryTimeMillis);
                    validity_date = moment(dateStr).format("YYYY-MM-DD");
                    let pObject = {
                      productItem: {
                        product_id: finalPurchaseItem.productId,
                        transaction_id: responseJson.orderId,
                        original_transaction_id:
                          finalPurchaseItem.transactionId,
                        purchase_date: start_date,
                        expires_date: validity_date,
                      },
                      isAutoRenew:
                        responseJson.autoRenewing == false ? "no" : "yes",
                      activePlanData: "null",
                    };
                    if (this.is24HoursCompleted("subscription_four")) {
                      //console.log("pObject", JSON.stringify(pObject))
                      this._transactionLogApi(
                        "subscription_active_plan_in_store_not_in_db",
                        pObject
                      );
                      storeData(
                        "subscription_four",
                        moment().format("YYYY/MM/DD HH:mm:ss")
                      );
                    }
                  }
                }
              }
            }
          })
          .catch((error) => {
            if (
              androidReceipt != null &&
              androidReceipt.expiryTimeMillis >= currentDate
            ) {
              this._transactionLogApi(
                "subscription_valid_reciept_failed",
                finalPurchaseItem
              );
            }
            console.error(error);
          });
      }
    }
  }

  /* Api call for update in app purchase (recurring). */
  getUpdateInAppApi(
    subscriptionObj,
    transaction_id,
    auto_renew_status,
    validity_date,
    start_date,
    product_id,
    recurring_id,
    transactionReceipt
  ) {
    var parameters = {
      plan_id: subscriptionObj[0].id,
      amount: subscriptionObj[0].amount,
      transaction_id: transaction_id,
      recurring: auto_renew_status,
      validity_date: validity_date,
      start_date: start_date,
      product_id: product_id,
      recurring_id: recurring_id,
      payment_receipt: transactionReceipt,
      device_id: Constants.uniqueId,
      device_type: Platform.OS,
      app_version: Constants.appDisplayVersion,
    };

    //console.log("parameters", JSON.stringify(parameters))

    fetch(BaseUrl() + IN_APP_UPDATE_SUBSCRIPTION, {
      method: "POST",
      headers: {
        device_id: Constants.uniqueId,
        device_type: Platform.OS,
        accept: "application/json",
        "Content-Type": "application/json",
        "access-token": Constants.ACCESS_TOKEN,
        Authorization: `Bearer ${Constants.ACCESS_TOKEN}`,
      },
      body: JSON.stringify(parameters),
    })
      .then((response) => response.json())
      .then((responseJson) => {
        if (responseJson.success) {
          LocalStorage.saveUserActivePlan(responseJson.data);
          this._transactionLogApi(
            "subscription_update_in_app_data_in_db_success",
            parameters
          );
        }
      })
      .catch((error) => {
        console.error(error);
        this._transactionLogApi(
          "subscription_update_in_app_data_in_db_failed",
          parameters
        );
      });
  }

  //Log Api
  _transactionLogApi(request_type, request_json) {
    if (Constants.NETWORK_CHECK == true) {
      fetch(BaseUrl() + IN_APP_LOG, {
        method: "POST",
        headers: {
          "access-token": Constants.ACCESS_TOKEN,
          Accept: "application/json",
          "Content-Type": "application/json",
          Authorization: `Bearer ${Constants.ACCESS_TOKEN}`,
        },
        body: JSON.stringify({
          device_type: Platform.OS,
          app_version: Constants.appDisplayVersion,
          device_id: Constants.uniqueId,
          request_type: request_type,
          request_json: JSON.stringify(request_json),
        }),
      })
        .then((response) => response.json())
        .then((responseJson) => {})
        .catch((error) => {
          this._transactionLogApi("subscription_log_api_failed", request_json);
        });
    } else {
      setTimeout(() => {
        this.setState({
          infoAlert: true,
          infoAlertMsg: String.NO_INTERNET_CONN,
        });
      }, 500);
    }
  }

  /* initialize in app purchase */
  async startInAppConnection(items) {
    //For In_App purchase.
    const itemSkus = Platform.select({
      ios: [items.ios_plan_id, items.ios_rec_plan_id],
      android: [items.android_plan_id, items.android_rec_plan_id],
    });
    try {
      console.log("------->",products)
      const products = await getProducts({skus: itemSkus});
      const subscriptions = await getSubscriptions({skus: itemSkus});
      console.log("subscriptions------->",JSON.stringify(subscriptions,null,2))
      return {products, subscriptions};
    } catch (err) {
      console.warn(err);
    }
  }

  /* Go to account information screen */
  goToAccountInfo(recurringType) {
    // if (recurringType == 'yes') {
    // 	params = {
    // 		isFromSubs: true
    // 	}
    // 	this.props?.navigation.navigate('AccountInformation', params);
    // } else {
    this.backToScreen();
    //}
  }

  /* Set background images */
  setImage() {
    if (diff1x < diff2x) {
      if (diff1x < diff3x) {
        this.setState({ subscriptionImg: Images.subscription1x });
      } else {
        this.setState({ subscriptionImg: Images.subscription3x });
      }
    } else {
      if (diff2x < diff3x) {
        this.setState({ subscriptionImg: Images.subscription2x });
      } else {
        this.setState({ subscriptionImg: Images.subscription3x });
      }
    }
  }

  /* Call api for get subscription list. */
  callSubscriptionApi() {
    this.setState({ isLoading: true });
    let type = "general";
    var params = {};
    var url = BaseUrl() + SUBSCRIPTION_LIST;
    this.props?.subscriptionListApi((url += `?type=${type}`), params, true);
  }

  /* Clear user data after expire access token or inactive user. */
  clearSession() {
    Constants.sessionClear();
    // this.props?.navigation.dispatch(
    //   // (resetAction = StackActions.reset({
    //   //   index: 0,
    //   //   actions: [NavigationActions.navigate({ routeName: "Login" })],
    //   // }))
    //   StackActions.replace("Login", {})
    // );

    NavigationService.navigateToClearStack("Login");
  }

  /* Go to send gift subscription. */
  sendGiftScreen() {
    this.props?.navigation.navigate("GiftSubscription");
  }

  /* Api call for request stripe payment. */
  // requestStripePaymentApi(tokenId, planId, isRecurring) {
  // 	var params = {
  // 		"stripe_token": tokenId,
  // 		"plan_id": planId,
  // 		"recurring": (isRecurring == true) ? "yes" : "no"
  // 	}

  // 	if (Constants.NETWORK_CHECK == true) {
  // 		this.setState({ isLoading: true })
  // 		var HeaderWithAccessToken = {
  // 			"accept": "application/json",
  // 			"access-token": Constants.ACCESS_TOKEN,
  // 			'app-version': Constants.version,
  // 			'subscription': true
  // 		};
  // 		this.props?.stripePlanSubscriptionApi(BaseUrl + STRIPE_PLAN_SUBSCRIPTION, params, HeaderWithAccessToken);
  // 	} else {
  // 		setTimeout(() => {
  // 			this.setState({ infoAlert: true, infoAlertMsg: String.NO_INTERNET_CONN })
  // 		}, 500);
  // 	}
  // }

  async requestPayment(items, index, i) {
    console.log("---------------------->",JSON.stringify(items,null,2));
    this.setState({ isLoading: true });
    const skuObjs = await this.startInAppConnection(items);
    plan_amount = items.amount;
    // console.log("requestPayment ", plan_amount);
    console.log("items.android_rec_plan_id ", items.android_rec_plan_id);
    this.setState({
      skuObjs,
      selectionRow: index,
      selectionSection: i,
      item_id: items.id,
      planType: items.plan_type,
      // Plan_amount: items.amount,
      inApp_rec_Plan_id:
        Platform.OS == "ios"
          ? items.ios_rec_plan_id
          : items.android_rec_plan_id,
      inApp_non_rec_Plan_id:
        Platform.OS == "ios" ? items.ios_plan_id : items.android_plan_id,
      planFor: items.plan_for,
      isPaymentPopup: true,
      isLoading: false
    });
  }

  /* learn more */
  onClickLearnMore(title, description) {
    var param = {
      categoryName: title,
      description: description,
    };
    this.props?.navigation.navigate("AboutCategory", param);
  }

  /* Select payment type and payment process. */
  paymentProcess(paymentType, isRecurring) {
    // if (paymentType == 'stripe') {
    // 	return stripe
    // 		.paymentRequestWithCardForm()
    // 		.then(stripeTokenInfo => {
    // 			isPayment = 'yes'
    // 			// //console.log("Token created", stripeTokenInfo.tokenId);
    // 			this.requestStripePaymentApi(stripeTokenInfo.tokenId, this.state.item_id, isRecurring);
    // 		})
    // 		.catch(error => {
    // 			isPayment = 'no'
    // 			console.warn('Payment failed', { error });
    // 		});

    // } else {
    LocalStorage.getUserActivePlan((data) => {
      let jsonData = JSON.parse(data);
      console.log(" getUserActivePlan : ", jsonData);
      if (jsonData != null) {
        this.setState({
          infoAlert: true,
          infoAlertMsg: String.alreadySubscribedPlan,
        });
        plan_amount = null;
        // if (jsonData != null && jsonData.payment_type == "in-app" && jsonData.recurring == "yes") {
        // 	this.setState({ infoAlert: true, infoAlertMsg: String.Get_Plan_Again })
      } else {
        let currentDate = moment().format("x");

        if (
          Platform.OS == "ios" &&
          inAppStoreData != null &&
          inAppStoreData.expires_date_ms >= currentDate
        ) {
          this.setState({
            infoAlert: true,
            infoAlertMsg: String.alreadySubscribedPlanInApp,
          });
          plan_amount = null;
        } else if (
          inAppStoreData != null &&
          inAppStoreData.expiryTimeMillis >= currentDate
        ) {
          this.setState({
            infoAlert: true,
            infoAlertMsg: String.alreadySubscribedPlanInApp,
          });
          plan_amount = null;
        } else {
          const inApp_plan_id =
            isRecurring == true
              ? this.state.inApp_rec_Plan_id
              : this.state.inApp_non_rec_Plan_id;
          // if (Platform.OS == 'ios') {
          // 	this.buyProductMethod(inApp_plan_id, isRecurring);
          // } else {
          // 	if (isRecurring == true) {
          // 		this.buySubscriptionMethod(inApp_plan_id, isRecurring);
          // 	} else {
          // 		this.buyProductMethod(inApp_plan_id, isRecurring);
          // 	}
          // }
          console.log("inAppPlanid", inApp_plan_id, "isRecurring", isRecurring);
          this.buyProductMethod(inApp_plan_id, isRecurring);
        }
      }
      // if (jsonData == null) {
      // 	const inApp_plan_id = (isRecurring == true) ? this.state.inApp_rec_Plan_id : this.state.inApp_non_rec_Plan_id
      // 	this.buyProductMethod(inApp_plan_id, isRecurring);
      // }
      // if (plan_amount >= jsonData.amount) {
      // 	const inApp_plan_id = (isRecurring == true) ? this.state.inApp_rec_Plan_id : this.state.inApp_non_rec_Plan_id
      // 	this.buyProductMethod(inApp_plan_id, isRecurring);
      // } else {
      // 	this.setState({ infoAlert: true, infoAlertMsg: 'Plan should be higher from the current plan' })
      // }
    });
  }

  _getReceiptValidAndroidToken() {
    fetch(
      AndroidValidReceiptUrl +
        ClientId +
        "&client_secret=" +
        SecretKey +
        "&refresh_token=" +
        RefreshToken,
      {
        method: "POST",
      }
    )
      .then((response) => response.json())
      .then((responseJson) => {
        if (responseJson) {
          // console.log('_getReceiptValidAndroidToken ', responseJson.access_token)
          receiptAccessToken = responseJson.access_token;
        }
      })
      .catch((error) => {
        console.error(error);
      });
  }

  /* Buy product for in app purchase ios. */
  async buyProductMethod(inApp_plan_id, isRecurring) {
    try {
      this.setState({isLoading: true});
      isPurchaseRunning = true;
      const offerToken =
        this.state.skuObjs?.subscriptions?.[0]?.subscriptionOfferDetails?.[0]
          ?.offerToken;
      console.log('this.state.skuObjs-------------->', offerToken);
      let skuObj = {};
      if (Platform.OS === 'android') {
        skuObj.skus = [inApp_plan_id];
      } else {
        skuObj.sku = inApp_plan_id;
      }
      // requestPurchase({...skuObj}).then((data) => {
      requestPurchase({...skuObj})
        .then(data => {
          //for both for rec and non rec in ios and android.
          console.log("buyProductMethod", data);
          this.setState({isLoading: false});
        })
        .catch(err => {
          Alert.alert("Error",err?.message)
          this.setState({isLoading: false});
        });
      // requestPurchase({sku:inApp_plan_id}).then((data) => {
      //   //for both for rec and non rec in ios and android.
      //   console.log("buyProductMethod", data);
      //   this.setState({isLoading: false});
      // }).catch(err=>{
      //   Alert.alert("Error",err?.message)
      //   this.setState({isLoading: false});
      // });
    } catch (err) {
      console.log("BUY_ERROR", err);
      console.warn(err.code, err.message);
      isPurchaseRunning = false;
    }
  }

  /* Buy product for in app purchase android. */
  // async buySubscriptionMethod(inApp_plan_id, isRecurring) {
  // 	this._getReceiptValidAndroidToken();
  // 	try {
  // 		RNIap.requestPurchase(inApp_plan_id, false).then((data) => {
  // 		//console.log('requestSubscription ', data)
  // 			this._transactionLogApi("buy_product_transaction_data_success", data)
  // 		});
  // 	} catch (err) {
  // 		this._transactionLogApi("buy_product_transaction_data_failed", inApp_plan_id)
  // 	}
  // }

  /* Payment request for in app payment and api call. */
  requestInAppPurchase(isRecurring, purchase, receiptResult) {
    console.log("purchase :" + JSON.stringify(purchase));
    var transactionId = "";
    var start_date = "";
    var validity_date = "";
    var recurring_id = "";
    var product_id = "";

    if (isRecurring == true) {
      transactionId = purchase.transactionId;
      start_date = moment(JSON.parse(purchase.transactionDate)).format(
        "YYYY-MM-DD"
      );
      product_id = purchase.productId;
      if (this.state.planType == "monthly") {
        const d = new Date(start_date);
        const calculate_validate = new Date(
          d.getTime() + 30 * 24 * 60 * 60 * 1000
        );
        validity_date = moment(calculate_validate).format("YYYY-MM-DD");
      } else {
        const d = new Date(start_date);
        const calculate_validate = new Date(
          d.getTime() + 365 * 24 * 60 * 60 * 1000
        );
        validity_date = moment(calculate_validate).format("YYYY-MM-DD");
      }
      if (Platform.OS == "ios") {
        recurring_id = purchase.originalTransactionIdentifierIOS
          ? purchase.originalTransactionIdentifierIOS
          : purchase.transactionId;
      } else {
        recurring_id = purchase.transactionId;
      }
    } else {
      transactionId = purchase.transactionId;
      recurring_id = null;
      product_id = purchase.productId;
      if (this.state.planType == "monthly") {
        start_date = moment(JSON.parse(purchase.transactionDate)).format(
          "YYYY-MM-DD"
        );
        const d = new Date(start_date);
        const calculate_validate = new Date(
          d.getTime() + 30 * 24 * 60 * 60 * 1000
        );
        validity_date = moment(calculate_validate).format("YYYY-MM-DD");
      } else {
        start_date = moment(JSON.parse(purchase.transactionDate)).format(
          "YYYY-MM-DD"
        );
        const d = new Date(start_date);
        const calculate_validate = new Date(
          d.getTime() + 365 * 24 * 60 * 60 * 1000
        );
        validity_date = moment(calculate_validate).format("YYYY-MM-DD");
      }
    }

    var params = {
      plan_id: this.state.item_id,
      amount: plan_amount,
      start_date: start_date,
      validity_date: validity_date,
      transaction_id: transactionId,
      recurring: isRecurring == true ? "yes" : "no",
      product_id: product_id,
      recurring_id: recurring_id,
      payment_receipt: purchase.transactionReceipt,
      device_id: Constants.uniqueId,
      device_type: Platform.OS,
      app_version: Constants.appDisplayVersion,
    };

    if (Constants.NETWORK_CHECK == true) {
      this.setState({ isLoading: true });
      isPayment_In_app = "yes";

      console.log("params get subscription", JSON.stringify(params));
      this.props?.requestInAppPurchaseSubscriptionApi(
        BaseUrl() + PURCHASE_IN_APP_SUBSCRIPTION,
        params
      );
    } else {
      setTimeout(() => {
        this.setState({
          infoAlert: true,
          infoAlertMsg: String.NO_INTERNET_CONN,
        });
      }, 500);
    }
  }

  /* Close payment popup. */
  _onClosePopup = (isComplete) => {
    this.setState({skuObjs:null, isPaymentPopup: false });
  };

  /* Callback for payment popup. */
  _paymentCallback = (paymentType, isRecurring) => {
    this.setState({ isPaymentPopup: false, is_recurring: isRecurring });
    console.log("isRecurring", isRecurring);
    setTimeout(() => {
      this.paymentProcess(paymentType, isRecurring);
    }, 500);
  };

  /* Close info popup. */
  _onCloseWarnInfo = (isComplete) => {
    this.setState({ infoAlert: false });
    if (isComplete == "401") {
      this.clearSession();
    } else if (isComplete == "paymentSuccess") {
      isPaySuccess = "yes";
      this.goToAccountInfo(this.state.isRecurring);
    } else if (isComplete == "updateApp") {
      Constants.appStorePlayStoreUrl();
    }
  };

  isPaymentRunning = (items, index, i) => {
    if (Platform.OS == "ios") {
      if (isPurchaseRunning) {
        Toast.show(String.paymentRequestProcess);
      } else {
        this.requestPayment(items, index, i);
      }
    } else {
      this.requestPayment(items, index, i);
    }
  };

  goToDonateScreen() {
    NavigationService.navigate("Donation", {
      returnData: this.returnData.bind(this),
      key: "Subscription",
    });
  }

  returnData(params) {}

  render() {
    console.log("------------->",subscriptionListArr.map(item=>item.plan_detail))
    return (
      <ImageBackground
        style={Styles.container}
        source={this.state.subscriptionImg}
        defaultSource={Images.subscription1x}
      >
        {this.state.isPaymentPopup == true ? (
          <PaymentPopup
            isOpen={this.state.isPaymentPopup}
            onClosePopup={this._onClosePopup}
            paymentCallback={this._paymentCallback}
            planFor={this.state.planFor}
          />
        ) : null}
        {/* <Loader visible={this.state.isLoading} />  */}
        {this.state.isLoading ? (
          <View
            style={{
              position: "absolute",
              justifyContent: "center",
              alignItems: "center",
              left: 0,
              right: 0,
              top: 0,
              bottom: 0,
              zIndex: 10
            }}
          >
            <ActivityIndicator size="large" />
          </View>
        ) : null}

        {/*====== Info popup. =======*/}
        {this.state.infoAlert ? (
          <WarningInfo
            loading={this.state.infoAlert}
            onCloseWarnInfo={this._onCloseWarnInfo}
            message={this.state.infoAlertMsg}
            infoKey={this.state.infoKey}
          />
        ) : null}

        {/*======== Header view. =======*/}
        <View style={Styles.headerView}>
          <View style={Styles.innerHeader}>
            {this.props?.route.params != null ||
            this.props?.route.params != undefined ? (
              <TouchableOpacity
                style={Styles.menuTouch}
                onPress={() => this.backToScreen()}
              >
                <Image source={Images.back_white} />
              </TouchableOpacity>
            ) : null}
            <Text
              style={[
                Styles.headerTxt,
                {
                  marginLeft:
                    this.props?.route.params != null ||
                    this.props?.route.params != undefined
                      ? null
                      : 60,
                },
              ]}
            >
              Subscription
            </Text>
          </View>
        </View>

        {this.state.isDataAvailable ? (
          <ScrollView>
            {/*======== Subscription list =======*/}
            <View style={{ margin: 20, flex: 1 }}>
              {Object.keys(subscriptionListArr).map((key, i) => (
                <View>
                  {subscriptionListArr[key].plan_detail.length == 0 ? null : (
                    <View
                      style={{
                        flexDirection: "row",
                        marginTop: i == 0 ? 5 : 25,
                        justifyContent: "space-between",
                        alignItems: "center",
                      }}
                    >
                      <Text
                        style={[Styles.basicTxt, { flex: i == 1 ? 0.8 : 1 }]}
                      >
                        {subscriptionListArr[key].plan_name.toUpperCase()}
                      </Text>
                      {i == 1 ? (
                        <TouchableOpacity
                          onPress={() =>
                            this.onClickLearnMore(
                              subscriptionListArr[key].plan_name,
                              subscriptionListArr[key].description
                            )
                          }
                        >
                          <Text style={[Styles.learnMoreTxt, { flex: 0.2 }]}>
                            LEARN MORE >
                          </Text>
                        </TouchableOpacity>
                      ) : null}
                    </View>
                  )}

                  {subscriptionListArr[key].plan_detail.map((items, index) => (
                    <TouchableOpacity
                      onPress={() =>
                        items.status == "inactive"
                          ? Toast.show("This plan is not available currently.")
                          : this.isPaymentRunning(items, index, i)
                      }
                    >
                      <View
                        style={[
                          Styles.basicView,
                          {
                            backgroundColor:
                              this.state.selectionSection == i &&
                              this.state.selectionRow == index
                                ? Colors.SECTION_VIEW
                                : Colors.LIGHT_BLUE5,
                            borderWidth:
                              this.state.selectionSection == i &&
                              this.state.selectionRow == index
                                ? 2
                                : 0,
                            borderColor:
                              this.state.selectionSection == i &&
                              this.state.selectionRow == index
                                ? Colors.WHITE
                                : null,
                          },
                        ]}
                      >
                        <View style={{ flex: 1, justifyContent: "flex-end" }}>
                          <Text
                            style={[
                              Styles.basicMonth,
                              {
                                color:
                                  items.status == "inactive"
                                    ? Colors.INACTIVE_MEDIA
                                    : Colors.WHITE,
                              },
                            ]}
                          >
                            {items.plan_type.toUpperCase()}
                          </Text>
                        </View>

                        <View
                          style={{
                            justifyContent: "flex-end",
                            marginRight: 10,
                          }}
                        >
                          {items.plan_type == "yearly" ? (
                            <View style={Styles.benefactorAmountView}>
                              <Text
                                style={[
                                  Styles.dollarTxt,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                    marginTop: -5,
                                  },
                                ]}
                              >
                                $
                              </Text>
                              <Text
                                style={[
                                  Styles.benefactorAmount,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                    marginTop: 0,
                                  },
                                ]}
                              >
                                {items.amount}
                              </Text>
                              <Text
                                style={[
                                  Styles.yearlyTxt,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                  },
                                ]}
                              >
                                {" "}
                                / year
                              </Text>
                            </View>
                          ) : null}

                          <View style={[Styles.benefactorAmountView]}>
                            {items.plan_type == "monthly" ? (
                              <Text
                                style={[
                                  Styles.dollarTxt,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                    marginTop: 5,
                                  },
                                ]}
                              >
                                $
                              </Text>
                            ) : null}
                            {items.plan_type == "monthly" ? (
                              <Text
                                style={[
                                  Styles.benefactorAmount,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                  },
                                ]}
                              >
                                {items.amount}
                              </Text>
                            ) : (
                              <Text
                                style={[
                                  Styles.yearlyToMonthlyTxt,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                  },
                                ]}
                              >
                                {"(12 months at $" +
                                  Number(items.amount / 12).toFixed(2) +
                                  "/mo)"}
                              </Text>
                            )}

                            {items.plan_type == "monthly" ? (
                              <Text
                                style={[
                                  Styles.benefactorBottomAmount,
                                  {
                                    color:
                                      items.status == "inactive"
                                        ? Colors.INACTIVE_MEDIA
                                        : Colors.WHITE,
                                  },
                                ]}
                              >
                                /MO
                              </Text>
                            ) : null}
                          </View>
                        </View>
                      </View>
                    </TouchableOpacity>
                  ))}

                  {/* {subscriptionListArr[key].plan_detail.map((items) => (
										(items.plan_type == "yearly") ? <Text style={{ color: Colors.WHITE, fontFamily: Fonts.type.Regular, fontSize: Fonts.size.medium, marginTop: 10 }}>${items.amount} Billed Annually</Text> : null
									))} */}
                </View>
              ))}
            </View>

            <Text style={Styles.donationTxt}>DONATION</Text>
            <TouchableOpacity
              style={Styles.sendGiftView}
              onPress={() => this.goToDonateScreen()}
            >
              <Text style={Styles.donateTxt}>Donate</Text>
            </TouchableOpacity>

            {/*======== Sent a gift. =======*/}
            {/* <View style={Styles.sendGiftView}>
              <TouchableOpacity onPress={() => Toast.show(String.comingSoon)}>
                <Text
                  style={{
                    color: Colors.WHITE,
                    fontFamily: Fonts.type.Light,
                    fontSize: Fonts.size.xLarge,
                  }}
                >
                  {String.sendGift}
                </Text>
                <Text
                  style={{
                    color: Colors.WHITE,
                    fontFamily: Fonts.type.Regular,
                    fontSize: Fonts.size.large,
                  }}
                >
                  {String.subsToFriendFamily}
                </Text>
              </TouchableOpacity>
            </View> */}

            <Text style={Styles.cancelSubTxt}>{String.youCanCancelSubs}</Text>
          </ScrollView>
        ) : (
          <View style={Styles.notFoundView}>
            <Text style={Styles.notFoundTxt}>
              {this.state.showText == false ? String.NoPlans : null}
            </Text>
          </View>
        )}
      </ImageBackground>
    );
  }
}

//make this component available to the app
function mapStateToProps(state, props) {
  return {
    data: state.SubscriptionReducer.data,
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(Actions, dispatch);
}

//Connect everything
export default connect(mapStateToProps, mapDispatchToProps)(Subscription);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant