Allow sub upgrades/downgrades on iOS (#14303)
* Allow sub upgrades/downgrades on iOS * fix check * fix(lint): line length * fix(typo): customER * fix tests * Implement correct handling for when subs are up/downgraded * fix lint errors * fix test Co-authored-by: SabreCat <sabe@habitica.com> Co-authored-by: Sabe Jones <sabrecat@gmail.com>
This commit is contained in:
@@ -106,10 +106,6 @@ api.verifyGemPurchase = async function verifyGemPurchase (options) {
|
||||
};
|
||||
|
||||
api.subscribe = async function subscribe (sku, user, receipt, headers, nextPaymentProcessing) {
|
||||
if (user && user.isSubscribed()) {
|
||||
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
|
||||
}
|
||||
|
||||
if (!sku) throw new BadRequest(shared.i18n.t('missingSubscriptionCode'));
|
||||
|
||||
let subCode;
|
||||
@@ -140,33 +136,49 @@ api.subscribe = async function subscribe (sku, user, receipt, headers, nextPayme
|
||||
throw new NotAuthorized(api.constants.RESPONSE_NO_ITEM_PURCHASED);
|
||||
}
|
||||
|
||||
let transactionId;
|
||||
let originalTransactionId;
|
||||
let newTransactionId;
|
||||
|
||||
for (const purchaseData of purchaseDataList) {
|
||||
const dateTerminated = new Date(Number(purchaseData.expirationDate));
|
||||
if (purchaseData.productId === sku && dateTerminated > new Date()) {
|
||||
transactionId = purchaseData.transactionId;
|
||||
originalTransactionId = purchaseData.originalTransactionId;
|
||||
newTransactionId = purchaseData.transactionId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (transactionId) {
|
||||
if (originalTransactionId) {
|
||||
let existingSub;
|
||||
if (user && user.isSubscribed()) {
|
||||
if (user.purchased.plan.customerId !== originalTransactionId) {
|
||||
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
|
||||
}
|
||||
existingSub = shared.content.subscriptionBlocks[user.purchased.plan.planId];
|
||||
}
|
||||
const existingUser = await User.findOne({
|
||||
'purchased.plan.customerId': transactionId,
|
||||
'purchased.plan.customerId': originalTransactionId,
|
||||
}).exec();
|
||||
if (existingUser) throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
|
||||
if (existingUser
|
||||
&& (originalTransactionId === newTransactionId || existingUser._id !== user._id)) {
|
||||
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
|
||||
}
|
||||
|
||||
nextPaymentProcessing = nextPaymentProcessing || moment.utc().add({ days: 2 }); // eslint-disable-line max-len, no-param-reassign
|
||||
|
||||
await payments.createSubscription({
|
||||
const data = {
|
||||
user,
|
||||
customerId: transactionId,
|
||||
customerId: originalTransactionId,
|
||||
paymentMethod: this.constants.PAYMENT_METHOD_APPLE,
|
||||
sub,
|
||||
headers,
|
||||
nextPaymentProcessing,
|
||||
additionalData: receipt,
|
||||
});
|
||||
};
|
||||
if (existingSub) {
|
||||
data.updatedFrom = existingSub;
|
||||
}
|
||||
await payments.createSubscription(data);
|
||||
} else {
|
||||
throw new NotAuthorized(api.constants.RESPONSE_INVALID_RECEIPT);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,15 @@ async function prepareSubscriptionValues (data) {
|
||||
? data.gift.subscription.key
|
||||
: data.sub.key];
|
||||
const autoRenews = data.autoRenews !== undefined ? data.autoRenews : true;
|
||||
const months = Number(block.months);
|
||||
const updatedFrom = data.updatedFrom
|
||||
? shared.content.subscriptionBlocks[data.updatedFrom.key]
|
||||
: undefined;
|
||||
let months;
|
||||
if (updatedFrom && Number(updatedFrom.months) !== 1) {
|
||||
months = Math.max(0, Number(block.months) - Number(updatedFrom.months));
|
||||
} else {
|
||||
months = Number(block.months);
|
||||
}
|
||||
const today = new Date();
|
||||
let group;
|
||||
let groupId;
|
||||
|
||||
Reference in New Issue
Block a user