Skip to content

Commit df8a38c

Browse files
authored
🐛 - Fix Android tip jar refunds (#341)
Tipping on Android were always refunded after a few days. The reason is that we didn't flush the purchase ("acknowledge" it to the play store): > your app must then acknowledge the purchase. This acknowledgement communicates to Google Play that you have granted entitlement for the purchase. We had the flushing mechanism set in the `TipJarScreen`, but putting it there will possibly hav the flushing effect not run (if the user has exit the screen before it ran, or for whatever reason else. Putting in the main `App` component will ensure it'll be flushed, either in the current session or in the next app relaunch.
1 parent a8a8e88 commit df8a38c

File tree

9 files changed

+44
-32
lines changed

9 files changed

+44
-32
lines changed

android/app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ android {
120120
applicationId "com.betterrail"
121121
minSdkVersion rootProject.ext.minSdkVersion
122122
targetSdkVersion rootProject.ext.targetSdkVersion
123-
versionCode 75
123+
versionCode 78
124124
versionName "2.2.2"
125125
missingDimensionStrategy "store", "play"
126126
}

app/app.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import { RootStore, RootStoreProvider, setupRootStore } from "./models"
3535
import { ToggleStorybook } from "../storybook/toggle-storybook"
3636
import { setInitialLanguage, setUserLanguage } from "./i18n/i18n"
3737
import "react-native-console-time-polyfill"
38-
import { withIAPContext } from "react-native-iap"
38+
import { useIAP, initConnection, finishTransaction, getAvailablePurchases, withIAPContext } from "react-native-iap"
3939
import PushNotification from "react-native-push-notification"
4040

4141
// Disable tracking in development environment
@@ -51,7 +51,6 @@ import { enableScreens } from "react-native-screens"
5151
import { canRunLiveActivities, monitorLiveActivities } from "./utils/ios-helpers"
5252
import { useDeepLinking } from "./hooks/use-deep-linking"
5353
import { openActiveRide } from "./utils/helpers/ride-helpers"
54-
import { useStations } from "./data/stations"
5554
enableScreens()
5655

5756
export const queryClient = new QueryClient()
@@ -65,7 +64,7 @@ function App() {
6564
const [rootStore, setRootStore] = useState<RootStore | undefined>(undefined)
6665
const [localeReady, setLocaleReady] = useState(false)
6766
const appState = useRef(AppState.currentState)
68-
const stations = useStations()
67+
const { currentPurchase } = useIAP()
6968

7069
useDeepLinking(rootStore, navigationRef)
7170

@@ -139,6 +138,29 @@ function App() {
139138
})
140139
}, [])
141140

141+
useEffect(() => {
142+
// load products and flush available purchases for the tip jar
143+
// see: https://github.com/dooboolab-community/react-native-iap/issues/126
144+
// and: https://react-native-iap.dooboolab.com/docs/guides/purchases
145+
const flushAvailablePurchases = async () => {
146+
try {
147+
await initConnection()
148+
const availablePurchases = await getAvailablePurchases()
149+
150+
availablePurchases.forEach((purchase) => {
151+
finishTransaction({ purchase, isConsumable: true })
152+
})
153+
} catch (error) {
154+
console.error("Failed to connect to IAP and finish all available transactions", error)
155+
}
156+
}
157+
158+
// to avoid prompting for login during development, only flush purchases in production
159+
if (!__DEV__) {
160+
flushAvailablePurchases()
161+
}
162+
}, [currentPurchase])
163+
142164
// Before we show the app, we have to wait for our state to be ready.
143165
// In the meantime, don't render anything. This will be the background
144166
// color set in native by rootView's background color. You can replace

app/screens/settings/settings-tip-jar-screen.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useEffect, useState } from "react"
22
import { observer } from "mobx-react-lite"
33
import { View, ViewStyle, TextStyle, Platform, ActivityIndicator } from "react-native"
4-
import { ProductPurchase, Purchase, RequestPurchase, useIAP } from "react-native-iap"
4+
import { ProductPurchase, RequestPurchase, useIAP } from "react-native-iap"
55
import { Screen, Text } from "../../components"
66
import { color, isDarkMode, spacing } from "../../theme"
77
import { TouchableOpacity } from "react-native-gesture-handler"
@@ -83,10 +83,10 @@ const TIP_AMOUNT: TextStyle = {
8383

8484
const TOTAL_TIPS: TextStyle = { textAlign: "center", marginTop: spacing[4] }
8585

86-
const PRODUCT_IDS = ["better_rail_tip_1", "better_rail_tip_2", "better_rail_tip_3", "better_rail_tip_4"]
87-
8886
const installSource = getInstallerPackageNameSync()
8987

88+
const PRODUCT_IDS = ["better_rail_tip_1", "better_rail_tip_2", "better_rail_tip_3", "better_rail_tip_4"]
89+
9090
export const TipJarScreen = observer(function TipJarScreen() {
9191
const [isLoading, setIsLoading] = useState(false)
9292
const [thanksModalVisible, setModalVisible] = useState(false)
@@ -97,18 +97,8 @@ export const TipJarScreen = observer(function TipJarScreen() {
9797
useIAP()
9898

9999
useEffect(() => {
100-
// see: https://github.com/dooboolab-community/react-native-iap/issues/126
101-
const flushAvailablePurchases = async () => {
102-
await getAvailablePurchases()
103-
availablePurchases.forEach(async (purchase) => {
104-
await finishTransaction({ purchase, isConsumable: true })
105-
})
106-
}
107-
108100
if (connected) {
109101
getProducts({ skus: PRODUCT_IDS })
110-
111-
flushAvailablePurchases()
112102
}
113103
}, [connected, getProducts])
114104

ios/BetterRail.xcodeproj/project.pbxproj

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@
11561156
CLANG_ENABLE_MODULES = YES;
11571157
CODE_SIGN_ENTITLEMENTS = BetterRail/BetterRailDebug.entitlements;
11581158
CODE_SIGN_STYLE = Manual;
1159-
CURRENT_PROJECT_VERSION = 1;
1159+
CURRENT_PROJECT_VERSION = 3;
11601160
DEVELOPMENT_TEAM = "";
11611161
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;
11621162
ENABLE_BITCODE = NO;
@@ -1196,7 +1196,7 @@
11961196
CODE_SIGN_IDENTITY = "Apple Development";
11971197
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
11981198
CODE_SIGN_STYLE = Manual;
1199-
CURRENT_PROJECT_VERSION = 1;
1199+
CURRENT_PROJECT_VERSION = 3;
12001200
DEVELOPMENT_TEAM = "";
12011201
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;
12021202
INFOPLIST_FILE = BetterRail/Info.plist;
@@ -1359,7 +1359,7 @@
13591359
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
13601360
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
13611361
CODE_SIGN_STYLE = Manual;
1362-
CURRENT_PROJECT_VERSION = 1;
1362+
CURRENT_PROJECT_VERSION = 3;
13631363
DEBUG_INFORMATION_FORMAT = dwarf;
13641364
DEVELOPMENT_TEAM = "";
13651365
"DEVELOPMENT_TEAM[sdk=watchos*]" = UE6BVYPPFX;
@@ -1401,7 +1401,7 @@
14011401
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Distribution";
14021402
CODE_SIGN_STYLE = Manual;
14031403
COPY_PHASE_STRIP = NO;
1404-
CURRENT_PROJECT_VERSION = 1;
1404+
CURRENT_PROJECT_VERSION = 3;
14051405
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
14061406
DEVELOPMENT_TEAM = "";
14071407
"DEVELOPMENT_TEAM[sdk=watchos*]" = UE6BVYPPFX;
@@ -1437,7 +1437,7 @@
14371437
CODE_SIGN_ENTITLEMENTS = "WatchBetterRail Extension/WatchBetterRail Extension.entitlements";
14381438
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer";
14391439
CODE_SIGN_STYLE = Manual;
1440-
CURRENT_PROJECT_VERSION = 1;
1440+
CURRENT_PROJECT_VERSION = 3;
14411441
DEBUG_INFORMATION_FORMAT = dwarf;
14421442
DEVELOPMENT_TEAM = "";
14431443
"DEVELOPMENT_TEAM[sdk=watchos*]" = UE6BVYPPFX;
@@ -1478,7 +1478,7 @@
14781478
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Distribution";
14791479
CODE_SIGN_STYLE = Manual;
14801480
COPY_PHASE_STRIP = NO;
1481-
CURRENT_PROJECT_VERSION = 1;
1481+
CURRENT_PROJECT_VERSION = 3;
14821482
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
14831483
DEVELOPMENT_TEAM = "";
14841484
"DEVELOPMENT_TEAM[sdk=watchos*]" = UE6BVYPPFX;
@@ -1516,7 +1516,7 @@
15161516
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
15171517
CODE_SIGN_ENTITLEMENTS = BetterRailWidgetExtensionDebug.entitlements;
15181518
CODE_SIGN_STYLE = Manual;
1519-
CURRENT_PROJECT_VERSION = 1;
1519+
CURRENT_PROJECT_VERSION = 3;
15201520
DEBUG_INFORMATION_FORMAT = dwarf;
15211521
DEVELOPMENT_TEAM = "";
15221522
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;
@@ -1557,7 +1557,7 @@
15571557
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
15581558
CODE_SIGN_STYLE = Manual;
15591559
COPY_PHASE_STRIP = NO;
1560-
CURRENT_PROJECT_VERSION = 1;
1560+
CURRENT_PROJECT_VERSION = 3;
15611561
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
15621562
DEVELOPMENT_TEAM = "";
15631563
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;
@@ -1590,7 +1590,7 @@
15901590
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
15911591
CODE_SIGN_ENTITLEMENTS = StationIntent/StationIntentDebug.entitlements;
15921592
CODE_SIGN_STYLE = Manual;
1593-
CURRENT_PROJECT_VERSION = 1;
1593+
CURRENT_PROJECT_VERSION = 3;
15941594
DEBUG_INFORMATION_FORMAT = dwarf;
15951595
DEVELOPMENT_TEAM = "";
15961596
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;
@@ -1629,7 +1629,7 @@
16291629
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
16301630
CODE_SIGN_STYLE = Manual;
16311631
COPY_PHASE_STRIP = NO;
1632-
CURRENT_PROJECT_VERSION = 1;
1632+
CURRENT_PROJECT_VERSION = 3;
16331633
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
16341634
DEVELOPMENT_TEAM = "";
16351635
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UE6BVYPPFX;

ios/BetterRail/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<key>CFBundleSignature</key>
2424
<string>????</string>
2525
<key>CFBundleVersion</key>
26-
<string>1</string>
26+
<string>3</string>
2727
<key>ITSAppUsesNonExemptEncryption</key>
2828
<false/>
2929
<key>LSApplicationQueriesSchemes</key>

ios/BetterRailWidget/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>$(CURRENT_PROJECT_VERSION)</string>
22+
<string>3</string>
2323
<key>NSExtension</key>
2424
<dict>
2525
<key>NSExtensionPointIdentifier</key>

ios/StationIntent/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>$(CURRENT_PROJECT_VERSION)</string>
22+
<string>3</string>
2323
<key>NSExtension</key>
2424
<dict>
2525
<key>NSExtensionAttributes</key>

ios/WatchBetterRail Extension/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>$(CURRENT_PROJECT_VERSION)</string>
22+
<string>3</string>
2323
<key>CLKComplicationPrincipalClass</key>
2424
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
2525
<key>NSExtension</key>

ios/WatchBetterRail/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>$(CURRENT_PROJECT_VERSION)</string>
22+
<string>3</string>
2323
<key>UISupportedInterfaceOrientations</key>
2424
<array>
2525
<string>UIInterfaceOrientationPortrait</string>

0 commit comments

Comments
 (0)