{"id":312992,"date":"2020-11-12T03:00:29","date_gmt":"2020-11-12T03:00:29","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=312992"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=312992","title":{"rendered":"\u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 In-app purchase \u0437\u0430 60 \u043c\u0438\u043d\u0443\u0442"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 In-app Purchase \u0438 In-app Subscription \u0434\u043b\u044f iOS \u0438 Android (server-server validation).<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/post\/162335\/\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043e\u0442 2013 \u0433\u043e\u0434\u0430 \u043f\u0440\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u043a\u0443\u043f\u043e\u043a. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u043b\u0430\u0442\u043d\u043e\u043c\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0436\u0435\u0439\u043b\u0431\u0440\u0435\u0439\u043a\u0430 \u0438 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0441\u043e\u0444\u0442\u0430. \u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0432 2020 \u0433\u043e\u0434\u0443 \u044d\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0442\u0430\u043a \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0430, \u0438 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0447\u0435\u043a\u043e\u0432 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442\u00bb \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u043e\u043a\u0443\u043f\u043a\u0435.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/369\/174\/29a\/36917429a5fbe19e0d0c8200ca94e862.png\"><br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 4 \u044d\u0442\u0430\u043f\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0447\u0435\u043a\u043e\u043c, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043a\u0443\u043f\u043a\u0438<\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u0432 Apple\/Google \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0447\u0435\u043a\u0430<\/li>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438<\/li>\n<li>\u041e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e\u043f\u0443\u0441\u0442\u0438\u043c 3 \u043f\u0443\u043d\u043a\u0442, \u0438\u0431\u043e \u043e\u043d \u0441\u0443\u0433\u0443\u0431\u043e \u0438\u043d\u0434\u0438\u0432\u0438\u0434\u0443\u0430\u043b\u0435\u043d.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u0434 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Node.js, \u043d\u043e \u043f\u043e \u0441\u0443\u0442\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430 \u0438 \u043d\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0442\u0440\u0443\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0415\u0449\u0435 \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044f \u0445\u043e\u0440\u043e\u0448\u0430\u044f <a href=\"https:\/\/habr.com\/ru\/company\/apphud\/blog\/472188\/\">\u00ab\u0422\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0447\u0435\u043a\u0430 App Store (App Store receipt)\u00bb<\/a>, \u0440\u0435\u0431\u044f\u0442\u0430 \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430\u043c\u0438. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0447\u0435\u043a (receipt) \u0438 \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043a\u0443\u043f\u043e\u043a.<\/p>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u0432 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u0430\u0445 \u043a\u043e\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b, \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"https:\/\/github.com\/denjoygroup\/inapppurchase\" rel=\"nofollow\">https:\/\/github.com\/denjoygroup\/inapppurchase<\/a>. \u0412 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c \u043d\u0438\u0436\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u0445 \u043a\u043e\u0434\u0430, \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0434\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u0430\u043c \u0442\u0430\u043a\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0441\u044b\u043b\u043a\u0438 \u043a \u044d\u0442\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c.<\/p>\n<p>  <\/p>\n<h2>iOS<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d <code>Apple Shared Secret<\/code> &ndash; \u044d\u0442\u043e \u043a\u043b\u044e\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432 iTunnes Connect, \u043e\u043d \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0447\u0435\u043a\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\"> apple: any = {     password: process.env.APPLE_SHARED_SECRET, \/\/ \u043a\u043b\u044e\u0447, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0441\u0432\u043e\u0439     host: 'buy.itunes.apple.com',     sandbox: 'sandbox.itunes.apple.com',     path: '\/verifyReceipt',     apiHost: 'api.appstoreconnect.apple.com',     pathToCheckSales: '\/v1\/salesReports'  } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0440\u0435\u0434\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043b\u0438\u0431\u043e \u043d\u0430 <code>sandbox.itunes.apple.com<\/code> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u043a\u0443\u043f\u043e\u043a, \u043b\u0438\u0431\u043e \u0432 \u043f\u0440\u043e\u0434 <code>buy.itunes.apple.com<\/code><\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/** * receiptValue - \u0447\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 * sandBox - \u0441\u0440\u0435\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a **\/ async _verifyReceipt(receiptValue: string, sandBox: boolean) {     let options = {         host: sandBox ? this._constants.apple.sandbox : this._constants.apple.host,         path: this._constants.apple.path,         method: 'POST'     };     let body = {         'receipt-data': receiptValue,         'password': this._constants.apple.password     };     let result = null;     let stringResult = await this._handlerService.sendHttp(options, body, 'https');     result = JSON.parse(stringResult);     return result; } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u043e\u0448\u0435\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 Apple \u0432 \u043f\u043e\u043b\u0435 <code>status<\/code> \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0432\u0430\u0448\u0435\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0423 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e\u043a\u0443\u043f\u043a\u0443<\/p>\n<p>  <\/p>\n<p><code><strong>21000<\/strong><\/code> \u2013 \u0417\u0430\u043f\u0440\u043e\u0441 \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d &ndash; \u043d\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u043c POST<\/p>\n<p>  <\/p>\n<p><code><strong>21002<\/strong><\/code> \u2013 \u0427\u0435\u043a \u043f\u043e\u0432\u0440\u0435\u0436\u0434\u0435\u043d, \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0435\u0433\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c<\/p>\n<p>  <\/p>\n<p><code><strong>21003<\/strong><\/code> \u2013 \u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0447\u0435\u043a, \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u043d\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0430<\/p>\n<p>  <\/p>\n<p><code><strong>21004<\/strong><\/code> \u2013 \u0412\u0430\u0448 <code>Shared Secret<\/code> \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0438\u043b\u0438 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0447\u0435\u043a\u0443<\/p>\n<p>  <\/p>\n<p><code><strong>21005<\/strong><\/code> \u2013 \u0421\u0435\u0440\u0432\u0435\u0440 \u044d\u043f\u043b\u0430 \u043d\u0435 \u0441\u043c\u043e\u0433 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u0440\u0430\u0437<\/p>\n<p>  <\/p>\n<p><code><strong>21006<\/strong><\/code> \u2013 \u0427\u0435\u043a \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d<\/p>\n<p>  <\/p>\n<p><code><strong>21007<\/strong><\/code> \u2013 \u0427\u0435\u043a \u0438\u0437 SandBox (\u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0441\u0440\u0435\u0434\u044b), \u043d\u043e \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 prod<\/p>\n<p>  <\/p>\n<p><code><strong>21008<\/strong><\/code> \u2013 \u0427\u0435\u043a \u0438\u0437 \u043f\u0440\u043e\u0434\u0430, \u043d\u043e \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0441\u0440\u0435\u0434\u0443<\/p>\n<p>  <\/p>\n<p><code><strong>21009<\/strong><\/code> \u2013 \u0421\u0435\u0440\u0432\u0435\u0440 \u044d\u043f\u043b\u0430 \u043d\u0435 \u0441\u043c\u043e\u0433 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0435\u0449\u0435 \u0440\u0430\u0437<\/p>\n<p>  <\/p>\n<p><code><strong>21010<\/strong><\/code> \u2013 \u0410\u043a\u043a\u0430\u0443\u043d\u0442 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0435\u043d<\/p>\n<p>  <\/p>\n<p><code><strong>0<\/strong><\/code> \u2013 \u041f\u043e\u043a\u0443\u043f\u043a\u0430 \u0432\u0430\u043b\u0438\u0434\u043d\u0430<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 iTunnes Connect \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">{     &quot;environment&quot;:&quot;Production&quot;,     &quot;receipt&quot;:{         &quot;receipt_type&quot;:&quot;Production&quot;,         &quot;adam_id&quot;:1527458047,         &quot;app_item_id&quot;:1527458047,         &quot;bundle_id&quot;:&quot;BUNDLE_ID&quot;,         &quot;application_version&quot;:&quot;0&quot;,         &quot;download_id&quot;:34089715299389,         &quot;version_external_identifier&quot;:838212484,         &quot;receipt_creation_date&quot;:&quot;2020-11-03 20:47:54 Etc\/GMT&quot;,         &quot;receipt_creation_date_ms&quot;:&quot;1604436474000&quot;,         &quot;receipt_creation_date_pst&quot;:&quot;2020-11-03 12:47:54 America\/Los_Angeles&quot;,         &quot;request_date&quot;:&quot;2020-11-03 20:48:01 Etc\/GMT&quot;,         &quot;request_date_ms&quot;:&quot;1604436481804&quot;,         &quot;request_date_pst&quot;:&quot;2020-11-03 12:48:01 America\/Los_Angeles&quot;,         &quot;original_purchase_date&quot;:&quot;2020-10-26 19:24:19 Etc\/GMT&quot;,         &quot;original_purchase_date_ms&quot;:&quot;1603740259000&quot;,         &quot;original_purchase_date_pst&quot;:&quot;2020-10-26 12:24:19 America\/Los_Angeles&quot;,         &quot;original_application_version&quot;:&quot;0&quot;,         &quot;in_app&quot;:[             {                 &quot;quantity&quot;:&quot;1&quot;,                 &quot;product_id&quot;:&quot;PRODUCT_ID&quot;,                 &quot;transaction_id&quot;:&quot;140000855642848&quot;,                 &quot;original_transaction_id&quot;:&quot;140000855642848&quot;,                 &quot;purchase_date&quot;:&quot;2020-11-03 20:47:53 Etc\/GMT&quot;,                 &quot;purchase_date_ms&quot;:&quot;1604436473000&quot;,                 &quot;purchase_date_pst&quot;:&quot;2020-11-03 12:47:53 America\/Los_Angeles&quot;,                 &quot;original_purchase_date&quot;:&quot;2020-11-03 20:47:54 Etc\/GMT&quot;,                 &quot;original_purchase_date_ms&quot;:&quot;1604436474000&quot;,                 &quot;original_purchase_date_pst&quot;:&quot;2020-11-03 12:47:54 America\/Los_Angeles&quot;,                 &quot;expires_date&quot;:&quot;2020-12-03 20:47:53 Etc\/GMT&quot;,                 &quot;expires_date_ms&quot;:&quot;1607028473000&quot;,                 &quot;expires_date_pst&quot;:&quot;2020-12-03 12:47:53 America\/Los_Angeles&quot;,                 &quot;web_order_line_item_id&quot;:&quot;140000337829668&quot;,                 &quot;is_trial_period&quot;:&quot;false&quot;,                 &quot;is_in_intro_offer_period&quot;:&quot;false&quot;             }         ]     },     &quot;latest_receipt_info&quot;:[         {             &quot;quantity&quot;:&quot;1&quot;,             &quot;product_id&quot;:&quot;PRODUCT_ID&quot;,             &quot;transaction_id&quot;:&quot;140000855642848&quot;,             &quot;original_transaction_id&quot;:&quot;140000855642848&quot;,             &quot;purchase_date&quot;:&quot;2020-11-03 20:47:53 Etc\/GMT&quot;,             &quot;purchase_date_ms&quot;:&quot;1604436473000&quot;,             &quot;purchase_date_pst&quot;:&quot;2020-11-03 12:47:53 America\/Los_Angeles&quot;,             &quot;original_purchase_date&quot;:&quot;2020-11-03 20:47:54 Etc\/GMT&quot;,             &quot;original_purchase_date_ms&quot;:&quot;1604436474000&quot;,             &quot;original_purchase_date_pst&quot;:&quot;2020-11-03 12:47:54 America\/Los_Angeles&quot;,             &quot;expires_date&quot;:&quot;2020-12-03 20:47:53 Etc\/GMT&quot;,             &quot;expires_date_ms&quot;:&quot;1607028473000&quot;,             &quot;expires_date_pst&quot;:&quot;2020-12-03 12:47:53 America\/Los_Angeles&quot;,             &quot;web_order_line_item_id&quot;:&quot;140000447829668&quot;,             &quot;is_trial_period&quot;:&quot;false&quot;,             &quot;is_in_intro_offer_period&quot;:&quot;false&quot;,             &quot;subscription_group_identifier&quot;:&quot;20675121&quot;         }     ],     &quot;latest_receipt&quot;:&quot;RECEIPT&quot;,     &quot;pending_renewal_info&quot;:[         {             &quot;auto_renew_product_id&quot;:&quot;PRODUCT_ID&quot;,             &quot;original_transaction_id&quot;:&quot;140000855642848&quot;,             &quot;product_id&quot;:&quot;PRODUCT_ID&quot;,             &quot;auto_renew_status&quot;:&quot;1&quot;         }     ],     &quot;status&quot;:0 } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u0442\u043e\u0438\u0442 \u0441\u0432\u0435\u0440\u0438\u0442\u044c <code>id<\/code> \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442 \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432 \u043e\u0442\u0432\u0435\u0442\u0435.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0434\u043b\u044f \u043d\u0430\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u0445 <code>in_app<\/code> \u0438 <code>latest_receipt_info<\/code>, \u0438 \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044d\u0442\u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b, \u043d\u043e:<\/p>\n<p>  <\/p>\n<p><code>latest_receipt_info<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435 \u043f\u043e\u043a\u0443\u043f\u043a\u0438.<\/p>\n<p>  <\/p>\n<p><code>in_app<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 Non-consumable \u0438 Non-Auto-Renewable \u043f\u043e\u043a\u0443\u043f\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>latest_receipt_info<\/code>, \u0441\u043e\u043e\u0442\u0432\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u044d\u0442\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0438\u0449\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u043f\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 <code>product_id<\/code> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0434\u0430\u0442\u0443, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u0435\u0449\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0435 \u043d\u0430\u0447\u0438\u0441\u043b\u0438\u043b\u0438 \u043b\u0438 \u043c\u044b \u0443\u0436\u0435 \u044d\u0442\u0443 \u043f\u043e\u043a\u0443\u043f\u043a\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f Consumable Purchase. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443 <code>original_transaction_id<\/code>, \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 \u0432 \u0431\u0430\u0437\u0435, \u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0433\u043e \u0433\u0430\u0439\u0434\u043b\u0430\u0439\u043d\u0430 \u043c\u044b \u044d\u0442\u043e\u0433\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c.<\/p>\n<p>  <\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/** * product - id \u043f\u043e\u043a\u0443\u043f\u043a\u0438 * resultFromApple - \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 Apple, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 * productType - \u0442\u0438\u043f \u043f\u043e\u043a\u0443\u043f\u043a\u0438 (\u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430, \u0440\u0430\u0441\u0445\u043e\u0434\u0443\u0435\u043c\u0430\u044f \u0438\u043b\u0438 non-consumable) * sandBox - \u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0441\u0440\u0435\u0434\u0430 \u0438\u043b\u0438 \u043d\u0435\u0442 * **\/ async parseResponse(product: string, resultFromApple: any, productType: ProductType, sandBox: boolean) {     let parsedResult: IPurchaseParsedResultFromProvider = {         validated: false,         trial: false,         checked: false,         sandBox,         productType: productType,         lastResponseFromProvider: JSON.stringify(resultFromApple)     };     switch (resultFromApple.status) {         \/**         * \u0412\u0430\u043b\u0438\u0434\u043d\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430         *\/         case 0: {             \/**             * \u0418\u0449\u0435\u043c \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u043f\u043e \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u043e\u043c\u0443 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0443             **\/             let currentPurchaseFromApple = this.getCurrentPurchaseFromAppleResult(resultFromApple, product!, productType);             if (!currentPurchaseFromApple) break;              parsedResult.checked = true;             parsedResult.originalTransactionId = this.getTransactionIdFromAppleResponse(currentPurchaseFromApple);             if (productType === ProductType.Subscription) {                 parsedResult.validated = (this.checkDateIsAfter(currentPurchaseFromApple.expires_date_ms)) ? true : false;                 parsedResult.expiredAt = (this.checkDateIsValid(currentPurchaseFromApple.expires_date_ms)) ?                 this.formatDate(currentPurchaseFromApple.expires_date_ms) : undefined;             } else {                 parsedResult.validated = true;             }             parsedResult.trial = !!currentPurchaseFromApple.is_trial_period;             break;         }         default:             if (!resultFromApple) console.log('empty result from apple');             else console.log('incorrect result from apple, status:', resultFromApple.status);     }     return parsedResult; } <\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e \u043d\u0430\u0448\u0435\u0439 \u043f\u043e\u043a\u0443\u043f\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>parsedResult<\/code>. \u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u044e, \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439, \u043d\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u0448\u0430\u0433\u0435 \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u0432\u0430\u043b\u0438\u0434\u043d\u0430 \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u0438\u043b\u0438 \u043d\u0435\u0442, \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u044d\u0442\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>parsedResult.validated<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0442\u043e \u043c\u043e\u0433\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 iTunnes Connect \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0443, \u0438\u0431\u043e \u0432\u043e\u0442 \u044d\u0442\u043e \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430. \u0422\u0430\u043a \u0436\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u0430\u0432\u0442\u043e\u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u043f\u043e\u043a\u0443\u043f\u043e\u043a, \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438 \u043a\u0430\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0440\u043e\u043d \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e &ndash; \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u043e\u043f\u043b\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043a\u0443\u043f\u043e\u043a, \u0430 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0440\u0430\u0437\u0443 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0437\u044b\u0432\u044b \u0441 \u043e\u0434\u043d\u043e\u0439 \u0437\u0432\u0435\u0437\u0434\u043e\u0439 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0441\u0442\u043e\u0440\u0435.<\/p>\n<p>  <\/p>\n<h2>Android<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0433\u0443\u0433\u043b\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0438\u0431\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u0434\u043e \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <code>OAuth<\/code> \u0438 \u043f\u043e\u0442\u043e\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u043a\u0443\u043f\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0433\u0443\u0433\u043b\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">google: any = {     host: 'androidpublisher.googleapis.com',     path: '\/androidpublisher\/v3\/applications',     email: process.env.GOOGLE_EMAIL,     key: process.env.GOOGLE_KEY,     storeName: process.env.GOOGLE_STORE_NAME } <\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0435\u0439 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u041e\u043a\u0435\u0439, \u0433\u0443\u0433\u043b, \u043f\u0440\u0438\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/** * product - \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 * token - \u0447\u0435\u043a * productType &ndash; \u0442\u0438\u043f \u043f\u043e\u043a\u0443\u043f\u043a\u0438, \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438\u043b\u0438 \u043d\u0435\u0442 **\/ async getPurchaseInfoFromGoogle(product: string, token: string, productType: ProductType) {     try {         let options = {             email: this._constants.google.email,             key: this._constants.google.key,             scopes: ['https:\/\/www.googleapis.com\/auth\/androidpublisher'],         };         const client = new JWT(options);         let productOrSubscriptionUrlPart = productType === ProductType.Subscription ? 'subscriptions' : 'products';         const url = `https:\/\/${this._constants.google.host}${this._constants.google.path}\/${this._constants.google.storeName}\/purchases\/${productOrSubscriptionUrlPart}\/${product}\/tokens\/${token}`;         const res = await client.request({ url });         return res.data as ResultFromGoogle;     } catch(e) {         return e as ErrorFromGoogle;     } } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <code>google-auth-library<\/code> \u0438 \u043a\u043b\u0430\u0441\u0441 <code>JWT<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0433\u0443\u0433\u043b\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">{     startTimeMillis: &quot;1603956759767&quot;,     expiryTimeMillis: &quot;1603966728908&quot;,     autoRenewing: false,     priceCurrencyCode: &quot;RUB&quot;,     priceAmountMicros: &quot;499000000&quot;,     countryCode: &quot;RU&quot;,     developerPayload: {         &quot;developerPayload&quot;:&quot;&quot;,         &quot;is_free_trial&quot;:false,         &quot;has_introductory_price_trial&quot;:false,         &quot;is_updated&quot;:false,         &quot;accountId&quot;:&quot;&quot;     },     cancelReason: 1,     orderId: &quot;GPA.3335-9310-7555-53285..5&quot;,     purchaseType: 0,     acknowledgementState: 1,     kind: &quot;androidpublisher#subscriptionPurchase&quot; } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u043f\u043e\u043a\u0443\u043f\u043a\u0438<\/p>\n<pre><code class=\"javascript\">parseResponse(product: string, result: ResultFromGoogle | ErrorFromGoogle, type: ProductType) {     let parsedResult: IPurchaseParsedResultFromProvider = {         validated: false,         trial: false,         checked: true,         sandBox: false,         productType: type,         lastResponseFromProvider: JSON.stringify(result),     };     if (this.isResultFromGoogle(result)) {         if (this.isSubscriptionResult(result)) {             parsedResult.expiredAt = moment(result.expiryTimeMillis, 'x').toDate();             parsedResult.validated = this.checkDateIsAfter(parsedResult.expiredAt);         } else if (this.isProductResult(result)) {             parsedResult.validated = true;         }     }     return parsedResult; } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e. \u041d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c <code>parsedResult<\/code>, \u0433\u0434\u0435 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435 <code>validated<\/code> &ndash; \u043f\u0440\u043e\u0448\u043b\u0430 \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438\u043b\u0438 \u043d\u0435\u0442.<\/p>\n<p>  <\/p>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0432 2 \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u043a\u0443\u043f\u043a\u0443. \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"https:\/\/github.com\/denjoygroup\/inapppurchase\" rel=\"nofollow\">https:\/\/github.com\/denjoygroup\/inapppurchase<\/a> (\u0430\u0432\u0442\u043e\u0440 \u043a\u043e\u0434\u0430 \u0410\u043b\u0435\u043a\u0441\u0435\u0439 \u0413\u0435\u0432\u043e\u0440\u043a\u044f\u043d)<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u044b \u0443\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043d\u044e\u0430\u043d\u0441\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0447\u0435\u043a\u043e\u0432: <a href=\"https:\/\/ru.adapty.io\/\" rel=\"nofollow\">https:\/\/ru.adapty.io\/<\/a> \u0438 <a href=\"https:\/\/apphud.com\/\" rel=\"nofollow\">https:\/\/apphud.com\/<\/a>. \u041d\u043e, \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 3 \u0441\u0442\u043e\u0440\u043e\u043d\u0435, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u043e\u043a\u0443\u043f\u043a\u0438, \u0442\u043e \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<p>  <\/p>\n<h2>P.S.<\/h2>\n<p>  <\/p>\n<p>\u041d\u0443, \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 &ndash; \u044d\u0442\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d \u0432\u044b\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u0441\u0430\u043c\u0438\u043c, \u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441\u0440\u0430\u0437\u0443 \u0432 iTunnes Connect \u0438 \u0432 Google API, \u0438\u043d\u0430\u0447\u0435 \u0432\u0430\u0448\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/527644\/\"> https:\/\/habr.com\/ru\/post\/527644\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442! \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 In-app Purchase \u0438 In-app Subscription \u0434\u043b\u044f iOS \u0438 Android (server-server validation).<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0445\u0430\u0431\u0440\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/post\/162335\/\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043e\u0442 2013 \u0433\u043e\u0434\u0430 \u043f\u0440\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043f\u043e\u043a\u0443\u043f\u043e\u043a. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u043b\u0430\u0442\u043d\u043e\u043c\u0443 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u0436\u0435\u0439\u043b\u0431\u0440\u0435\u0439\u043a\u0430 \u0438 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0441\u043e\u0444\u0442\u0430. \u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0432 2020 \u0433\u043e\u0434\u0443 \u044d\u0442\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0442\u0430\u043a \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0430, \u0438 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0447\u0435\u043a\u043e\u0432 \u043f\u043e\u043a\u0443\u043f\u043e\u043a \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u00ab\u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442\u00bb \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u043e\u043a\u0443\u043f\u043a\u0435.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/369\/174\/29a\/36917429a5fbe19e0d0c8200ca94e862.png\">  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-312992","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=312992"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/312992\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=312992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=312992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=312992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}