mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Support subscription payment through Google Play Store (#8437)
* Support subscription payment through Google Play Store * minor fixes to iap subscriptions * Support subscription payment through Google Play Store * minor fixes to iap subscriptions * revert change to test * add unit tests for google payments * add integration tests for google payments * change config formatting for play api * fix typo in file name * fix typo in example config * Improve google payment tests * fix linter errors
This commit is contained in:
committed by
Sabe Jones
parent
a002bc5e20
commit
4d0295a60d
@@ -5,10 +5,11 @@ import {
|
||||
import iap from '../../../libs/inAppPurchases';
|
||||
import payments from '../../../libs/payments';
|
||||
import {
|
||||
NotAuthorized,
|
||||
BadRequest,
|
||||
} from '../../../libs/errors';
|
||||
import { model as IapPurchaseReceipt } from '../../../models/iapPurchaseReceipt';
|
||||
import logger from '../../../libs/logger';
|
||||
import googlePayments from '../../../libs/googlePayments';
|
||||
|
||||
let api = {};
|
||||
|
||||
@@ -28,63 +29,56 @@ api.iapAndroidVerify = {
|
||||
let user = res.locals.user;
|
||||
let iapBody = req.body;
|
||||
|
||||
await iap.setup();
|
||||
|
||||
let testObj = {
|
||||
data: iapBody.transaction.receipt,
|
||||
signature: iapBody.transaction.signature,
|
||||
};
|
||||
|
||||
let googleRes = await iap.validate(iap.GOOGLE, testObj);
|
||||
|
||||
let isValidated = iap.isValidated(googleRes);
|
||||
if (!isValidated) throw new NotAuthorized('INVALID_RECEIPT');
|
||||
|
||||
let receiptObj = JSON.parse(testObj.data); // passed as a string
|
||||
let token = receiptObj.token || receiptObj.purchaseToken;
|
||||
|
||||
let existingReceipt = await IapPurchaseReceipt.findOne({
|
||||
_id: token,
|
||||
}).exec();
|
||||
if (existingReceipt) throw new NotAuthorized('RECEIPT_ALREADY_USED');
|
||||
|
||||
await IapPurchaseReceipt.create({
|
||||
_id: token,
|
||||
consumed: true,
|
||||
userId: user._id,
|
||||
});
|
||||
|
||||
let amount;
|
||||
|
||||
switch (receiptObj.productId) {
|
||||
case 'com.habitrpg.android.habitica.iap.4gems':
|
||||
amount = 1;
|
||||
break;
|
||||
case 'com.habitrpg.android.habitica.iap.20.gems':
|
||||
case 'com.habitrpg.android.habitica.iap.21gems':
|
||||
amount = 5.25;
|
||||
break;
|
||||
case 'com.habitrpg.android.habitica.iap.42gems':
|
||||
amount = 10.5;
|
||||
break;
|
||||
case 'com.habitrpg.android.habitica.iap.84gems':
|
||||
amount = 21;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!amount) throw new Error('INVALID_ITEM_PURCHASED');
|
||||
|
||||
await payments.buyGems({
|
||||
user,
|
||||
paymentMethod: 'IAP GooglePlay',
|
||||
amount,
|
||||
headers: req.headers,
|
||||
});
|
||||
let googleRes = await googlePayments.verifyGemPurchase(user, iapBody.transaction.receipt, iapBody.transaction.signature, req.headers);
|
||||
|
||||
res.respond(200, googleRes);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @apiIgnore Payments are considered part of the private API
|
||||
* @api {post} /iap/android/subscription Android Subscribe
|
||||
* @apiName IapAndroidSubscribe
|
||||
* @apiGroup Payments
|
||||
**/
|
||||
api.iapSubscriptionAndroid = {
|
||||
method: 'POST',
|
||||
url: '/iap/android/subscribe',
|
||||
middlewares: [authWithUrl],
|
||||
async handler (req, res) {
|
||||
if (!req.body.sku) throw new BadRequest(res.t('missingSubscriptionCode'));
|
||||
let user = res.locals.user;
|
||||
let iapBody = req.body;
|
||||
|
||||
await googlePayments.subscribe(req.body.sku, user, iapBody.transaction.receipt, iapBody.transaction.signature, req.headers);
|
||||
|
||||
res.respond(200);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @apiIgnore Payments are considered part of the private API
|
||||
* @api {get} /iap/android/subscribe/cancel Google Payments: subscribe cancel
|
||||
* @apiName AndroidSubscribeCancel
|
||||
* @apiGroup Payments
|
||||
**/
|
||||
api.iapCancelSubscriptionAndroid = {
|
||||
method: 'GET',
|
||||
url: '/iap/android/subscribe/cancel',
|
||||
middlewares: [authWithUrl],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
await googlePayments.cancelSubscribe(user, req.headers);
|
||||
|
||||
if (req.query.noRedirect) {
|
||||
res.respond(200);
|
||||
} else {
|
||||
res.redirect('/');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// IMPORTANT: NOT PORTED TO v3 standards (not using res.respond)
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user