fix issue where subs would be applied multiple times

This commit is contained in:
Phillip Thelen
2022-11-02 16:36:09 +01:00
committed by Phillip Thelen
parent cf75d941fa
commit 0dd25b6431
2 changed files with 68 additions and 18 deletions

View File

@@ -415,26 +415,72 @@ describe('Apple Payments', () => {
} }
}); });
it('errors when a user is using the same subscription', async () => { describe('does not apply multiple times', async () => {
payments.createSubscription.restore(); it('errors when a user is using the same subscription', async () => {
iap.getPurchaseData.restore(); payments.createSubscription.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData') iap.getPurchaseData.restore();
.returns([{ iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
expirationDate: moment.utc().add({ day: 1 }).toDate(), .returns([{
productId: sku, expirationDate: moment.utc().add({ day: 1 }).toDate(),
transactionId: token, productId: sku,
originalTransactionId: token, transactionId: token,
}]); originalTransactionId: token,
}]);
await applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing);
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
await applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing); it('errors when a user is using a rebill of the same subscription', async () => {
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
productId: sku,
transactionId: token + 'renew',
originalTransactionId: token,
}]);
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing)) await applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing);
.to.eventually.be.rejected.and.to.eql({
httpCode: 401, await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
name: 'NotAuthorized', .to.eventually.be.rejected.and.to.eql({
message: applePayments.constants.RESPONSE_ALREADY_USED, httpCode: 401,
}); name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
it('errors when a different user is using the subscription', async () => {
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
productId: sku,
transactionId: token,
originalTransactionId: token,
}]);
await applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing);
const secondUser = new User();
await expect(applePayments.subscribe(sku, secondUser, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
}); });
}); });
describe('cancelSubscribe ', () => { describe('cancelSubscribe ', () => {

View File

@@ -124,12 +124,16 @@ api.subscribe = async function subscribe (sku, user, receipt, headers, nextPayme
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED); throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
} }
existingSub = shared.content.subscriptionBlocks[user.purchased.plan.planId]; existingSub = shared.content.subscriptionBlocks[user.purchased.plan.planId];
if (existingSub === sub) {
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
}
} }
const existingUser = await User.findOne({ const existingUser = await User.findOne({
'purchased.plan.customerId': originalTransactionId, 'purchased.plan.customerId': originalTransactionId,
}).exec(); }).exec();
if (existingUser if (existingUser
&& (originalTransactionId === newTransactionId || existingUser._id !== user._id)) { && (originalTransactionId === newTransactionId
|| existingUser._id !== user._id)) {
throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED); throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED);
} }