diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..896022e Binary files /dev/null and b/.DS_Store differ diff --git a/index.js b/index.js index 7c51396..312837c 100644 --- a/index.js +++ b/index.js @@ -1,85 +1,91 @@ -'use strict'; +"use strict"; const platforms = { - amazon: require('./lib/amazon'), - apple: require('./lib/apple'), - google: require('./lib/google'), - roku: require('./lib/roku') + amazon: require("./lib/amazon"), + apple: require("./lib/apple"), + google: require("./lib/google"), + roku: require("./lib/roku"), + vizio: require("./lib/vizio"), }; const promisify = (fn) => { - return (...args) => { - return new Promise((resolve, reject) => { - fn(...args, (err, res) => { - return (err ? reject(err) : resolve(res)); - }); - }); - }; + return (...args) => { + return new Promise((resolve, reject) => { + fn(...args, (err, res) => { + return err ? reject(err) : resolve(res); + }); + }); + }; }; function verifyPayment(platform, payment, cb) { - function syncError(error) { - process.nextTick(function () { - cb(error); - }); - } + function syncError(error) { + process.nextTick(function () { + cb(error); + }); + } - if (!payment) { - return syncError(new Error('No payment given')); - } + if (!payment) { + return syncError(new Error("No payment given")); + } - const engine = platforms[platform]; + const engine = platforms[platform]; - if (!engine) { - return syncError(new Error(`Platform ${platform} not recognized`)); - } + if (!engine) { + return syncError(new Error(`Platform ${platform} not recognized`)); + } - engine.verifyPayment(payment, function (error, result) { - if (error) { - return cb(error); - } + engine.verifyPayment(payment, function (error, result) { + if (error) { + return cb(error); + } - result.platform = platform; + result.platform = platform; - cb(null, result); - }); + cb(null, result); + }); } function cancelSubscription(platform, payment, cb) { - function syncError(error) { - process.nextTick(function () { - cb(error); - }); - } - - if (!payment) { - return syncError(new Error('No payment given')); - } - - const engine = platforms[platform]; - - if (!engine) { - return syncError(new Error(`Platform ${platform} not recognized`)); - } - - if (!engine.cancelSubscription) { - return syncError(new Error(`Platform ${platform - } does not have cancelSubscription method`)); - } - - engine.cancelSubscription(payment, function (error, result) { - if (error) { - return cb(error); - } - - cb(null, result); - }); + function syncError(error) { + process.nextTick(function () { + cb(error); + }); + } + + if (!payment) { + return syncError(new Error("No payment given")); + } + + const engine = platforms[platform]; + + if (!engine) { + return syncError(new Error(`Platform ${platform} not recognized`)); + } + + if (!engine.cancelSubscription) { + return syncError( + new Error(`Platform ${platform} does not have cancelSubscription method`) + ); + } + + engine.cancelSubscription(payment, function (error, result) { + if (error) { + return cb(error); + } + + cb(null, result); + }); } exports.verifyPayment = (platform, payment, cb) => { - return (cb ? verifyPayment(platform, payment, cb) : promisify(verifyPayment)(platform, payment)); + return cb + ? verifyPayment(platform, payment, cb) + : promisify(verifyPayment)(platform, payment); }; exports.cancelSubscription = (platform, payment, cb) => { - return (cb ? cancelSubscription(platform, payment, cb) : promisify(cancelSubscription)(platform, payment)); + return cb + ? cancelSubscription(platform, payment, cb) + : promisify(cancelSubscription)(platform, payment); }; diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000..564f9bc Binary files /dev/null and b/lib/.DS_Store differ diff --git a/lib/amazon/index.js b/lib/amazon/index.js index ce7d16b..549cfab 100644 --- a/lib/amazon/index.js +++ b/lib/amazon/index.js @@ -4,7 +4,8 @@ const assert = require('assert'); const https = require('../https'); const apiUrl = { - production: 'https://appstore-sdk.amazon.com/version/1.0/verifyReceiptId/developer/' + production: 'https://appstore-sdk.amazon.com/version/1.0/verifyReceiptId/developer/', + sandbox: 'https://appstore-sdk.amazon.com/sandbox/version/1.0/verifyReceiptId/developer/' }; function parseResult(resultString) { @@ -38,7 +39,8 @@ exports.verifyPayment = function (payment, cb) { }); } - const requestUrl = `${apiUrl.production + payment.secret}/user/${payment.userId}/receiptId/${payment.receipt}`; + const url = payment.sandbox ? apiUrl.sandbox : apiUrl.production + const requestUrl = `${url + payment.secret}/user/${payment.userId}/receiptId/${payment.receipt}`; https.get(requestUrl, null, function (error, res, resultString) { if (error) { diff --git a/lib/vizio/index.js b/lib/vizio/index.js new file mode 100644 index 0000000..d9a7e92 --- /dev/null +++ b/lib/vizio/index.js @@ -0,0 +1,66 @@ +"use strict"; + +const assert = require("assert"); +const https = require("../https"); + +const apiUrl = { + sandbox: "https://preprod.api.developer-vizio.external.plat.vizio.com", + production: "https://api.developer-vizio.external.plat.vizio.com", +}; + +function parseResult(resultString) { + const result = JSON.parse(resultString); + return { + receipt: result, + transactionId: result.data.orderNumber, + productId: result.data.contentId, + purchaseDate: new Date(result.data.createdDate).getTime(), + expirationDate: null, + }; +} + +exports.verifyPayment = function (payment, cb) { + try { + assert.equal(typeof payment.partner, "string", "Partner must be a string"); + assert.equal(typeof payment.receipt, "string", "Receipt must be a string"); + assert.equal(typeof payment.secret, "string", "Secret must be a string"); + } catch (error) { + return process.nextTick(function () { + cb(error); + }); + } + + const url = payment.sandbox ? apiUrl.sandbox : apiUrl.production; + const requestUrl = `${url}/entitlements/batch/v1/transactions/${payment.partner}/orders/${payment.receipt}`; + https.get( + requestUrl, + { headers: { Authorization: payment.secret } }, + function (error, res, resultString) { + if (error) { + return cb(error); + } + + if (res.statusCode !== 200) { + return cb( + new Error( + `Received ${res.statusCode} status code with body: ${resultString}` + ) + ); + } + + let resultObject = null; + + try { + resultObject = parseResult(resultString); + } catch (error) { + return cb(error); + } + + if (resultObject.error) { + return cb(new Error(resultObject.error)); + } + + cb(null, resultObject); + } + ); +}; diff --git a/package.json b/package.json index c475989..c4b8eb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "iap", - "version": "1.1.1", + "name": "@fanmio/iap", + "version": "1.1.5", "description": "In-app purchase validation for Apple, Google, Amazon, Roku", "main": "index.js", "scripts": {