myxl-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/@types/payment.d.ts +10 -0
- package/dist/auth.d.ts +20 -0
- package/dist/auth.js +157 -0
- package/dist/ciam.d.ts +259 -0
- package/dist/ciam.js +351 -0
- package/dist/client.d.ts +56 -0
- package/dist/client.js +276 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.js +70 -0
- package/dist/device.d.ts +23 -0
- package/dist/device.js +107 -0
- package/dist/encrypt.d.ts +37 -0
- package/dist/encrypt.js +259 -0
- package/dist/family-plan.d.ts +28 -0
- package/dist/family-plan.js +325 -0
- package/dist/family.d.ts +146 -0
- package/dist/family.js +365 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +1487 -0
- package/dist/lib/decoy.d.ts +17 -0
- package/dist/lib/decoy.js +117 -0
- package/dist/lib/encrypt-helper.d.ts +71 -0
- package/dist/lib/encrypt-helper.js +166 -0
- package/dist/lib/payment.d.ts +116 -0
- package/dist/lib/payment.js +271 -0
- package/dist/lib/utils.d.ts +15 -0
- package/dist/lib/utils.js +290 -0
- package/dist/notification.d.ts +28 -0
- package/dist/notification.js +275 -0
- package/dist/package.d.ts +259 -0
- package/dist/package.js +387 -0
- package/dist/payments/balance.d.ts +2 -0
- package/dist/payments/balance.js +408 -0
- package/dist/payments/decoy.d.ts +1 -0
- package/dist/payments/decoy.js +6 -0
- package/dist/payments/ewallet.d.ts +11 -0
- package/dist/payments/ewallet.js +373 -0
- package/dist/payments/index.d.ts +3 -0
- package/dist/payments/index.js +632 -0
- package/dist/payments/qris.d.ts +2 -0
- package/dist/payments/qris.js +378 -0
- package/dist/profile.d.ts +1 -0
- package/dist/profile.js +266 -0
- package/dist/verification.d.ts +2 -0
- package/dist/verification.js +279 -0
- package/package.json +116 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1487 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
function __accessProp(key) {
|
|
7
|
+
return this[key];
|
|
8
|
+
}
|
|
9
|
+
var __toCommonJS = (from) => {
|
|
10
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
11
|
+
if (entry)
|
|
12
|
+
return entry;
|
|
13
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (var key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(entry, key))
|
|
17
|
+
__defProp(entry, key, {
|
|
18
|
+
get: __accessProp.bind(from, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
__moduleCache.set(from, entry);
|
|
23
|
+
return entry;
|
|
24
|
+
};
|
|
25
|
+
var __moduleCache;
|
|
26
|
+
var __returnValue = (v) => v;
|
|
27
|
+
function __exportSetter(name, newValue) {
|
|
28
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
29
|
+
}
|
|
30
|
+
var __export = (target, all) => {
|
|
31
|
+
for (var name in all)
|
|
32
|
+
__defProp(target, name, {
|
|
33
|
+
get: all[name],
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
set: __exportSetter.bind(all, name)
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
40
|
+
|
|
41
|
+
// src/lib/encrypt-helper.ts
|
|
42
|
+
var exports_encrypt_helper = {};
|
|
43
|
+
__export(exports_encrypt_helper, {
|
|
44
|
+
makeXSignaturePayment: () => makeXSignaturePayment,
|
|
45
|
+
makeXSignatureLoyalty: () => makeXSignatureLoyalty,
|
|
46
|
+
makeXSignatureBountyAllotment: () => makeXSignatureBountyAllotment,
|
|
47
|
+
makeXSignatureBounty: () => makeXSignatureBounty,
|
|
48
|
+
makeXSignatureBasic: () => makeXSignatureBasic,
|
|
49
|
+
makeXSignature: () => makeXSignature,
|
|
50
|
+
makeAxApiSignature: () => makeAxApiSignature,
|
|
51
|
+
encryptXData: () => encryptXData,
|
|
52
|
+
encryptEncryptedField: () => encryptEncryptedField,
|
|
53
|
+
decryptXData: () => decryptXData,
|
|
54
|
+
decryptEncryptedField: () => decryptEncryptedField
|
|
55
|
+
});
|
|
56
|
+
import crypto from "crypto";
|
|
57
|
+
function pkcs7Pad(buf, blockSize = 16) {
|
|
58
|
+
const pad = blockSize - buf.length % blockSize;
|
|
59
|
+
const padBuf = Buffer.alloc(pad, pad);
|
|
60
|
+
return Buffer.concat([buf, padBuf]);
|
|
61
|
+
}
|
|
62
|
+
function pkcs7Unpad(buf) {
|
|
63
|
+
const pad = buf[buf.length - 1] ?? 16;
|
|
64
|
+
if (pad < 1 || pad > 16)
|
|
65
|
+
throw new Error("Invalid PKCS7 padding");
|
|
66
|
+
return buf.slice(0, buf.length - pad);
|
|
67
|
+
}
|
|
68
|
+
function deriveIv(xtimeMs) {
|
|
69
|
+
const sha = crypto.createHash("sha256").update(String(xtimeMs)).digest("hex");
|
|
70
|
+
return Buffer.from(sha.slice(0, 16), "ascii");
|
|
71
|
+
}
|
|
72
|
+
function urlsafeB64Encode(buf) {
|
|
73
|
+
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_");
|
|
74
|
+
}
|
|
75
|
+
function urlsafeB64Decode(s) {
|
|
76
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
77
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
78
|
+
return Buffer.from(padded, "base64");
|
|
79
|
+
}
|
|
80
|
+
function encryptXData(plaintext, xtimeMs) {
|
|
81
|
+
const key = Buffer.from(XDATA_KEY, "ascii");
|
|
82
|
+
const iv = deriveIv(xtimeMs);
|
|
83
|
+
const padded = pkcs7Pad(Buffer.from(plaintext, "utf-8"));
|
|
84
|
+
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
|
85
|
+
cipher.setAutoPadding(false);
|
|
86
|
+
const ct = Buffer.concat([cipher.update(padded), cipher.final()]);
|
|
87
|
+
return urlsafeB64Encode(ct);
|
|
88
|
+
}
|
|
89
|
+
function decryptXData(xdata, xtimeMs) {
|
|
90
|
+
const key = Buffer.from(XDATA_KEY, "ascii");
|
|
91
|
+
const iv = deriveIv(xtimeMs);
|
|
92
|
+
const ct = urlsafeB64Decode(xdata);
|
|
93
|
+
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
|
94
|
+
decipher.setAutoPadding(false);
|
|
95
|
+
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
96
|
+
return pkcs7Unpad(pt).toString("utf-8");
|
|
97
|
+
}
|
|
98
|
+
function makeXSignature(idToken, method, path, sigTimeSec) {
|
|
99
|
+
const keyStr = `${X_API_BASE_SECRET};${idToken};${method};${path};${sigTimeSec}`;
|
|
100
|
+
const msg = `${idToken};${sigTimeSec};`;
|
|
101
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
102
|
+
}
|
|
103
|
+
function makeXSignaturePayment(accessToken, sigTimeSec, packageCode, tokenPayment, paymentMethod, paymentFor, path) {
|
|
104
|
+
const keyStr = `${X_API_BASE_SECRET};${sigTimeSec}#ae-hei_9Tee6he+Ik3Gais5=;POST;${path};${sigTimeSec}`;
|
|
105
|
+
const msg = `${accessToken};${tokenPayment};${sigTimeSec};${paymentFor};${paymentMethod};${packageCode};`;
|
|
106
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
107
|
+
}
|
|
108
|
+
function makeXSignatureBounty(accessToken, sigTimeSec, packageCode, tokenPayment) {
|
|
109
|
+
const path = "api/v8/personalization/bounties-exchange";
|
|
110
|
+
const keyStr = `${X_API_BASE_SECRET};${accessToken};${sigTimeSec}#ae-hei_9Tee6he+Ik3Gais5=;POST;${path};${sigTimeSec}`;
|
|
111
|
+
const msg = `${accessToken};${tokenPayment};${sigTimeSec};${packageCode};`;
|
|
112
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
113
|
+
}
|
|
114
|
+
function makeXSignatureLoyalty(sigTimeSec, packageCode, tokenConfirmation, path) {
|
|
115
|
+
const keyStr = `${X_API_BASE_SECRET};${sigTimeSec}#ae-hei_9Tee6he+Ik3Gais5=;POST;${path};${sigTimeSec}`;
|
|
116
|
+
const msg = `${tokenConfirmation};${sigTimeSec};${packageCode};`;
|
|
117
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
118
|
+
}
|
|
119
|
+
function makeXSignatureBountyAllotment(sigTimeSec, packageCode, tokenConfirmation, path, destinationMsisdn) {
|
|
120
|
+
const keyStr = `${X_API_BASE_SECRET};${sigTimeSec}#ae-hei_9Tee6he+Ik3Gais5=;${destinationMsisdn};POST;${path};${sigTimeSec}`;
|
|
121
|
+
const msg = `${tokenConfirmation};${sigTimeSec};${destinationMsisdn};${packageCode};`;
|
|
122
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
123
|
+
}
|
|
124
|
+
function makeXSignatureBasic(method, path, sigTimeSec) {
|
|
125
|
+
const keyStr = `${X_API_BASE_SECRET};${method};${path};${sigTimeSec}`;
|
|
126
|
+
const msg = `${sigTimeSec};en;`;
|
|
127
|
+
return crypto.createHmac("sha512", keyStr).update(msg).digest("hex");
|
|
128
|
+
}
|
|
129
|
+
function makeAxApiSignature(tsForSign, contact, code, contactType) {
|
|
130
|
+
const preimage = `${tsForSign}password${contactType}${contact}${code}openid`;
|
|
131
|
+
const digest = crypto.createHmac("sha256", Buffer.from(AX_API_SIG_KEY, "ascii")).update(preimage).digest();
|
|
132
|
+
return digest.toString("base64");
|
|
133
|
+
}
|
|
134
|
+
function decryptEncryptedField(encryptedB64) {
|
|
135
|
+
const ivAscii = encryptedB64.slice(-16);
|
|
136
|
+
const b64Part = encryptedB64.slice(0, -16);
|
|
137
|
+
const key = Buffer.from(ENCRYPTED_FIELD_KEY, "ascii");
|
|
138
|
+
const iv = Buffer.from(ivAscii, "ascii");
|
|
139
|
+
const ct = urlsafeB64Decode(b64Part);
|
|
140
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", key, iv);
|
|
141
|
+
decipher.setAutoPadding(false);
|
|
142
|
+
const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
143
|
+
return pkcs7Unpad(pt).toString("utf-8");
|
|
144
|
+
}
|
|
145
|
+
function encryptEncryptedField(plaintext) {
|
|
146
|
+
const key = Buffer.from(ENCRYPTED_FIELD_KEY, "ascii");
|
|
147
|
+
const ivHex = crypto.randomBytes(8).toString("hex");
|
|
148
|
+
const iv = Buffer.from(ivHex, "ascii");
|
|
149
|
+
const padded = pkcs7Pad(Buffer.from(plaintext, "utf-8"));
|
|
150
|
+
const cipher = crypto.createCipheriv("aes-128-cbc", key, iv);
|
|
151
|
+
cipher.setAutoPadding(false);
|
|
152
|
+
const ct = Buffer.concat([cipher.update(padded), cipher.final()]);
|
|
153
|
+
return urlsafeB64Encode(ct) + ivHex;
|
|
154
|
+
}
|
|
155
|
+
var init_encrypt_helper = __esm(() => {
|
|
156
|
+
init_config();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// src/encrypt.ts
|
|
160
|
+
var exports_encrypt = {};
|
|
161
|
+
__export(exports_encrypt, {
|
|
162
|
+
makeXSignaturePayment: () => makeXSignaturePayment,
|
|
163
|
+
makeXSignatureLoyalty: () => makeXSignatureLoyalty,
|
|
164
|
+
makeXSignatureBountyAllotment: () => makeXSignatureBountyAllotment,
|
|
165
|
+
makeXSignatureBounty: () => makeXSignatureBounty,
|
|
166
|
+
makeXSignatureBasic: () => makeXSignatureBasic,
|
|
167
|
+
makeAxApiSignature: () => makeAxApiSignature,
|
|
168
|
+
encryptSignXData: () => encryptSignXData,
|
|
169
|
+
encryptEncryptedField: () => encryptEncryptedField,
|
|
170
|
+
decryptXDataSync: () => decryptXDataSync,
|
|
171
|
+
decryptXData: () => decryptXData2,
|
|
172
|
+
decryptEncryptedField: () => decryptEncryptedField,
|
|
173
|
+
buildEncryptedField: () => buildEncryptedField
|
|
174
|
+
});
|
|
175
|
+
import crypto2 from "crypto";
|
|
176
|
+
function encryptSignXData(method, path, idToken, payload) {
|
|
177
|
+
const plainBody = JSON.stringify(payload);
|
|
178
|
+
const xtime = Date.now();
|
|
179
|
+
const xdata = encryptXData(plainBody, xtime);
|
|
180
|
+
const sigTimeSec = Math.floor(xtime / 1000);
|
|
181
|
+
const xSignature = makeXSignature(idToken, method, path, sigTimeSec);
|
|
182
|
+
return {
|
|
183
|
+
x_signature: xSignature,
|
|
184
|
+
encrypted_body: { xdata, xtime }
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function decryptXDataSync(xdata, xtimeMs) {
|
|
188
|
+
const { decryptXData: decryptXData2 } = (init_encrypt_helper(), __toCommonJS(exports_encrypt_helper));
|
|
189
|
+
const plaintext = decryptXData2(xdata, xtimeMs);
|
|
190
|
+
return JSON.parse(plaintext);
|
|
191
|
+
}
|
|
192
|
+
async function decryptXData2(xdata, xtimeMs) {
|
|
193
|
+
const { decryptXData: _decrypt } = (init_encrypt_helper(), __toCommonJS(exports_encrypt_helper));
|
|
194
|
+
return JSON.parse(_decrypt(xdata, xtimeMs));
|
|
195
|
+
}
|
|
196
|
+
function randomIvHex16() {
|
|
197
|
+
return crypto2.randomBytes(8).toString("hex");
|
|
198
|
+
}
|
|
199
|
+
function b64(data, urlsafe) {
|
|
200
|
+
const b64str = data.toString("base64");
|
|
201
|
+
if (urlsafe) {
|
|
202
|
+
return b64str.replace(/\+/g, "-").replace(/\//g, "_");
|
|
203
|
+
}
|
|
204
|
+
return b64str;
|
|
205
|
+
}
|
|
206
|
+
function buildEncryptedField(ivHex16 = null, urlsafeB64 = false) {
|
|
207
|
+
const key = Buffer.from(ENCRYPTED_FIELD_KEY, "ascii");
|
|
208
|
+
const ivHex = ivHex16 ?? randomIvHex16();
|
|
209
|
+
const iv = Buffer.from(ivHex, "ascii");
|
|
210
|
+
const pt = Buffer.alloc(16, 16);
|
|
211
|
+
const cipher = crypto2.createCipheriv("aes-128-cbc", key, iv);
|
|
212
|
+
cipher.setAutoPadding(false);
|
|
213
|
+
const ct = Buffer.concat([cipher.update(pt), cipher.final()]);
|
|
214
|
+
return b64(ct, urlsafeB64) + ivHex;
|
|
215
|
+
}
|
|
216
|
+
var init_encrypt = __esm(() => {
|
|
217
|
+
init_config();
|
|
218
|
+
init_encrypt_helper();
|
|
219
|
+
init_encrypt_helper();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// src/lib/utils.ts
|
|
223
|
+
var exports_utils = {};
|
|
224
|
+
__export(exports_utils, {
|
|
225
|
+
unseal: () => unseal,
|
|
226
|
+
tsGmt7WithoutColon: () => tsGmt7WithoutColon,
|
|
227
|
+
sendApiRequest: () => sendApiRequest,
|
|
228
|
+
javaLikeTimestamp: () => javaLikeTimestamp,
|
|
229
|
+
interceptPage: () => interceptPage,
|
|
230
|
+
base64Encode: () => base64Encode
|
|
231
|
+
});
|
|
232
|
+
import axios from "axios";
|
|
233
|
+
import { v4 as uuidv4 } from "uuid";
|
|
234
|
+
import { DateTime } from "luxon";
|
|
235
|
+
function javaLikeTimestamp(dt = DateTime.now()) {
|
|
236
|
+
return dt.toMillis().toString();
|
|
237
|
+
}
|
|
238
|
+
async function sendApiRequest(path, payloadDict, idToken, method = "POST") {
|
|
239
|
+
const encryptedPayload = encryptSignXData(method, path, idToken, payloadDict);
|
|
240
|
+
const xtime = Number(encryptedPayload.encrypted_body.xtime);
|
|
241
|
+
const sigTimeSec = Math.floor(xtime / 1000);
|
|
242
|
+
const body = encryptedPayload.encrypted_body;
|
|
243
|
+
const x_sig = encryptedPayload.x_signature;
|
|
244
|
+
const headers = {
|
|
245
|
+
host: BASE_API_URL.replace(/^https?:\/\//, ""),
|
|
246
|
+
"content-type": "application/json; charset=utf-8",
|
|
247
|
+
"user-agent": UA,
|
|
248
|
+
"x-api-key": API_KEY,
|
|
249
|
+
authorization: `Bearer ${idToken}`,
|
|
250
|
+
"x-hv": "v3",
|
|
251
|
+
"x-signature-time": String(sigTimeSec),
|
|
252
|
+
"x-signature": x_sig,
|
|
253
|
+
"x-request-id": uuidv4(),
|
|
254
|
+
"x-request-at": javaLikeTimestamp(),
|
|
255
|
+
"x-version-app": X_APP_VERSION
|
|
256
|
+
};
|
|
257
|
+
const url = `${BASE_API_URL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
258
|
+
const resp = await axios.post(url, body, {
|
|
259
|
+
headers,
|
|
260
|
+
timeout: 30000
|
|
261
|
+
});
|
|
262
|
+
const respData = resp.data;
|
|
263
|
+
const decryptedXData = await decryptXData2(respData.xdata, respData.xtime);
|
|
264
|
+
if (decryptedXData.status === "FAILED") {
|
|
265
|
+
throw new Error(JSON.stringify(decryptedXData));
|
|
266
|
+
}
|
|
267
|
+
return decryptedXData;
|
|
268
|
+
}
|
|
269
|
+
function base64Encode(str) {
|
|
270
|
+
return Buffer.from(str, "utf-8").toString("base64");
|
|
271
|
+
}
|
|
272
|
+
function tsGmt7WithoutColon(date) {
|
|
273
|
+
let formatted = date.toFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
|
|
274
|
+
if (formatted.endsWith("+07:00")) {
|
|
275
|
+
formatted = formatted.replace("+07:00", "+0700");
|
|
276
|
+
}
|
|
277
|
+
return formatted;
|
|
278
|
+
}
|
|
279
|
+
async function interceptPage(idToken, optionCode, isEnterprise = false) {
|
|
280
|
+
const path = "misc/api/v8/utility/intercept-page";
|
|
281
|
+
const rawPayload = {
|
|
282
|
+
is_enterprise: isEnterprise,
|
|
283
|
+
lang: "en",
|
|
284
|
+
package_option_code: optionCode
|
|
285
|
+
};
|
|
286
|
+
console.log("Fetching intercept page...");
|
|
287
|
+
try {
|
|
288
|
+
const res = await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
289
|
+
if ("status" in res) {
|
|
290
|
+
console.log(`Intercept status: ${res["status"]}`);
|
|
291
|
+
} else {
|
|
292
|
+
console.log("Intercept error");
|
|
293
|
+
}
|
|
294
|
+
} catch (err) {
|
|
295
|
+
console.log("Intercept error", err);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function unseal(getter, fallback) {
|
|
299
|
+
try {
|
|
300
|
+
const hex = getter();
|
|
301
|
+
if (!hex || typeof __SEED__ === "undefined")
|
|
302
|
+
return fallback;
|
|
303
|
+
const seed = Buffer.from(__SEED__, "hex");
|
|
304
|
+
const data = Buffer.from(hex, "hex");
|
|
305
|
+
return Buffer.from(data.map((b, i) => b ^ seed[i % seed.length])).toString("utf8");
|
|
306
|
+
} catch {
|
|
307
|
+
return fallback;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
var init_utils = __esm(() => {
|
|
311
|
+
init_config();
|
|
312
|
+
init_encrypt();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// src/config.ts
|
|
316
|
+
var exports_config = {};
|
|
317
|
+
__export(exports_config, {
|
|
318
|
+
X_APP_VERSION: () => X_APP_VERSION,
|
|
319
|
+
X_API_BASE_SECRET: () => X_API_BASE_SECRET,
|
|
320
|
+
XDATA_KEY: () => XDATA_KEY,
|
|
321
|
+
UA: () => UA,
|
|
322
|
+
ENCRYPTED_FIELD_KEY: () => ENCRYPTED_FIELD_KEY,
|
|
323
|
+
DEFAULT_AX_FP: () => DEFAULT_AX_FP,
|
|
324
|
+
DEFAULT_AX_DEVICE_ID: () => DEFAULT_AX_DEVICE_ID,
|
|
325
|
+
CIRCLE_MSISDN_KEY: () => CIRCLE_MSISDN_KEY,
|
|
326
|
+
BASIC_AUTH: () => BASIC_AUTH,
|
|
327
|
+
BASE_CIAM_URL: () => BASE_CIAM_URL,
|
|
328
|
+
BASE_API_URL: () => BASE_API_URL,
|
|
329
|
+
AX_FP_KEY: () => AX_FP_KEY,
|
|
330
|
+
AX_API_SIG_KEY: () => AX_API_SIG_KEY,
|
|
331
|
+
API_KEY: () => API_KEY
|
|
332
|
+
});
|
|
333
|
+
var BASE_API_URL, BASE_CIAM_URL, BASIC_AUTH, AX_FP_KEY, UA, API_KEY, ENCRYPTED_FIELD_KEY, XDATA_KEY, AX_API_SIG_KEY, X_API_BASE_SECRET, CIRCLE_MSISDN_KEY, DEFAULT_AX_DEVICE_ID = "a9698fc65ed122e1b0efb2b7e9d93728", DEFAULT_AX_FP = "LDMGk/l1xEViBHOOsQb/CtVyh6FI0QvxXGfsoizEhr7ms1SBTYN07kcmSY3CWDlkG39iSV4p0AuafPoIL+pyoI+1StGif01C7Z/3Lprtkn+WHS3QAKHuAb8LQGe9/2pn", X_APP_VERSION = "8.9.0";
|
|
334
|
+
var init_config = __esm(() => {
|
|
335
|
+
init_utils();
|
|
336
|
+
BASE_API_URL = unseal(() => __E_BASE_API_URL__, "https://api.myxl.xlaxiata.co.id");
|
|
337
|
+
BASE_CIAM_URL = unseal(() => __E_BASE_CIAM_URL__, "https://gede.ciam.xlaxiata.co.id");
|
|
338
|
+
BASIC_AUTH = unseal(() => __E_BASIC_AUTH__, "OWZjOTdlZDEtNmEzMC00OGQ1LTk1MTYtNjBjNTNjZTNhMTM1OllEV21GNExKajlYSUt3UW56eTJlMmxiMHRKUWIyOW8z");
|
|
339
|
+
AX_FP_KEY = unseal(() => __E_AX_FP_KEY__, "18b4d589826af50241177961590e6693");
|
|
340
|
+
UA = unseal(() => __E_UA__, "myXL / 8.9.0(1202); com.android.vending; (samsung; SM-N935F; SDK 33; Android 13)");
|
|
341
|
+
API_KEY = unseal(() => __E_API_KEY__, "vT8tINqHaOxXbGE7eOWAhA==");
|
|
342
|
+
ENCRYPTED_FIELD_KEY = unseal(() => __E_ENCRYPTED_FIELD_KEY__, "5dccbf08920a5527");
|
|
343
|
+
XDATA_KEY = unseal(() => __E_XDATA_KEY__, "5dccbf08920a5527b99e222789c34bb7");
|
|
344
|
+
AX_API_SIG_KEY = unseal(() => __E_AX_API_SIG_KEY__, "18b4d589826af50241177961590e6693");
|
|
345
|
+
X_API_BASE_SECRET = unseal(() => __E_X_API_BASE_SECRET__, "mU1Y4n1vBjf3M7tMnRkFU08mVyUJHed8B5En3EAniu1mXLixeuASmBmKnkyzVziOye7rG5nIekMdthensbQMcOJ6SLnrkGyfXALD7mrBC6vuWv6G01pmD3XlU5rT7Tzx");
|
|
346
|
+
CIRCLE_MSISDN_KEY = unseal(() => __E_CIRCLE_MSISDN_KEY__, "5dccbf08920a5527");
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// src/auth.ts
|
|
350
|
+
init_config();
|
|
351
|
+
init_utils();
|
|
352
|
+
init_encrypt();
|
|
353
|
+
var exports_auth = {};
|
|
354
|
+
__export(exports_auth, {
|
|
355
|
+
submitSmsOtp: () => submitSmsOtp,
|
|
356
|
+
submitOtp: () => submitOtp,
|
|
357
|
+
getOtp: () => getOtp
|
|
358
|
+
});
|
|
359
|
+
import axios2 from "axios";
|
|
360
|
+
import { v4 as uuidv42 } from "uuid";
|
|
361
|
+
import { DateTime as DateTime2, FixedOffsetZone } from "luxon";
|
|
362
|
+
import * as crypto3 from "crypto";
|
|
363
|
+
async function getOtp(contact, axDeviceId, axFingerprint) {
|
|
364
|
+
const url = BASE_CIAM_URL + "/realms/xl-ciam/auth/otp";
|
|
365
|
+
const querystring = {
|
|
366
|
+
contact,
|
|
367
|
+
contactType: "SMS",
|
|
368
|
+
alternateContact: "false"
|
|
369
|
+
};
|
|
370
|
+
const gmt7Zone = FixedOffsetZone.instance(420);
|
|
371
|
+
const now = DateTime2.now().setZone(gmt7Zone);
|
|
372
|
+
const ax_request_at = javaLikeTimestamp(now);
|
|
373
|
+
const ax_request_id = uuidv42();
|
|
374
|
+
const headers = {
|
|
375
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
376
|
+
Authorization: `Basic ${BASIC_AUTH}`,
|
|
377
|
+
"Ax-Device-Id": axDeviceId,
|
|
378
|
+
"Ax-Fingerprint": axFingerprint,
|
|
379
|
+
"Ax-Request-At": ax_request_at,
|
|
380
|
+
"Ax-Request-Device": "samsung",
|
|
381
|
+
"Ax-Request-Device-Model": "SM-N935F",
|
|
382
|
+
"Ax-Request-Id": ax_request_id,
|
|
383
|
+
"Ax-Substype": "PREPAID",
|
|
384
|
+
"Content-Type": "application/json",
|
|
385
|
+
Host: BASE_CIAM_URL.replace(/^https?:\/\//, ""),
|
|
386
|
+
"User-Agent": UA
|
|
387
|
+
};
|
|
388
|
+
const { data } = await axios2.get(url, {
|
|
389
|
+
headers,
|
|
390
|
+
params: querystring,
|
|
391
|
+
timeout: 30000
|
|
392
|
+
});
|
|
393
|
+
return data;
|
|
394
|
+
}
|
|
395
|
+
async function submitOtp(contactType, contact, code, axDeviceId, axFingerprint) {
|
|
396
|
+
let finalContact = "";
|
|
397
|
+
let finalCode = "";
|
|
398
|
+
if (contactType === "SMS") {
|
|
399
|
+
finalContact = contact;
|
|
400
|
+
finalCode = code;
|
|
401
|
+
} else if (contactType === "DEVICEID") {
|
|
402
|
+
finalContact = base64Encode(contact);
|
|
403
|
+
finalCode = code;
|
|
404
|
+
}
|
|
405
|
+
const url = BASE_CIAM_URL + "/realms/xl-ciam/protocol/openid-connect/token";
|
|
406
|
+
const now = DateTime2.now().setZone("Asia/Jakarta");
|
|
407
|
+
const ts_for_sign = tsGmt7WithoutColon(now);
|
|
408
|
+
const ts_header = tsGmt7WithoutColon(now.minus({ minutes: 5 }));
|
|
409
|
+
const signature = await makeAxApiSignature(ts_for_sign, finalContact, code, contactType);
|
|
410
|
+
const payload = `contactType=${encodeURIComponent(contactType)}&code=${encodeURIComponent(finalCode)}&grant_type=password&contact=${encodeURIComponent(finalContact)}&scope=openid`;
|
|
411
|
+
const axRequestId = crypto3.randomUUID();
|
|
412
|
+
const headers = {
|
|
413
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
414
|
+
Authorization: `Basic ${BASIC_AUTH}`,
|
|
415
|
+
"Ax-Api-Signature": signature,
|
|
416
|
+
"Ax-Device-Id": axDeviceId,
|
|
417
|
+
"Ax-Fingerprint": axFingerprint,
|
|
418
|
+
"Ax-Request-At": ts_header,
|
|
419
|
+
"Ax-Request-Device": "samsung",
|
|
420
|
+
"Ax-Request-Device-Model": "SM-N935F",
|
|
421
|
+
"Ax-Request-Id": axRequestId,
|
|
422
|
+
"Ax-Substype": "PREPAID",
|
|
423
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
424
|
+
"User-Agent": UA
|
|
425
|
+
};
|
|
426
|
+
const response = await axios2.post(url, payload, {
|
|
427
|
+
headers,
|
|
428
|
+
timeout: 30000
|
|
429
|
+
});
|
|
430
|
+
return response.data;
|
|
431
|
+
}
|
|
432
|
+
async function submitSmsOtp(contact, code, axDeviceId, axFingerprint) {
|
|
433
|
+
return submitOtp("SMS", contact, code, axDeviceId, axFingerprint);
|
|
434
|
+
}
|
|
435
|
+
// src/ciam.ts
|
|
436
|
+
init_config();
|
|
437
|
+
init_utils();
|
|
438
|
+
var exports_ciam = {};
|
|
439
|
+
__export(exports_ciam, {
|
|
440
|
+
getTieringInfo: () => getTieringInfo,
|
|
441
|
+
getRedeemables: () => getRedeemables,
|
|
442
|
+
getProfile: () => getProfile,
|
|
443
|
+
getNewToken: () => getNewToken,
|
|
444
|
+
getBalance: () => getBalance,
|
|
445
|
+
fetchMyPackages: () => fetchMyPackages,
|
|
446
|
+
checkQuota: () => checkQuota
|
|
447
|
+
});
|
|
448
|
+
import axios3 from "axios";
|
|
449
|
+
import { DateTime as DateTime3, FixedOffsetZone as FixedOffsetZone2 } from "luxon";
|
|
450
|
+
import { v4 as uuidv43 } from "uuid";
|
|
451
|
+
async function getNewToken(refreshToken, axDeviceId, axFingerprint) {
|
|
452
|
+
try {
|
|
453
|
+
const url = `${BASE_CIAM_URL}/realms/xl-ciam/protocol/openid-connect/token`;
|
|
454
|
+
const gmt7Zone = FixedOffsetZone2.instance(420);
|
|
455
|
+
const now = DateTime3.now().setZone(gmt7Zone);
|
|
456
|
+
const ax_request_at = now.toFormat("yyyy-MM-dd'T'HH:mm:ss.SSS") + "+0700";
|
|
457
|
+
const ax_request_id = uuidv43();
|
|
458
|
+
const headers = {
|
|
459
|
+
Host: BASE_CIAM_URL.replace("https://", ""),
|
|
460
|
+
"ax-request-at": ax_request_at,
|
|
461
|
+
"ax-device-id": axDeviceId,
|
|
462
|
+
"ax-request-id": ax_request_id,
|
|
463
|
+
"ax-request-device": "samsung",
|
|
464
|
+
"ax-request-device-model": "SM-N935F",
|
|
465
|
+
"ax-fingerprint": axFingerprint,
|
|
466
|
+
authorization: `Basic ${BASIC_AUTH}`,
|
|
467
|
+
"user-agent": UA,
|
|
468
|
+
"ax-substype": "PREPAID",
|
|
469
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
470
|
+
};
|
|
471
|
+
const data = new URLSearchParams({
|
|
472
|
+
grant_type: "refresh_token",
|
|
473
|
+
refresh_token: refreshToken
|
|
474
|
+
});
|
|
475
|
+
const resp = await axios3.post(url, data.toString(), {
|
|
476
|
+
headers,
|
|
477
|
+
timeout: 30000
|
|
478
|
+
});
|
|
479
|
+
return resp.data;
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.error("Refresh token tidak valid:", error);
|
|
482
|
+
throw new Error("Refresh token tidak valid.");
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
async function getProfile(accessToken, idToken) {
|
|
486
|
+
const path = "api/v8/profile";
|
|
487
|
+
const rawPayload = {
|
|
488
|
+
access_token: accessToken,
|
|
489
|
+
app_version: X_APP_VERSION,
|
|
490
|
+
is_enterprise: false,
|
|
491
|
+
lang: "en"
|
|
492
|
+
};
|
|
493
|
+
const res = await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
494
|
+
return res.data.profile;
|
|
495
|
+
}
|
|
496
|
+
async function getBalance(idToken) {
|
|
497
|
+
const path = "api/v8/packages/balance-and-credit";
|
|
498
|
+
const rawPayload = {
|
|
499
|
+
is_enterprise: false,
|
|
500
|
+
lang: "en"
|
|
501
|
+
};
|
|
502
|
+
return await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
503
|
+
}
|
|
504
|
+
async function getTieringInfo(idToken) {
|
|
505
|
+
const path = "gamification/api/v8/loyalties/tiering/info";
|
|
506
|
+
const rawPayload = {
|
|
507
|
+
is_enterprise: false,
|
|
508
|
+
lang: "en"
|
|
509
|
+
};
|
|
510
|
+
return await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
511
|
+
}
|
|
512
|
+
async function getRedeemables({ idToken, isEnterprise }) {
|
|
513
|
+
const path = "api/v8/personalization/redeemables";
|
|
514
|
+
const rawPayload = {
|
|
515
|
+
is_enterprise: isEnterprise,
|
|
516
|
+
lang: "en"
|
|
517
|
+
};
|
|
518
|
+
return await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
519
|
+
}
|
|
520
|
+
async function checkQuota(msisdn) {
|
|
521
|
+
const url = `https://xl-ku.my.id/end.php?check=package&number=${msisdn}&version=2`;
|
|
522
|
+
console.log(`Fetching quota for ${msisdn} from external API...`);
|
|
523
|
+
const response = await axios3.get(url);
|
|
524
|
+
return response.data;
|
|
525
|
+
}
|
|
526
|
+
async function fetchMyPackages({ idToken }) {
|
|
527
|
+
const path = "api/v8/packages/quota-details";
|
|
528
|
+
const rawPayload = {
|
|
529
|
+
is_enterprise: false,
|
|
530
|
+
lang: "en",
|
|
531
|
+
family_member_id: ""
|
|
532
|
+
};
|
|
533
|
+
return await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
534
|
+
}
|
|
535
|
+
// src/client.ts
|
|
536
|
+
init_utils();
|
|
537
|
+
var exports_client = {};
|
|
538
|
+
__export(exports_client, {
|
|
539
|
+
getTransactionHistory: () => getTransactionHistory,
|
|
540
|
+
dashboardSegments: () => dashboardSegments
|
|
541
|
+
});
|
|
542
|
+
async function getTransactionHistory({ idToken }) {
|
|
543
|
+
const path = "payments/api/v8/transaction-history";
|
|
544
|
+
const payload = {
|
|
545
|
+
is_enterprise: false,
|
|
546
|
+
lang: "en"
|
|
547
|
+
};
|
|
548
|
+
console.log("Fetching transaction history...");
|
|
549
|
+
const res = await sendApiRequest(path, payload, idToken, "POST");
|
|
550
|
+
return res.data.list;
|
|
551
|
+
}
|
|
552
|
+
async function dashboardSegments({ idToken, accessToken }) {
|
|
553
|
+
const path = "dashboard/api/v8/segments";
|
|
554
|
+
const rawPayload = {
|
|
555
|
+
access_token: accessToken
|
|
556
|
+
};
|
|
557
|
+
const res = await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
558
|
+
return res;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/index.ts
|
|
562
|
+
init_config();
|
|
563
|
+
|
|
564
|
+
// src/device.ts
|
|
565
|
+
init_config();
|
|
566
|
+
var exports_device = {};
|
|
567
|
+
__export(exports_device, {
|
|
568
|
+
getAxDeviceId: () => getAxDeviceId,
|
|
569
|
+
generateAxFp: () => generateAxFp,
|
|
570
|
+
buildFingerprintPlain: () => buildFingerprintPlain,
|
|
571
|
+
axFingerprint: () => axFingerprint
|
|
572
|
+
});
|
|
573
|
+
import crypto4 from "crypto";
|
|
574
|
+
function randint(min, max) {
|
|
575
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
576
|
+
}
|
|
577
|
+
function buildFingerprintPlain(dev) {
|
|
578
|
+
return `${dev.manufacturer}|${dev.model}|${dev.lang}|${dev.resolution}|` + `${dev.tz_short}|${dev.ip}|${dev.font_scale}|Android ${dev.android_release}|${dev.msisdn}`;
|
|
579
|
+
}
|
|
580
|
+
function pkcs7Pad2(buf, blockSize = 16) {
|
|
581
|
+
const padLen = blockSize - (buf.length % blockSize || blockSize);
|
|
582
|
+
const padByte = padLen;
|
|
583
|
+
const padding = Buffer.alloc(padLen, padByte);
|
|
584
|
+
return Buffer.concat([buf, padding]);
|
|
585
|
+
}
|
|
586
|
+
function axFingerprint(dev, secretKey32Ascii) {
|
|
587
|
+
const key = Buffer.from(secretKey32Ascii, "ascii");
|
|
588
|
+
if (![16, 24, 32].includes(key.length)) {
|
|
589
|
+
throw new Error(`AX_FP_KEY invalid length: got ${key.length} bytes. Expected 16/24/32 ASCII chars.`);
|
|
590
|
+
}
|
|
591
|
+
const iv = Buffer.alloc(16, 0);
|
|
592
|
+
const pt = Buffer.from(buildFingerprintPlain(dev), "utf8");
|
|
593
|
+
const padded = pkcs7Pad2(pt, 16);
|
|
594
|
+
const cipher = crypto4.createCipheriv(key.length === 16 ? "aes-128-cbc" : key.length === 24 ? "aes-192-cbc" : "aes-256-cbc", key, iv);
|
|
595
|
+
cipher.setAutoPadding(false);
|
|
596
|
+
const ct = Buffer.concat([cipher.update(padded), cipher.final()]);
|
|
597
|
+
return ct.toString("base64");
|
|
598
|
+
}
|
|
599
|
+
function generateAxFp(params) {
|
|
600
|
+
const dev = {
|
|
601
|
+
manufacturer: "samsung" + String(randint(1000, 9999)),
|
|
602
|
+
model: "SM-N93" + String(randint(1000, 9999)),
|
|
603
|
+
lang: "en",
|
|
604
|
+
resolution: "720x1540",
|
|
605
|
+
tz_short: "GMT07:00",
|
|
606
|
+
ip: params?.ip ?? "192.169.69.69",
|
|
607
|
+
font_scale: 1,
|
|
608
|
+
android_release: "13",
|
|
609
|
+
msisdn: params?.msisdn ?? "6281398370564"
|
|
610
|
+
};
|
|
611
|
+
const fp = axFingerprint(dev, AX_FP_KEY);
|
|
612
|
+
return fp;
|
|
613
|
+
}
|
|
614
|
+
function getAxDeviceId(axFp) {
|
|
615
|
+
if (!axFp || !axFp.trim())
|
|
616
|
+
throw new Error("AX_FP is empty");
|
|
617
|
+
return crypto4.createHash("md5").update(axFp, "utf8").digest("hex");
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/index.ts
|
|
621
|
+
init_encrypt();
|
|
622
|
+
|
|
623
|
+
// src/family.ts
|
|
624
|
+
init_utils();
|
|
625
|
+
var exports_family = {};
|
|
626
|
+
__export(exports_family, {
|
|
627
|
+
getFamilySafe: () => getFamilySafe,
|
|
628
|
+
getFamily: () => getFamily
|
|
629
|
+
});
|
|
630
|
+
async function getFamily(idToken, familyCode, isEnterprise, migrationType) {
|
|
631
|
+
let isEnterpriseList = [false, true];
|
|
632
|
+
let migrationTypeList = [
|
|
633
|
+
"NONE",
|
|
634
|
+
"PRE_TO_PRIOH",
|
|
635
|
+
"PRIOH_TO_PRIO",
|
|
636
|
+
"PRIO_TO_PRIOH"
|
|
637
|
+
];
|
|
638
|
+
if (typeof isEnterprise !== "undefined") {
|
|
639
|
+
isEnterpriseList = [isEnterprise];
|
|
640
|
+
}
|
|
641
|
+
if (typeof migrationType !== "undefined") {
|
|
642
|
+
migrationTypeList = [migrationType];
|
|
643
|
+
}
|
|
644
|
+
const path = "api/v8/xl-stores/options/list";
|
|
645
|
+
const comboList = [];
|
|
646
|
+
for (const mt of migrationTypeList) {
|
|
647
|
+
for (const ie of isEnterpriseList) {
|
|
648
|
+
comboList.push({ ie, mt });
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
const requests = comboList.map(({ ie, mt }) => {
|
|
652
|
+
const payloadDict = {
|
|
653
|
+
is_show_tagging_tab: true,
|
|
654
|
+
is_dedicated_event: true,
|
|
655
|
+
is_transaction_routine: false,
|
|
656
|
+
migration_type: mt,
|
|
657
|
+
package_family_code: familyCode,
|
|
658
|
+
is_autobuy: false,
|
|
659
|
+
is_enterprise: ie,
|
|
660
|
+
is_pdlp: true,
|
|
661
|
+
referral_code: "",
|
|
662
|
+
is_migration: false,
|
|
663
|
+
lang: "en"
|
|
664
|
+
};
|
|
665
|
+
return sendApiRequest(path, payloadDict, idToken, "POST").then((res) => ({
|
|
666
|
+
res,
|
|
667
|
+
ie,
|
|
668
|
+
mt
|
|
669
|
+
})).catch((e) => {
|
|
670
|
+
return { res: null, ie, mt, error: e };
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
const results = await Promise.all(requests);
|
|
674
|
+
for (const { res, ie, mt } of results) {
|
|
675
|
+
if (res && res["status"] === "SUCCESS") {
|
|
676
|
+
const familyName = res.data?.package_family?.name ?? "";
|
|
677
|
+
if (familyName !== "") {
|
|
678
|
+
console.log(`Success with is_enterprise=${ie}, migration_type=${mt}. Family name: ${familyName}`);
|
|
679
|
+
return res.data;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
async function getFamilySafe(idToken, familyCode, isEnterprise, migrationType) {
|
|
686
|
+
let isEnterpriseList = [false, true];
|
|
687
|
+
let migrationTypeList = [
|
|
688
|
+
"NONE",
|
|
689
|
+
"PRE_TO_PRIOH",
|
|
690
|
+
"PRIOH_TO_PRIO",
|
|
691
|
+
"PRIO_TO_PRIOH"
|
|
692
|
+
];
|
|
693
|
+
if (typeof isEnterprise !== "undefined") {
|
|
694
|
+
isEnterpriseList = [isEnterprise];
|
|
695
|
+
}
|
|
696
|
+
if (typeof migrationType !== "undefined") {
|
|
697
|
+
migrationTypeList = [migrationType];
|
|
698
|
+
}
|
|
699
|
+
const path = "api/v8/xl-stores/options/list";
|
|
700
|
+
let familyData = null;
|
|
701
|
+
for (const mt of migrationTypeList) {
|
|
702
|
+
if (familyData !== null)
|
|
703
|
+
break;
|
|
704
|
+
for (const ie of isEnterpriseList) {
|
|
705
|
+
if (familyData !== null)
|
|
706
|
+
break;
|
|
707
|
+
const payloadDict = {
|
|
708
|
+
is_show_tagging_tab: true,
|
|
709
|
+
is_dedicated_event: true,
|
|
710
|
+
is_transaction_routine: false,
|
|
711
|
+
migration_type: mt,
|
|
712
|
+
package_family_code: familyCode,
|
|
713
|
+
is_autobuy: false,
|
|
714
|
+
is_enterprise: ie,
|
|
715
|
+
is_pdlp: true,
|
|
716
|
+
referral_code: "",
|
|
717
|
+
is_migration: false,
|
|
718
|
+
lang: "en"
|
|
719
|
+
};
|
|
720
|
+
try {
|
|
721
|
+
const res = await sendApiRequest(path, payloadDict, idToken, "POST");
|
|
722
|
+
if (!res || res["status"] !== "SUCCESS") {
|
|
723
|
+
continue;
|
|
724
|
+
}
|
|
725
|
+
const familyName = res.data?.package_family?.name ?? "";
|
|
726
|
+
if (familyName !== "") {
|
|
727
|
+
familyData = res.data;
|
|
728
|
+
console.log(`Success with is_enterprise=${ie}, migration_type=${mt}. Family name: ${familyName}`);
|
|
729
|
+
}
|
|
730
|
+
} catch (e) {
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
return familyData;
|
|
736
|
+
}
|
|
737
|
+
// src/family-plan.ts
|
|
738
|
+
init_utils();
|
|
739
|
+
var exports_family_plan = {};
|
|
740
|
+
__export(exports_family_plan, {
|
|
741
|
+
validateMsisdn: () => validateMsisdn,
|
|
742
|
+
setQuotaLimit: () => setQuotaLimit,
|
|
743
|
+
removeMember: () => removeMember,
|
|
744
|
+
getFamilyData: () => getFamilyData,
|
|
745
|
+
changeMember: () => changeMember
|
|
746
|
+
});
|
|
747
|
+
async function getFamilyData(idToken) {
|
|
748
|
+
const path = "sharings/api/v8/family-plan/member-info";
|
|
749
|
+
const payload = {
|
|
750
|
+
group_id: 0,
|
|
751
|
+
is_enterprise: false,
|
|
752
|
+
lang: "en"
|
|
753
|
+
};
|
|
754
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
755
|
+
}
|
|
756
|
+
async function validateMsisdn(idToken, msisdn) {
|
|
757
|
+
const path = "api/v8/auth/validate-msisdn";
|
|
758
|
+
const payload = {
|
|
759
|
+
with_bizon: true,
|
|
760
|
+
with_family_plan: true,
|
|
761
|
+
is_enterprise: false,
|
|
762
|
+
with_optimus: true,
|
|
763
|
+
lang: "en",
|
|
764
|
+
msisdn,
|
|
765
|
+
with_regist_status: true,
|
|
766
|
+
with_enterprise: true
|
|
767
|
+
};
|
|
768
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
769
|
+
}
|
|
770
|
+
async function changeMember(idToken, parentAlias, alias, slotId, familyMemberId, newMsisdn) {
|
|
771
|
+
const path = "sharings/api/v8/family-plan/change-member";
|
|
772
|
+
const payload = {
|
|
773
|
+
parent_alias: parentAlias,
|
|
774
|
+
is_enterprise: false,
|
|
775
|
+
slot_id: slotId,
|
|
776
|
+
alias,
|
|
777
|
+
lang: "en",
|
|
778
|
+
msisdn: newMsisdn,
|
|
779
|
+
family_member_id: familyMemberId
|
|
780
|
+
};
|
|
781
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
782
|
+
}
|
|
783
|
+
async function removeMember(idToken, familyMemberId) {
|
|
784
|
+
const path = "sharings/api/v8/family-plan/remove-member";
|
|
785
|
+
const payload = {
|
|
786
|
+
is_enterprise: false,
|
|
787
|
+
family_member_id: familyMemberId,
|
|
788
|
+
lang: "en"
|
|
789
|
+
};
|
|
790
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
791
|
+
}
|
|
792
|
+
async function setQuotaLimit(idToken, originalAllocation, newAllocation, familyMemberId) {
|
|
793
|
+
const path = "sharings/api/v8/family-plan/allocate-quota";
|
|
794
|
+
const payload = {
|
|
795
|
+
is_enterprise: false,
|
|
796
|
+
member_allocations: [{
|
|
797
|
+
new_text_allocation: 0,
|
|
798
|
+
original_text_allocation: 0,
|
|
799
|
+
original_voice_allocation: 0,
|
|
800
|
+
original_allocation: originalAllocation,
|
|
801
|
+
new_voice_allocation: 0,
|
|
802
|
+
message: "",
|
|
803
|
+
new_allocation: newAllocation,
|
|
804
|
+
family_member_id: familyMemberId,
|
|
805
|
+
status: ""
|
|
806
|
+
}],
|
|
807
|
+
lang: "en"
|
|
808
|
+
};
|
|
809
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
810
|
+
}
|
|
811
|
+
// src/notification.ts
|
|
812
|
+
init_utils();
|
|
813
|
+
var exports_notification = {};
|
|
814
|
+
__export(exports_notification, {
|
|
815
|
+
getNotifications: () => getNotifications,
|
|
816
|
+
getNotificationDetail: () => getNotificationDetail
|
|
817
|
+
});
|
|
818
|
+
async function getNotifications(idToken) {
|
|
819
|
+
const path = "api/v8/notification-non-grouping";
|
|
820
|
+
const payload = {
|
|
821
|
+
is_enterprise: false,
|
|
822
|
+
lang: "en"
|
|
823
|
+
};
|
|
824
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
825
|
+
}
|
|
826
|
+
async function getNotificationDetail(idToken, notificationId) {
|
|
827
|
+
const path = "api/v8/notification/detail";
|
|
828
|
+
const payload = {
|
|
829
|
+
is_enterprise: false,
|
|
830
|
+
lang: "en",
|
|
831
|
+
notification_id: notificationId
|
|
832
|
+
};
|
|
833
|
+
return sendApiRequest(path, payload, idToken, "POST");
|
|
834
|
+
}
|
|
835
|
+
// src/package.ts
|
|
836
|
+
var exports_package = {};
|
|
837
|
+
__export(exports_package, {
|
|
838
|
+
getPackageByOrderId: () => getPackageByOrderId,
|
|
839
|
+
getPackage: () => getPackage,
|
|
840
|
+
getAddons: () => getAddons
|
|
841
|
+
});
|
|
842
|
+
init_utils();
|
|
843
|
+
async function getPackage({
|
|
844
|
+
idToken,
|
|
845
|
+
packageOptionCode,
|
|
846
|
+
packageFamilyCode = "",
|
|
847
|
+
packageVariantCode = ""
|
|
848
|
+
}) {
|
|
849
|
+
const path = "api/v8/xl-stores/options/detail";
|
|
850
|
+
const payload = {
|
|
851
|
+
is_transaction_routine: false,
|
|
852
|
+
migration_type: "NONE",
|
|
853
|
+
package_family_code: packageFamilyCode,
|
|
854
|
+
family_role_hub: "",
|
|
855
|
+
is_autobuy: false,
|
|
856
|
+
is_enterprise: false,
|
|
857
|
+
is_shareable: false,
|
|
858
|
+
is_migration: false,
|
|
859
|
+
lang: "en",
|
|
860
|
+
package_option_code: packageOptionCode,
|
|
861
|
+
is_upsell_pdp: false,
|
|
862
|
+
package_variant_code: packageVariantCode
|
|
863
|
+
};
|
|
864
|
+
console.log("Fetching package...");
|
|
865
|
+
const response = await sendApiRequest(path, payload, idToken, "POST");
|
|
866
|
+
return response.data;
|
|
867
|
+
}
|
|
868
|
+
async function getPackageByOrderId({
|
|
869
|
+
idToken,
|
|
870
|
+
packageFamilyCode,
|
|
871
|
+
packageVariantCode,
|
|
872
|
+
order,
|
|
873
|
+
isEnterprise,
|
|
874
|
+
migrationType
|
|
875
|
+
}) {
|
|
876
|
+
const xpackages = await getFamily(idToken, packageFamilyCode, isEnterprise, migrationType);
|
|
877
|
+
if (!xpackages) {
|
|
878
|
+
throw new Error("Data tidak ditemukan untuk family code yang diberikan.");
|
|
879
|
+
}
|
|
880
|
+
const findVariant = xpackages.package_variants.find((v) => v.package_variant_code === packageVariantCode);
|
|
881
|
+
if (!findVariant) {
|
|
882
|
+
throw new Error(`Package variant with code ${packageVariantCode} not found in family ${packageFamilyCode}`);
|
|
883
|
+
}
|
|
884
|
+
const findPackageOption = findVariant.package_options.find((x) => x.order === order);
|
|
885
|
+
if (!findPackageOption) {
|
|
886
|
+
throw new Error(`Package option with order ${order} not found in variant ${findVariant.package_variant_code}`);
|
|
887
|
+
}
|
|
888
|
+
const data = await getPackage({
|
|
889
|
+
idToken,
|
|
890
|
+
packageOptionCode: findPackageOption.package_option_code
|
|
891
|
+
});
|
|
892
|
+
data.package_option.package_option_code = findPackageOption.package_option_code;
|
|
893
|
+
return data;
|
|
894
|
+
}
|
|
895
|
+
async function getAddons({
|
|
896
|
+
idToken,
|
|
897
|
+
packageOptionCode
|
|
898
|
+
}) {
|
|
899
|
+
const path = "api/v8/xl-stores/options/addons-pinky-box";
|
|
900
|
+
const rawPayload = {
|
|
901
|
+
is_enterprise: false,
|
|
902
|
+
lang: "en",
|
|
903
|
+
package_option_code: packageOptionCode
|
|
904
|
+
};
|
|
905
|
+
console.log("Fetching addons...");
|
|
906
|
+
const res = await sendApiRequest(path, rawPayload, idToken, "POST");
|
|
907
|
+
if (!("data" in res)) {
|
|
908
|
+
console.log("Error getting addons:", res.error ?? "Unknown error");
|
|
909
|
+
return null;
|
|
910
|
+
}
|
|
911
|
+
return res.data;
|
|
912
|
+
}
|
|
913
|
+
// src/payments/index.ts
|
|
914
|
+
var exports_payments = {};
|
|
915
|
+
__export(exports_payments, {
|
|
916
|
+
settlementQris: () => settlementQris,
|
|
917
|
+
settlementEWallet: () => settlementEWallet,
|
|
918
|
+
settlementBalance: () => settlementBalance,
|
|
919
|
+
EWalletProviderEnum: () => EWalletProviderEnum
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
// src/payments/balance.ts
|
|
923
|
+
init_encrypt();
|
|
924
|
+
init_utils();
|
|
925
|
+
init_config();
|
|
926
|
+
import axios4 from "axios";
|
|
927
|
+
import { v4 as uuidv44 } from "uuid";
|
|
928
|
+
import { DateTime as DateTime4 } from "luxon";
|
|
929
|
+
async function settlementBalance({
|
|
930
|
+
idToken,
|
|
931
|
+
accessToken,
|
|
932
|
+
item,
|
|
933
|
+
items,
|
|
934
|
+
paymentFor,
|
|
935
|
+
tokenConfirmation,
|
|
936
|
+
topup_number = "",
|
|
937
|
+
stage_token = "",
|
|
938
|
+
overwriteAmount = null,
|
|
939
|
+
paymentTargetsMethodsOption
|
|
940
|
+
}) {
|
|
941
|
+
const payment_targets = items.map((item2) => item2.item_code).join(";");
|
|
942
|
+
const [paymentRes, encryptedFields] = await Promise.all([
|
|
943
|
+
sendApiRequest("payments/api/v8/payment-methods-option", {
|
|
944
|
+
payment_type: "PURCHASE",
|
|
945
|
+
is_enterprise: false,
|
|
946
|
+
payment_target: paymentTargetsMethodsOption ?? item.item_code,
|
|
947
|
+
lang: "en",
|
|
948
|
+
is_referral: false,
|
|
949
|
+
token_confirmation: tokenConfirmation
|
|
950
|
+
}, idToken, "POST"),
|
|
951
|
+
Promise.all([
|
|
952
|
+
buildEncryptedField(null, true),
|
|
953
|
+
buildEncryptedField(null, true)
|
|
954
|
+
])
|
|
955
|
+
]);
|
|
956
|
+
const { token_payment, timestamp } = paymentRes.data;
|
|
957
|
+
const price = overwriteAmount === 0 ? 0 : item.item_price;
|
|
958
|
+
const [encrypted_payment_token, encrypted_authentication_id] = encryptedFields;
|
|
959
|
+
const settlementPath = "payments/api/v8/settlement-multipayment";
|
|
960
|
+
const sigInput = {
|
|
961
|
+
accessToken,
|
|
962
|
+
timestamp,
|
|
963
|
+
itemCode: item.item_code,
|
|
964
|
+
token_payment,
|
|
965
|
+
payment_method: "BALANCE",
|
|
966
|
+
paymentFor,
|
|
967
|
+
settlementPath
|
|
968
|
+
};
|
|
969
|
+
const settlementPayload = {
|
|
970
|
+
total_discount: 0,
|
|
971
|
+
is_enterprise: false,
|
|
972
|
+
payment_token: "",
|
|
973
|
+
token_payment,
|
|
974
|
+
activated_autobuy_code: "",
|
|
975
|
+
cc_payment_type: "",
|
|
976
|
+
is_myxl_wallet: false,
|
|
977
|
+
pin: "",
|
|
978
|
+
ewallet_promo_id: "",
|
|
979
|
+
members: [],
|
|
980
|
+
total_fee: 0,
|
|
981
|
+
fingerprint: "",
|
|
982
|
+
autobuy_threshold_setting: { label: "", type: "", value: 0 },
|
|
983
|
+
is_use_point: false,
|
|
984
|
+
lang: "en",
|
|
985
|
+
payment_method: "BALANCE",
|
|
986
|
+
timestamp,
|
|
987
|
+
points_gained: 0,
|
|
988
|
+
can_trigger_rating: false,
|
|
989
|
+
akrab_members: [],
|
|
990
|
+
akrab_parent_alias: "",
|
|
991
|
+
referral_unique_code: "",
|
|
992
|
+
coupon: "",
|
|
993
|
+
payment_for: paymentFor,
|
|
994
|
+
with_upsell: false,
|
|
995
|
+
topup_number,
|
|
996
|
+
stage_token,
|
|
997
|
+
authentication_id: "",
|
|
998
|
+
encrypted_payment_token,
|
|
999
|
+
token: "",
|
|
1000
|
+
token_confirmation: "",
|
|
1001
|
+
access_token: accessToken,
|
|
1002
|
+
wallet_number: "",
|
|
1003
|
+
encrypted_authentication_id,
|
|
1004
|
+
additional_data: {
|
|
1005
|
+
original_price: item.item_price,
|
|
1006
|
+
is_spend_limit_temporary: false,
|
|
1007
|
+
migration_type: "",
|
|
1008
|
+
akrab_m2m_group_id: "false",
|
|
1009
|
+
spend_limit_amount: 0,
|
|
1010
|
+
is_spend_limit: false,
|
|
1011
|
+
mission_id: "",
|
|
1012
|
+
tax: 0,
|
|
1013
|
+
quota_bonus: 0,
|
|
1014
|
+
cashtag: "",
|
|
1015
|
+
is_family_plan: false,
|
|
1016
|
+
combo_details: [],
|
|
1017
|
+
is_switch_plan: false,
|
|
1018
|
+
discount_recurring: 0,
|
|
1019
|
+
is_akrab_m2m: false,
|
|
1020
|
+
balance_type: "PREPAID_BALANCE",
|
|
1021
|
+
has_bonus: false,
|
|
1022
|
+
discount_promo: 0
|
|
1023
|
+
},
|
|
1024
|
+
total_amount: price,
|
|
1025
|
+
is_using_autobuy: false,
|
|
1026
|
+
items
|
|
1027
|
+
};
|
|
1028
|
+
const [encrypted, xSig] = await Promise.all([
|
|
1029
|
+
encryptSignXData("POST", settlementPath, idToken, settlementPayload),
|
|
1030
|
+
makeXSignaturePayment(accessToken, timestamp, payment_targets, token_payment, "BALANCE", paymentFor, settlementPath)
|
|
1031
|
+
]);
|
|
1032
|
+
const xtimeRaw = encrypted.encrypted_body?.xtime;
|
|
1033
|
+
const sigTimeSec = Math.floor(Number(xtimeRaw) / 1000);
|
|
1034
|
+
const apiHost = BASE_API_URL.replace(/^https?:\/\//, "").replace(/\/$/, "");
|
|
1035
|
+
const headers = {
|
|
1036
|
+
host: apiHost,
|
|
1037
|
+
"content-type": "application/json; charset=utf-8",
|
|
1038
|
+
"user-agent": UA,
|
|
1039
|
+
"x-api-key": API_KEY,
|
|
1040
|
+
authorization: `Bearer ${idToken}`,
|
|
1041
|
+
"x-hv": "v3",
|
|
1042
|
+
"x-signature-time": String(sigTimeSec),
|
|
1043
|
+
"x-signature": xSig,
|
|
1044
|
+
"x-request-id": uuidv44(),
|
|
1045
|
+
"x-request-at": javaLikeTimestamp(DateTime4.fromSeconds(sigTimeSec, { zone: "utc" }).setZone("local")),
|
|
1046
|
+
"x-version-app": X_APP_VERSION
|
|
1047
|
+
};
|
|
1048
|
+
const url = `${BASE_API_URL.replace(/\/$/, "")}/${settlementPath}`;
|
|
1049
|
+
const resp = await axios4.post(url, encrypted.encrypted_body, { headers, timeout: 30000 });
|
|
1050
|
+
const { xdata, xtime } = resp.data;
|
|
1051
|
+
const decryptedXData = await decryptXData2(xdata, xtime);
|
|
1052
|
+
return decryptedXData;
|
|
1053
|
+
}
|
|
1054
|
+
// src/payments/ewallet.ts
|
|
1055
|
+
init_encrypt();
|
|
1056
|
+
init_utils();
|
|
1057
|
+
init_config();
|
|
1058
|
+
import axios5 from "axios";
|
|
1059
|
+
import { v4 as uuidv45 } from "uuid";
|
|
1060
|
+
import { DateTime as DateTime5 } from "luxon";
|
|
1061
|
+
var EWalletProviderEnum;
|
|
1062
|
+
((EWalletProviderEnum2) => {
|
|
1063
|
+
EWalletProviderEnum2["DANA"] = "DANA";
|
|
1064
|
+
EWalletProviderEnum2["ShopeePay"] = "SHOPEEPAY";
|
|
1065
|
+
EWalletProviderEnum2["GoPay"] = "GOPAY";
|
|
1066
|
+
EWalletProviderEnum2["OVO"] = "OVO";
|
|
1067
|
+
})(EWalletProviderEnum ||= {});
|
|
1068
|
+
async function settlementEWallet({
|
|
1069
|
+
idToken,
|
|
1070
|
+
accessToken,
|
|
1071
|
+
item,
|
|
1072
|
+
items,
|
|
1073
|
+
paymentFor,
|
|
1074
|
+
tokenConfirmation,
|
|
1075
|
+
topup_number = "",
|
|
1076
|
+
walletNumber = "",
|
|
1077
|
+
stage_token = "",
|
|
1078
|
+
overwriteAmount = null,
|
|
1079
|
+
paymentTargetsMethodsOption,
|
|
1080
|
+
paymentMethod
|
|
1081
|
+
}) {
|
|
1082
|
+
const payment_targets = items.map((item2) => item2.item_code).join(";");
|
|
1083
|
+
await interceptPage(idToken, item.item_code, false);
|
|
1084
|
+
const paymentRes = await sendApiRequest("payments/api/v8/payment-methods-option", {
|
|
1085
|
+
payment_type: "PURCHASE",
|
|
1086
|
+
is_enterprise: false,
|
|
1087
|
+
payment_target: paymentTargetsMethodsOption ?? item.item_code,
|
|
1088
|
+
lang: "en",
|
|
1089
|
+
is_referral: false,
|
|
1090
|
+
token_confirmation: tokenConfirmation
|
|
1091
|
+
}, idToken, "POST");
|
|
1092
|
+
const { token_payment, timestamp } = paymentRes.data;
|
|
1093
|
+
const price = overwriteAmount === 0 ? 0 : item.item_price;
|
|
1094
|
+
const settlementPath = "payments/api/v8/settlement-multipayment/ewallet";
|
|
1095
|
+
const settlementPayload = {
|
|
1096
|
+
akrab: {
|
|
1097
|
+
akrab_members: [],
|
|
1098
|
+
akrab_parent_alias: "",
|
|
1099
|
+
members: []
|
|
1100
|
+
},
|
|
1101
|
+
can_trigger_rating: false,
|
|
1102
|
+
total_discount: 0,
|
|
1103
|
+
coupon: "",
|
|
1104
|
+
payment_for: paymentFor,
|
|
1105
|
+
topup_number,
|
|
1106
|
+
stage_token,
|
|
1107
|
+
is_enterprise: false,
|
|
1108
|
+
autobuy: {
|
|
1109
|
+
is_using_autobuy: false,
|
|
1110
|
+
activated_autobuy_code: "",
|
|
1111
|
+
autobuy_threshold_setting: {
|
|
1112
|
+
label: "",
|
|
1113
|
+
type: "",
|
|
1114
|
+
value: 0
|
|
1115
|
+
}
|
|
1116
|
+
},
|
|
1117
|
+
access_token: accessToken,
|
|
1118
|
+
is_myxl_wallet: false,
|
|
1119
|
+
wallet_number: walletNumber,
|
|
1120
|
+
additional_data: {},
|
|
1121
|
+
total_amount: price,
|
|
1122
|
+
total_fee: 0,
|
|
1123
|
+
is_use_point: false,
|
|
1124
|
+
lang: "en",
|
|
1125
|
+
items,
|
|
1126
|
+
verification_token: token_payment,
|
|
1127
|
+
payment_method: paymentMethod,
|
|
1128
|
+
timestamp
|
|
1129
|
+
};
|
|
1130
|
+
const encrypted = await encryptSignXData("POST", settlementPath, idToken, settlementPayload);
|
|
1131
|
+
const xtimeRaw = encrypted.encrypted_body?.xtime;
|
|
1132
|
+
const sigTimeSec = Math.floor((typeof xtimeRaw === "string" ? parseInt(xtimeRaw) : Number(xtimeRaw)) / 1000);
|
|
1133
|
+
const xSig = await makeXSignaturePayment(accessToken, timestamp, payment_targets, token_payment, paymentMethod, paymentFor, settlementPath);
|
|
1134
|
+
const headers = {
|
|
1135
|
+
host: BASE_API_URL.replace("https://", ""),
|
|
1136
|
+
"content-type": "application/json; charset=utf-8",
|
|
1137
|
+
"user-agent": UA,
|
|
1138
|
+
"x-api-key": API_KEY,
|
|
1139
|
+
authorization: `Bearer ${idToken}`,
|
|
1140
|
+
"x-hv": "v3",
|
|
1141
|
+
"x-signature-time": String(sigTimeSec),
|
|
1142
|
+
"x-signature": xSig,
|
|
1143
|
+
"x-request-id": uuidv45(),
|
|
1144
|
+
"x-request-at": javaLikeTimestamp(DateTime5.fromSeconds(sigTimeSec, { zone: "utc" }).setZone("local")),
|
|
1145
|
+
"x-version-app": X_APP_VERSION
|
|
1146
|
+
};
|
|
1147
|
+
const url = `${BASE_API_URL}/${settlementPath}`;
|
|
1148
|
+
const resp = await axios5.post(url, encrypted.encrypted_body, { headers, timeout: 30000 });
|
|
1149
|
+
const decryptedXData = await decryptXData2(resp.data.xdata, resp.data.xtime);
|
|
1150
|
+
return decryptedXData;
|
|
1151
|
+
}
|
|
1152
|
+
// src/payments/qris.ts
|
|
1153
|
+
init_encrypt();
|
|
1154
|
+
init_utils();
|
|
1155
|
+
init_config();
|
|
1156
|
+
import axios6 from "axios";
|
|
1157
|
+
import { v4 as uuidv46 } from "uuid";
|
|
1158
|
+
import { DateTime as DateTime6 } from "luxon";
|
|
1159
|
+
async function settlementQris({
|
|
1160
|
+
idToken,
|
|
1161
|
+
accessToken,
|
|
1162
|
+
item,
|
|
1163
|
+
items,
|
|
1164
|
+
paymentFor,
|
|
1165
|
+
tokenConfirmation,
|
|
1166
|
+
topup_number = "",
|
|
1167
|
+
stage_token = "",
|
|
1168
|
+
overwriteAmount = null,
|
|
1169
|
+
paymentTargetsMethodsOption
|
|
1170
|
+
}) {
|
|
1171
|
+
const payment_targets = items.map((item2) => item2.item_code).join(";");
|
|
1172
|
+
await interceptPage(idToken, item.item_code, false);
|
|
1173
|
+
const paymentRes = await sendApiRequest("payments/api/v8/payment-methods-option", {
|
|
1174
|
+
payment_type: "PURCHASE",
|
|
1175
|
+
is_enterprise: false,
|
|
1176
|
+
payment_target: paymentTargetsMethodsOption ?? item.item_code,
|
|
1177
|
+
lang: "en",
|
|
1178
|
+
is_referral: false,
|
|
1179
|
+
token_confirmation: tokenConfirmation
|
|
1180
|
+
}, idToken, "POST");
|
|
1181
|
+
const { token_payment, timestamp } = paymentRes.data;
|
|
1182
|
+
const price = overwriteAmount === 0 ? 0 : item.item_price;
|
|
1183
|
+
const settlementPath = "payments/api/v8/settlement-multipayment/qris";
|
|
1184
|
+
const settlementPayload = {
|
|
1185
|
+
akrab: {
|
|
1186
|
+
akrab_members: [],
|
|
1187
|
+
akrab_parent_alias: "",
|
|
1188
|
+
members: []
|
|
1189
|
+
},
|
|
1190
|
+
can_trigger_rating: false,
|
|
1191
|
+
total_discount: 0,
|
|
1192
|
+
coupon: "",
|
|
1193
|
+
payment_for: paymentFor,
|
|
1194
|
+
topup_number,
|
|
1195
|
+
stage_token,
|
|
1196
|
+
is_enterprise: false,
|
|
1197
|
+
autobuy: {
|
|
1198
|
+
is_using_autobuy: false,
|
|
1199
|
+
activated_autobuy_code: "",
|
|
1200
|
+
autobuy_threshold_setting: {
|
|
1201
|
+
label: "",
|
|
1202
|
+
type: "",
|
|
1203
|
+
value: 0
|
|
1204
|
+
}
|
|
1205
|
+
},
|
|
1206
|
+
access_token: accessToken,
|
|
1207
|
+
is_myxl_wallet: false,
|
|
1208
|
+
additional_data: {
|
|
1209
|
+
original_price: item.item_price,
|
|
1210
|
+
is_spend_limit_temporary: false,
|
|
1211
|
+
migration_type: "",
|
|
1212
|
+
spend_limit_amount: 0,
|
|
1213
|
+
is_spend_limit: false,
|
|
1214
|
+
tax: 0,
|
|
1215
|
+
benefit_type: "",
|
|
1216
|
+
quota_bonus: 0,
|
|
1217
|
+
cashtag: "",
|
|
1218
|
+
is_family_plan: false,
|
|
1219
|
+
combo_details: [],
|
|
1220
|
+
is_switch_plan: false,
|
|
1221
|
+
discount_recurring: 0,
|
|
1222
|
+
has_bonus: false,
|
|
1223
|
+
discount_promo: 0
|
|
1224
|
+
},
|
|
1225
|
+
total_amount: price,
|
|
1226
|
+
total_fee: 0,
|
|
1227
|
+
is_use_point: false,
|
|
1228
|
+
lang: "en",
|
|
1229
|
+
items,
|
|
1230
|
+
verification_token: token_payment,
|
|
1231
|
+
payment_method: "QRIS",
|
|
1232
|
+
timestamp
|
|
1233
|
+
};
|
|
1234
|
+
const encrypted = await encryptSignXData("POST", settlementPath, idToken, settlementPayload);
|
|
1235
|
+
const xtimeRaw = encrypted.encrypted_body?.xtime;
|
|
1236
|
+
const sigTimeSec = Math.floor((typeof xtimeRaw === "string" ? parseInt(xtimeRaw) : Number(xtimeRaw)) / 1000);
|
|
1237
|
+
const xSig = await makeXSignaturePayment(accessToken, timestamp, payment_targets, token_payment, "QRIS", paymentFor, settlementPath);
|
|
1238
|
+
const headers = {
|
|
1239
|
+
host: BASE_API_URL.replace("https://", ""),
|
|
1240
|
+
"content-type": "application/json; charset=utf-8",
|
|
1241
|
+
"user-agent": UA,
|
|
1242
|
+
"x-api-key": API_KEY,
|
|
1243
|
+
authorization: `Bearer ${idToken}`,
|
|
1244
|
+
"x-hv": "v3",
|
|
1245
|
+
"x-signature-time": String(sigTimeSec),
|
|
1246
|
+
"x-signature": xSig,
|
|
1247
|
+
"x-request-id": uuidv46(),
|
|
1248
|
+
"x-request-at": javaLikeTimestamp(DateTime6.fromSeconds(sigTimeSec, { zone: "utc" }).setZone("local")),
|
|
1249
|
+
"x-version-app": X_APP_VERSION
|
|
1250
|
+
};
|
|
1251
|
+
const url = `${BASE_API_URL}/${settlementPath}`;
|
|
1252
|
+
const resp = await axios6.post(url, encrypted.encrypted_body, { headers, timeout: 30000 });
|
|
1253
|
+
const decryptedXData = await decryptXData2(resp.data.xdata, resp.data.xtime);
|
|
1254
|
+
return decryptedXData;
|
|
1255
|
+
}
|
|
1256
|
+
// src/profile.ts
|
|
1257
|
+
init_utils();
|
|
1258
|
+
var exports_profile = {};
|
|
1259
|
+
__export(exports_profile, {
|
|
1260
|
+
getPendingTransaction: () => getPendingTransaction
|
|
1261
|
+
});
|
|
1262
|
+
async function getPendingTransaction(idToken) {
|
|
1263
|
+
const path = "api/v8/profile";
|
|
1264
|
+
const payload = {
|
|
1265
|
+
is_enterprise: false,
|
|
1266
|
+
lang: "en"
|
|
1267
|
+
};
|
|
1268
|
+
const res = await sendApiRequest(path, payload, idToken, "POST");
|
|
1269
|
+
return res.data;
|
|
1270
|
+
}
|
|
1271
|
+
// src/@types/payment.ts
|
|
1272
|
+
var exports_payment = {};
|
|
1273
|
+
__export(exports_payment, {
|
|
1274
|
+
PaymentMethodEnum: () => PaymentMethodEnum
|
|
1275
|
+
});
|
|
1276
|
+
var PaymentMethodEnum;
|
|
1277
|
+
((PaymentMethodEnum2) => {
|
|
1278
|
+
PaymentMethodEnum2["Pulsa"] = "BALANCE";
|
|
1279
|
+
PaymentMethodEnum2["EWallet"] = "EWALLET";
|
|
1280
|
+
PaymentMethodEnum2["QRIS"] = "QRIS";
|
|
1281
|
+
PaymentMethodEnum2["PulsaDecoy"] = "BALANCE_DECOY";
|
|
1282
|
+
PaymentMethodEnum2["PulsaDecoyV2"] = "BALANCE_DECOY_V2";
|
|
1283
|
+
PaymentMethodEnum2["QRISDecoy"] = "QRIS_DECOY";
|
|
1284
|
+
PaymentMethodEnum2["QRISDecoyV2"] = "QRIS_DECOY_V2";
|
|
1285
|
+
PaymentMethodEnum2["PulsaN"] = "BALANCE_N";
|
|
1286
|
+
})(PaymentMethodEnum ||= {});
|
|
1287
|
+
|
|
1288
|
+
// src/index.ts
|
|
1289
|
+
init_utils();
|
|
1290
|
+
|
|
1291
|
+
// src/verification.ts
|
|
1292
|
+
init_utils();
|
|
1293
|
+
var exports_verification = {};
|
|
1294
|
+
__export(exports_verification, {
|
|
1295
|
+
validatePuk: () => validatePuk,
|
|
1296
|
+
checkDukcapil: () => checkDukcapil
|
|
1297
|
+
});
|
|
1298
|
+
async function validatePuk(msisdn, puk) {
|
|
1299
|
+
const path = "api/v8/infos/validate-puk";
|
|
1300
|
+
const payload = {
|
|
1301
|
+
is_enterprise: false,
|
|
1302
|
+
puk,
|
|
1303
|
+
is_enc: false,
|
|
1304
|
+
msisdn,
|
|
1305
|
+
lang: "en"
|
|
1306
|
+
};
|
|
1307
|
+
return sendApiRequest(path, payload, "", "POST");
|
|
1308
|
+
}
|
|
1309
|
+
async function checkDukcapil(msisdn, kk, nik) {
|
|
1310
|
+
const path = "api/v8/auth/regist/dukcapil";
|
|
1311
|
+
const payload = {
|
|
1312
|
+
msisdn,
|
|
1313
|
+
kk,
|
|
1314
|
+
nik,
|
|
1315
|
+
lang: "en"
|
|
1316
|
+
};
|
|
1317
|
+
return sendApiRequest(path, payload, "", "POST");
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// src/index.ts
|
|
1321
|
+
init_encrypt_helper();
|
|
1322
|
+
|
|
1323
|
+
// src/lib/payment.ts
|
|
1324
|
+
init_utils();
|
|
1325
|
+
var exports_payment2 = {};
|
|
1326
|
+
__export(exports_payment2, {
|
|
1327
|
+
getTransactionDetail: () => getTransactionDetail
|
|
1328
|
+
});
|
|
1329
|
+
async function getTransactionDetail({
|
|
1330
|
+
idToken,
|
|
1331
|
+
transactionId
|
|
1332
|
+
}) {
|
|
1333
|
+
const path = "payments/api/v8/pending-detail";
|
|
1334
|
+
const payload = {
|
|
1335
|
+
transaction_id: transactionId,
|
|
1336
|
+
is_enterprise: false,
|
|
1337
|
+
lang: "en",
|
|
1338
|
+
status: ""
|
|
1339
|
+
};
|
|
1340
|
+
const res = await sendApiRequest(path, payload, idToken, "POST");
|
|
1341
|
+
return res.data;
|
|
1342
|
+
}
|
|
1343
|
+
// src/lib/decoy.ts
|
|
1344
|
+
var exports_decoy = {};
|
|
1345
|
+
__export(exports_decoy, {
|
|
1346
|
+
getDecoyName: () => getDecoyName,
|
|
1347
|
+
getDecoyData: () => getDecoyData,
|
|
1348
|
+
decoyIsExits: () => decoyIsExits
|
|
1349
|
+
});
|
|
1350
|
+
// src/data/decoys/decoy-default-balance.json
|
|
1351
|
+
var decoy_default_balance_default = {
|
|
1352
|
+
family_name: "XL PASS",
|
|
1353
|
+
family_code: "b0a20d74-0c54-4e3b-8f3f-01e7482e50bf",
|
|
1354
|
+
is_enterprise: true,
|
|
1355
|
+
migration_type: "NONE",
|
|
1356
|
+
variant_code: "719d093f-6f8d-46a4-8390-6a0003a172ea",
|
|
1357
|
+
option_name: "XL PASS 30 days",
|
|
1358
|
+
order: 1,
|
|
1359
|
+
price: 889750
|
|
1360
|
+
};
|
|
1361
|
+
// src/data/decoys/decoy-default-qris.json
|
|
1362
|
+
var decoy_default_qris_default = {
|
|
1363
|
+
family_name: "",
|
|
1364
|
+
family_code: "580c1f94-7dc4-416e-96f6-8faf26567516",
|
|
1365
|
+
is_enterprise: false,
|
|
1366
|
+
migration_type: "NONE",
|
|
1367
|
+
variant_code: "b50f954a-696e-46d0-8700-8e4d38521525",
|
|
1368
|
+
option_name: "",
|
|
1369
|
+
order: 27,
|
|
1370
|
+
price: 1000
|
|
1371
|
+
};
|
|
1372
|
+
// src/data/decoys/decoy-default-qris0.json
|
|
1373
|
+
var decoy_default_qris0_default = {
|
|
1374
|
+
family_name: "Kuota Aplikasi BIZ 2GB",
|
|
1375
|
+
family_code: "c6f2cd72-8b21-420a-b8d5-e0186afe5be6",
|
|
1376
|
+
is_enterprise: true,
|
|
1377
|
+
migration_type: "NONE",
|
|
1378
|
+
variant_code: "b7cf278e-c989-4760-8a26-0a20c1a47a40",
|
|
1379
|
+
option_name: "Vidio 2GB",
|
|
1380
|
+
order: 11,
|
|
1381
|
+
price: 0
|
|
1382
|
+
};
|
|
1383
|
+
// src/data/decoys/decoy-prio-balance.json
|
|
1384
|
+
var decoy_prio_balance_default = {
|
|
1385
|
+
family_name: "PRIO PASS",
|
|
1386
|
+
family_code: "2512b72a-a3cd-4c70-a736-132cf2c1f0c0",
|
|
1387
|
+
is_enterprise: null,
|
|
1388
|
+
migration_type: null,
|
|
1389
|
+
variant_code: "cff298bd-8ec8-4696-b689-12407d36be15",
|
|
1390
|
+
option_name: "PRIO PASS 30 days",
|
|
1391
|
+
order: 1,
|
|
1392
|
+
price: 999000
|
|
1393
|
+
};
|
|
1394
|
+
// src/data/decoys/decoy-prio-qris.json
|
|
1395
|
+
var decoy_prio_qris_default = {
|
|
1396
|
+
family_name: "Conference",
|
|
1397
|
+
family_code: "5dab52d5-6f02-4678-b72f-088396ceb113",
|
|
1398
|
+
is_enterprise: true,
|
|
1399
|
+
migration_type: "PRIOH_TO_PRIO",
|
|
1400
|
+
variant_code: "bf84ad5b-87e9-4769-9bd2-2359535c05e4",
|
|
1401
|
+
option_name: "Conference 2GB",
|
|
1402
|
+
order: 1,
|
|
1403
|
+
price: 2000
|
|
1404
|
+
};
|
|
1405
|
+
// src/data/decoys/decoy-prio-qris0.json
|
|
1406
|
+
var decoy_prio_qris0_default = {
|
|
1407
|
+
family_name: "Conference",
|
|
1408
|
+
family_code: "5dab52d5-6f02-4678-b72f-088396ceb113",
|
|
1409
|
+
is_enterprise: true,
|
|
1410
|
+
migration_type: "PRIOH_TO_PRIO",
|
|
1411
|
+
variant_code: "bf84ad5b-87e9-4769-9bd2-2359535c05e4",
|
|
1412
|
+
option_name: "Conference 2GB",
|
|
1413
|
+
order: 1,
|
|
1414
|
+
price: 2000
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
// src/lib/decoy.ts
|
|
1418
|
+
var needPrioDecoys = ["PRIORITAS", "PRIOHYBRID", "GO"];
|
|
1419
|
+
var getDecoyName = (paymentMethod) => {
|
|
1420
|
+
switch (paymentMethod) {
|
|
1421
|
+
case "BALANCE_DECOY" /* PulsaDecoy */:
|
|
1422
|
+
return "balance";
|
|
1423
|
+
case "BALANCE_DECOY_V2" /* PulsaDecoyV2 */:
|
|
1424
|
+
return "balance";
|
|
1425
|
+
case "QRIS_DECOY" /* QRISDecoy */:
|
|
1426
|
+
return "qris";
|
|
1427
|
+
case "QRIS_DECOY_V2" /* QRISDecoyV2 */:
|
|
1428
|
+
return "qris0";
|
|
1429
|
+
default:
|
|
1430
|
+
return "balance";
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
var decoyIsExits = (paymentMethod) => {
|
|
1434
|
+
return [
|
|
1435
|
+
"BALANCE_DECOY" /* PulsaDecoy */,
|
|
1436
|
+
"BALANCE_DECOY_V2" /* PulsaDecoyV2 */,
|
|
1437
|
+
"QRIS_DECOY" /* QRISDecoy */,
|
|
1438
|
+
"QRIS_DECOY_V2" /* QRISDecoyV2 */
|
|
1439
|
+
].includes(paymentMethod);
|
|
1440
|
+
};
|
|
1441
|
+
var decoyMap = {
|
|
1442
|
+
prio: {
|
|
1443
|
+
balance: decoy_prio_balance_default,
|
|
1444
|
+
qris: decoy_prio_qris_default,
|
|
1445
|
+
qris0: decoy_prio_qris0_default
|
|
1446
|
+
},
|
|
1447
|
+
default: {
|
|
1448
|
+
balance: decoy_default_balance_default,
|
|
1449
|
+
qris: decoy_default_qris_default,
|
|
1450
|
+
qris0: decoy_default_qris0_default
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
var getDecoyData = ({
|
|
1454
|
+
subscriptionType,
|
|
1455
|
+
decoy
|
|
1456
|
+
}) => {
|
|
1457
|
+
const isPrio = needPrioDecoys.includes(subscriptionType);
|
|
1458
|
+
const group = isPrio ? "prio" : "default";
|
|
1459
|
+
return decoyMap[group][decoy];
|
|
1460
|
+
};
|
|
1461
|
+
// src/payments/decoy.ts
|
|
1462
|
+
var exports_decoy2 = {};
|
|
1463
|
+
__export(exports_decoy2, {
|
|
1464
|
+
default: () => decoy_default
|
|
1465
|
+
});
|
|
1466
|
+
var decoy_default = undefined;
|
|
1467
|
+
export {
|
|
1468
|
+
exports_verification as Verification,
|
|
1469
|
+
exports_utils as Utils,
|
|
1470
|
+
exports_payment as Types,
|
|
1471
|
+
exports_profile as Profile,
|
|
1472
|
+
exports_decoy2 as PaymentsDecoy,
|
|
1473
|
+
exports_payments as Payments,
|
|
1474
|
+
exports_payment2 as Payment,
|
|
1475
|
+
exports_package as Package,
|
|
1476
|
+
exports_notification as Notification,
|
|
1477
|
+
exports_family_plan as FamilyPlan,
|
|
1478
|
+
exports_family as Family,
|
|
1479
|
+
exports_encrypt_helper as EncryptHelper,
|
|
1480
|
+
exports_encrypt as Encrypt,
|
|
1481
|
+
exports_device as Device,
|
|
1482
|
+
exports_decoy as Decoy,
|
|
1483
|
+
exports_config as Config,
|
|
1484
|
+
exports_client as Client,
|
|
1485
|
+
exports_ciam as Ciam,
|
|
1486
|
+
exports_auth as Auth
|
|
1487
|
+
};
|