Skip to content

Commit 966fc3b

Browse files
committed
fix: upgrade existing Play subscription with proration instead of stacking a new purchase
1 parent 1377330 commit 966fc3b

3 files changed

Lines changed: 21 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 17)
44
set(CMAKE_CXX_STANDARD_REQUIRED ON)
55

66
set(PROJECT AmneziaVPN)
7-
set(AMNEZIAVPN_VERSION 5.0.0.6)
7+
set(AMNEZIAVPN_VERSION 5.0.1.2)
88

99
set(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP ON CACHE BOOL "" FORCE)
1010
set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES

client/android/billing/src/main/kotlin/BillingProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ class BillingProvider(context: Context) : AutoCloseable {
264264
val subscriptionUpdateParams = oldPurchaseToken?.let {
265265
BillingFlowParams.SubscriptionUpdateParams.newBuilder()
266266
.setOldPurchaseToken(oldPurchaseToken)
267-
.setSubscriptionReplacementMode(ReplacementMode.WITHOUT_PRORATION)
267+
.setSubscriptionReplacementMode(ReplacementMode.CHARGE_PRORATED_PRICE)
268268
.build()
269269
}
270270

client/core/controllers/api/subscriptionController.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,22 @@ ErrorCode SubscriptionController::processPlayMarketPurchase(const QString &userC
981981
QObject::connect(&watcher, &QFutureWatcher<QPair<bool, QString>>::finished, &waitLoop, &QEventLoop::quit);
982982

983983
QFuture<QPair<bool, QString>> future = QtConcurrent::run([androidController, productId]() {
984+
// If the user already has an active "premium" subscription, upgrade/replace it with proration
985+
// instead of stacking a second, independent purchase that Google Play would just queue behind it.
986+
QString oldPurchaseToken;
987+
QJsonObject existingPurchasesResult = androidController->queryPurchases();
988+
if (existingPurchasesResult.value("responseCode").toInt(-1) == 0) {
989+
const QJsonArray existingPurchases = existingPurchasesResult.value("purchases").toArray();
990+
for (const QJsonValue &purchaseValue : existingPurchases) {
991+
const QJsonObject existingPurchase = purchaseValue.toObject();
992+
if (existingPurchase.value("purchaseState").toInt(-1) == 1) { // PURCHASED
993+
oldPurchaseToken = existingPurchase.value("purchaseToken").toString();
994+
qInfo() << "[Billing] Found existing active subscription, will upgrade instead of purchasing a new one";
995+
break;
996+
}
997+
}
998+
}
999+
9841000
QJsonObject plansResult = androidController->getSubscriptionPlans();
9851001
int responseCode = plansResult.value("responseCode").toInt(-1);
9861002
if (responseCode != 0) {
@@ -1016,7 +1032,9 @@ ErrorCode SubscriptionController::processPlayMarketPurchase(const QString &userC
10161032
qWarning() << "[Billing] No offer token found for basePlanId:" << productId;
10171033
return qMakePair(false, QString());
10181034
}
1019-
QJsonObject purchaseResult = androidController->purchaseSubscription(offerToken);
1035+
QJsonObject purchaseResult = oldPurchaseToken.isEmpty()
1036+
? androidController->purchaseSubscription(offerToken)
1037+
: androidController->upgradeSubscription(offerToken, oldPurchaseToken);
10201038
responseCode = purchaseResult.value("responseCode").toInt(-1);
10211039
if (responseCode != 0) {
10221040
qWarning() << "[Billing] Purchase failed, responseCode:" << responseCode;

0 commit comments

Comments
 (0)