react-native-iap
react-native-iap copied to clipboard
[Android] offerToken is required for constructing ProductDetailsParams
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
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:
- Initialize package using initConnection function
- Fetch skus
- call the requestPurchase function and provide skus in it
- 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);