Skip to content

Commit 4e93cf3

Browse files
authored
fix(route): apple iap (#20404)
1 parent 94834e6 commit 4e93cf3

File tree

1 file changed

+34
-36
lines changed

1 file changed

+34
-36
lines changed

lib/routes/appstore/in-app-purchase.ts

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Route } from '@/types';
2-
import got from '@/utils/got';
3-
import * as url from 'node:url';
2+
import ofetch from '@/utils/ofetch';
43
import { load } from 'cheerio';
54

65
export const route: Route = {
@@ -24,56 +23,55 @@ export const route: Route = {
2423
handler,
2524
};
2625

26+
const getMediaApiToken = (metaContent) => {
27+
if (!metaContent) {
28+
throw new Error('Empty web experience config meta content');
29+
}
30+
const config = JSON.parse(decodeURIComponent(metaContent));
31+
return config.MEDIA_API.token;
32+
};
33+
2734
async function handler(ctx) {
2835
const country = ctx.req.param('country');
2936
const id = ctx.req.param('id');
3037
const link = `https://apps.apple.com/${country}/app/${id}`;
31-
const target = url.resolve(link, '?mt=8#see-all/in-app-purchases');
3238

33-
const res = await got.get(target);
34-
const $ = load(res.data);
39+
const res = await ofetch(link);
40+
const $ = load(res);
3541
const lang = $('html').attr('lang');
42+
const mediaToken = getMediaApiToken($('meta[name="web-experience-app/config/environment"]').attr('content'));
3643

37-
const apiResponse = (
38-
await got({
39-
method: 'get',
40-
url: `https://amp-api.apps.apple.com/v1/catalog/${country}/apps/${id.replace('id', '')}?platform=web&include=Cmerchandised-in-apps%2Ctop-in-apps%2Ceula&l=${lang}`,
41-
headers: {
42-
authorization:
43-
'Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IkNSRjVITkJHUFEifQ.eyJpc3MiOiI4Q1UyNk1LTFM0IiwiaWF0IjoxNjA3MDMxMTcwLCJleHAiOjE2MTAwNTUxNzB9.qzq2PKkPBNDwHbShoBY3T7J2IjgWsR_MyAvTnZtQB5FZjsH_ZY5esBa0qXbA9kUiq_90GkRoNVMR03meOQQ7SQ',
44-
authority: 'amp-api.apps.apple.com',
45-
referer: target,
46-
},
47-
})
48-
).data.data[0];
44+
const apiResponse = await ofetch(`https://amp-api-edge.apps.apple.com/v1/catalog/${country}/apps/${id.replace('id', '')}`, {
45+
query: {
46+
platform: 'web',
47+
include: 'merchandised-in-apps,top-in-apps,eula',
48+
l: lang,
49+
},
50+
headers: {
51+
authorization: `Bearer ${mediaToken}`,
52+
origin: 'https://apps.apple.com',
53+
},
54+
});
4955

50-
const attributes = apiResponse.attributes;
51-
const titleTemp = attributes.name;
56+
const appData = apiResponse.data[0];
57+
const attributes = appData.attributes;
5258

5359
const platform = attributes.deviceFamilies.includes('mac') ? 'macOS' : 'iOS';
54-
let title;
60+
5561
let item = [];
5662

57-
const iap = apiResponse.relationships['top-in-apps'].data;
63+
const iap = appData.relationships['top-in-apps'].data;
5864
if (iap) {
59-
title = `${country === 'cn' ? '内购限免提醒' : 'IAP price watcher'}: ${titleTemp} for ${platform}`;
60-
61-
item = iap.map((e) => {
62-
const title = `${e.attributes.name} is now ${e.attributes.offers[0].priceFormatted}`;
63-
64-
const result = {
65-
link,
66-
guid: e.attributes.url,
67-
description: e.attributes.artwork ? e.attributes.description.standard + `<br><img src=${e.attributes.artwork.url.replace('{w}x{h}{c}.{f}', '320x0w.jpg')}>` : e.attributes.description.standard,
68-
title,
69-
pubDate: new Date().toUTCString(),
70-
};
71-
return result;
72-
});
65+
item = iap.map(({ attributes }) => ({
66+
title: `${attributes.name} is now ${attributes.offers[0].priceFormatted}`,
67+
link: attributes.url,
68+
guid: `${attributes.url}:${attributes.offerName}:${attributes.offers[0].priceString}`,
69+
description: attributes.artwork ? attributes.description.standard + `<br><img src=${attributes.artwork.url.replace('{w}x{h}{c}.{f}', '3000x3000bb.webp')}>` : attributes.description.standard,
70+
}));
7371
}
7472

7573
return {
76-
title,
74+
title: `${country.toLowerCase() === 'cn' ? '内购限免提醒' : 'IAP price watcher'}: ${attributes.name} for ${platform}`,
7775
link,
7876
item,
7977
};

0 commit comments

Comments
 (0)