@nakamura-123/pages 1.1.8 → 1.1.9
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.
|
@@ -52,6 +52,7 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
|
|
|
52
52
|
return [4 /*yield*/, (0, expo_iap_1.initConnection)()];
|
|
53
53
|
case 1:
|
|
54
54
|
result = _a.sent();
|
|
55
|
+
console.log("IAP接続結果: ", result);
|
|
55
56
|
itemSkus = paymentItems || [];
|
|
56
57
|
console.log("Item SKUs: ", itemSkus);
|
|
57
58
|
if (!(itemSkus.length > 0)) return [3 /*break*/, 3];
|
|
@@ -59,6 +60,12 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
|
|
|
59
60
|
case 2:
|
|
60
61
|
productList = _a.sent();
|
|
61
62
|
console.log("Product List: ", productList);
|
|
63
|
+
console.log("商品数: ", productList.length);
|
|
64
|
+
productList.forEach(function (product, index) {
|
|
65
|
+
console.log("\u5546\u54C1[".concat(index, "] ID: "), product.id);
|
|
66
|
+
console.log("\u5546\u54C1[".concat(index, "] Title: "), product.title);
|
|
67
|
+
console.log("\u5546\u54C1[".concat(index, "] productId: "), product.productId);
|
|
68
|
+
});
|
|
62
69
|
setProducts && setProducts(productList);
|
|
63
70
|
return [3 /*break*/, 4];
|
|
64
71
|
case 3:
|
|
@@ -67,7 +74,8 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
|
|
|
67
74
|
case 4: return [3 /*break*/, 7];
|
|
68
75
|
case 5:
|
|
69
76
|
err_1 = _a.sent();
|
|
70
|
-
console.
|
|
77
|
+
console.error("IAP Initialization Error: ", err_1);
|
|
78
|
+
console.error("エラーの詳細: ", err_1 instanceof Error ? err_1.message : String(err_1));
|
|
71
79
|
return [3 /*break*/, 7];
|
|
72
80
|
case 6:
|
|
73
81
|
setLoading && setLoading(false);
|
|
@@ -79,149 +87,291 @@ var initializeIAP = function (paymentItems, setProducts, setLoading) { return __
|
|
|
79
87
|
exports.initializeIAP = initializeIAP;
|
|
80
88
|
// 11. 購入処理
|
|
81
89
|
var handlePurchase = function (productId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
82
|
-
var purchase, receipt, isValid, err_2;
|
|
83
90
|
return __generator(this, function (_a) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
91
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
92
|
+
console.log("購入開始: ", productId);
|
|
93
|
+
// リスナーを設定
|
|
94
|
+
var purchaseUpdateSubscription = (0, expo_iap_1.purchaseUpdatedListener)(function (purchase) {
|
|
95
|
+
console.log("購入成功レスポンス: ", purchase);
|
|
96
|
+
purchaseUpdateSubscription.remove();
|
|
97
|
+
purchaseErrorSubscription.remove();
|
|
98
|
+
// 購入データの検証
|
|
99
|
+
if (!purchase) {
|
|
100
|
+
reject(new Error("無効な購入応答"));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
resolve(purchase);
|
|
104
|
+
});
|
|
105
|
+
var purchaseErrorSubscription = (0, expo_iap_1.purchaseErrorListener)(function (error) {
|
|
106
|
+
console.log("購入エラーレスポンス: ", error);
|
|
107
|
+
purchaseUpdateSubscription.remove();
|
|
108
|
+
purchaseErrorSubscription.remove();
|
|
109
|
+
reject(error);
|
|
110
|
+
});
|
|
111
|
+
// 購入リクエストを開始(結果はリスナーで受け取る)
|
|
112
|
+
(0, expo_iap_1.requestPurchase)({
|
|
113
|
+
request: {
|
|
114
|
+
ios: { sku: productId },
|
|
115
|
+
android: { skus: [productId] },
|
|
116
|
+
},
|
|
117
|
+
type: "inapp",
|
|
118
|
+
}).catch(function (error) {
|
|
119
|
+
console.error("購入リクエスト開始エラー: ", error);
|
|
120
|
+
purchaseUpdateSubscription.remove();
|
|
121
|
+
purchaseErrorSubscription.remove();
|
|
122
|
+
reject(error);
|
|
123
|
+
});
|
|
124
|
+
})
|
|
125
|
+
.then(function (purchase) { return __awaiter(void 0, void 0, void 0, function () {
|
|
126
|
+
var receipt, isValid;
|
|
127
|
+
return __generator(this, function (_a) {
|
|
128
|
+
switch (_a.label) {
|
|
129
|
+
case 0:
|
|
130
|
+
console.log("購入検証開始: ", purchase);
|
|
131
|
+
receipt = purchase.transactionReceipt || purchase.purchaseToken;
|
|
132
|
+
if (!receipt) {
|
|
133
|
+
throw new Error("レシートデータが無効です");
|
|
134
|
+
}
|
|
135
|
+
isValid = (0, ReceiptFnc_1.validatePurchaseClientSide)(receipt, react_native_1.Platform.OS);
|
|
136
|
+
if (!isValid) {
|
|
137
|
+
throw new Error("購入検証に失敗しました");
|
|
138
|
+
}
|
|
139
|
+
if (!(react_native_1.Platform.OS === "android" &&
|
|
140
|
+
(0, exports.getAndroidPurchaseState)(purchase) === "wait")) return [3 /*break*/, 1];
|
|
141
|
+
alert("手続きが完了しました。支払いが完了したら、このページにある「以前購入した方はこちらから復元」をタップしてください。");
|
|
142
|
+
return [3 /*break*/, 3];
|
|
143
|
+
case 1: return [4 /*yield*/, (0, expo_iap_1.finishTransaction)({ purchase: purchase, isConsumable: false })];
|
|
144
|
+
case 2:
|
|
145
|
+
_a.sent();
|
|
146
|
+
alert("購入が完了しました!");
|
|
147
|
+
_a.label = 3;
|
|
148
|
+
case 3: return [2 /*return*/, purchase]; // 成功時に購入データを返す
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}); })
|
|
152
|
+
.catch(function (err) {
|
|
119
153
|
// エラー処理を整理
|
|
154
|
+
console.error("購入エラーの詳細: ", err);
|
|
155
|
+
console.error("エラーメッセージ: ", err instanceof Error ? err.message : String(err));
|
|
156
|
+
console.error("エラーコード: ", err === null || err === void 0 ? void 0 : err.code);
|
|
157
|
+
// ユーザーがキャンセルした場合は静かに終了
|
|
158
|
+
if ((err === null || err === void 0 ? void 0 : err.code) === "E_USER_CANCELLED" ||
|
|
159
|
+
(err === null || err === void 0 ? void 0 : err.code) === "user-cancelled") {
|
|
160
|
+
console.log("ユーザーが購入をキャンセルしました");
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
120
163
|
// dispatch(
|
|
121
|
-
// pushCoinError({ title: "購入処理中にエラーが発生しました", log:
|
|
164
|
+
// pushCoinError({ title: "購入処理中にエラーが発生しました", log:jerr })
|
|
122
165
|
// );
|
|
123
166
|
alert("購入に失敗しました。\nしばらく時間を置いた後、もう一度実行してみてください。もしそれでも購入できない場合は「よくある質問」をご確認いただくか、必要に応じて「お問い合わせフォーム」からご連絡ください。");
|
|
124
|
-
return
|
|
125
|
-
|
|
126
|
-
}
|
|
167
|
+
return null; // 失敗時はnullを返す
|
|
168
|
+
})];
|
|
127
169
|
});
|
|
128
170
|
}); };
|
|
129
171
|
exports.handlePurchase = handlePurchase;
|
|
130
172
|
// 21. 購入復元
|
|
131
173
|
var restorePurchases = function (dispatch, isAlert) { return __awaiter(void 0, void 0, void 0, function () {
|
|
132
|
-
var purchases, receipts, _i, purchases_1, purchase, receipt, error_1;
|
|
174
|
+
var purchases, receipts, _i, purchases_1, purchase, receipt, finishError_1, itemError_1, storageError_1, hasWaitingPayment, error_1;
|
|
133
175
|
return __generator(this, function (_a) {
|
|
134
176
|
switch (_a.label) {
|
|
135
177
|
case 0:
|
|
136
|
-
_a.trys.push([0,
|
|
137
|
-
console.log("
|
|
178
|
+
_a.trys.push([0, 15, , 16]);
|
|
179
|
+
console.log("購入復元開始");
|
|
138
180
|
return [4 /*yield*/, (0, expo_iap_1.getAvailablePurchases)()];
|
|
139
181
|
case 1:
|
|
140
182
|
purchases = _a.sent();
|
|
141
|
-
console.log("
|
|
183
|
+
console.log("取得した購入アイテム: ", purchases);
|
|
184
|
+
// Androidの場合、購入状態をログ出力
|
|
185
|
+
if (react_native_1.Platform.OS === "android" && purchases.length > 0) {
|
|
186
|
+
purchases.forEach(function (purchase, index) {
|
|
187
|
+
if (purchase.platform === "android") {
|
|
188
|
+
console.log("\u8CFC\u5165\u30A2\u30A4\u30C6\u30E0[".concat(index, "] purchaseStateAndroid: "), purchase.purchaseStateAndroid);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
142
192
|
receipts = [];
|
|
143
193
|
_i = 0, purchases_1 = purchases;
|
|
144
194
|
_a.label = 2;
|
|
145
195
|
case 2:
|
|
146
|
-
if (!(_i < purchases_1.length)) return [3 /*break*/,
|
|
196
|
+
if (!(_i < purchases_1.length)) return [3 /*break*/, 10];
|
|
147
197
|
purchase = purchases_1[_i];
|
|
198
|
+
_a.label = 3;
|
|
199
|
+
case 3:
|
|
200
|
+
_a.trys.push([3, 8, , 9]);
|
|
148
201
|
receipt = (0, ReceiptFnc_1.unifyReceipt)(purchase);
|
|
149
202
|
if (receipt) {
|
|
150
|
-
|
|
203
|
+
console.log("レシート情報: ", {
|
|
204
|
+
productId: receipt.productId,
|
|
205
|
+
isPaid: receipt.isPaid,
|
|
206
|
+
paymentState: receipt.isPaid ? "paid" : "wait",
|
|
207
|
+
});
|
|
208
|
+
// 状態更新を個別にtry-catchで保護
|
|
209
|
+
try {
|
|
210
|
+
dispatch((0, exports.updateAllFreeState)(receipt));
|
|
211
|
+
}
|
|
212
|
+
catch (dispatchError) {
|
|
213
|
+
console.error("状態更新エラー(継続します): ", dispatchError);
|
|
214
|
+
}
|
|
151
215
|
receipts.push(receipt);
|
|
152
216
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
217
|
+
else {
|
|
218
|
+
console.warn("レシートの統一に失敗(スキップします): ", purchase);
|
|
219
|
+
}
|
|
220
|
+
if (!checkIsAcknowledgedAndroid(purchase)) return [3 /*break*/, 7];
|
|
157
221
|
_a.label = 4;
|
|
158
222
|
case 4:
|
|
223
|
+
_a.trys.push([4, 6, , 7]);
|
|
224
|
+
return [4 /*yield*/, (0, expo_iap_1.finishTransaction)({ purchase: purchase, isConsumable: false })];
|
|
225
|
+
case 5:
|
|
226
|
+
_a.sent();
|
|
227
|
+
console.log("トランザクション完了: ", purchase.productId);
|
|
228
|
+
return [3 /*break*/, 7];
|
|
229
|
+
case 6:
|
|
230
|
+
finishError_1 = _a.sent();
|
|
231
|
+
console.error("トランザクション完了エラー(継続します): ", finishError_1);
|
|
232
|
+
return [3 /*break*/, 7];
|
|
233
|
+
case 7: return [3 /*break*/, 9];
|
|
234
|
+
case 8:
|
|
235
|
+
itemError_1 = _a.sent();
|
|
236
|
+
console.error("購入アイテムの処理エラー(次のアイテムへ継続): ", itemError_1);
|
|
237
|
+
console.error("問題のあるアイテム: ", purchase);
|
|
238
|
+
return [3 /*break*/, 9];
|
|
239
|
+
case 9:
|
|
159
240
|
_i++;
|
|
160
241
|
return [3 /*break*/, 2];
|
|
161
|
-
case
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
242
|
+
case 10:
|
|
243
|
+
// 購入アイテムがない場合はAllFreeの状態を更新
|
|
244
|
+
if (receipts.length === 0) {
|
|
245
|
+
try {
|
|
246
|
+
dispatch((0, exports.updateAllFreeState)(null));
|
|
247
|
+
}
|
|
248
|
+
catch (dispatchError) {
|
|
249
|
+
console.error("状態更新エラー(null時): ", dispatchError);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (!(receipts.length > 0)) return [3 /*break*/, 14];
|
|
253
|
+
_a.label = 11;
|
|
254
|
+
case 11:
|
|
255
|
+
_a.trys.push([11, 13, , 14]);
|
|
165
256
|
return [4 /*yield*/, stores_1.coinStorage.replacePurchasedItems(receipts)];
|
|
166
|
-
case
|
|
257
|
+
case 12:
|
|
167
258
|
_a.sent();
|
|
168
|
-
|
|
169
|
-
case
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
259
|
+
return [3 /*break*/, 14];
|
|
260
|
+
case 13:
|
|
261
|
+
storageError_1 = _a.sent();
|
|
262
|
+
console.error("ストレージ保存エラー: ", storageError_1);
|
|
263
|
+
return [3 /*break*/, 14];
|
|
264
|
+
case 14:
|
|
265
|
+
console.log("購入復元完了: ", receipts.length, "件");
|
|
266
|
+
// アラート表示(支払い待ち状態を考慮)
|
|
267
|
+
if (isAlert) {
|
|
268
|
+
try {
|
|
269
|
+
if (receipts.length === 0) {
|
|
270
|
+
alert("購入済みのアイテムがありませんでした");
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
hasWaitingPayment = receipts.some(function (receipt) { return receipt && !receipt.isPaid; });
|
|
274
|
+
if (hasWaitingPayment) {
|
|
275
|
+
alert("お支払い手続き中です。\n\n支払いが完了したら、このページにある「以前購入した方はこちらから復元」をタップしてください。");
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
alert("購入アイテムを復元しました!");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (alertError) {
|
|
283
|
+
console.error("アラート表示エラー: ", alertError);
|
|
284
|
+
// アラート表示に失敗してもクラッシュさせない
|
|
285
|
+
}
|
|
286
|
+
}
|
|
174
287
|
return [2 /*return*/, receipts]; // 復元アイテムがあればpurchasesを返す
|
|
175
|
-
case
|
|
288
|
+
case 15:
|
|
176
289
|
error_1 = _a.sent();
|
|
177
|
-
console.
|
|
290
|
+
console.error("Restore Error: ", error_1);
|
|
291
|
+
console.error("エラーの詳細: ", error_1 instanceof Error ? error_1.message : String(error_1));
|
|
178
292
|
// dispatch(pushCoinError({ title: "購入復元に失敗しました", log: error }));
|
|
179
293
|
isAlert &&
|
|
180
294
|
alert("購入アイテムの復元に失敗しました。しばらく時間を置いた後、もう一度実行してみてください。もしそれでも購入できない場合は「よくある質問」をご確認いただくか、必要に応じて「お問い合わせフォーム」からご連絡ください。");
|
|
181
295
|
return [2 /*return*/, null]; // エラーが発生した場合もnullを返す
|
|
182
|
-
case
|
|
296
|
+
case 16: return [2 /*return*/];
|
|
183
297
|
}
|
|
184
298
|
});
|
|
185
299
|
}); };
|
|
186
300
|
exports.restorePurchases = restorePurchases;
|
|
187
301
|
// 91. AllFreeの状態確認
|
|
188
302
|
var updateAllFreeState = function (receipt) { return function (dispatch, getState) {
|
|
189
|
-
var _a;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
303
|
+
var _a, _b, _c;
|
|
304
|
+
try {
|
|
305
|
+
if (receipt === null) {
|
|
306
|
+
dispatch({ type: "setting/updateAllFreeState", payload: "none" });
|
|
307
|
+
dispatch({ type: "setting/updateLastCheckedDate", payload: null });
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
var state = getState();
|
|
311
|
+
if (!state || !state.app || !state.app.appSetting) {
|
|
312
|
+
console.warn("状態が不正です: app.appSettingが存在しません");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
var freeId = (_c = (_b = (_a = state.app.appSetting.setting) === null || _a === void 0 ? void 0 : _a.payment) === null || _b === void 0 ? void 0 : _b.items) === null || _c === void 0 ? void 0 : _c.allFreeId;
|
|
316
|
+
if (!freeId) {
|
|
317
|
+
console.warn("allFreeIdが設定されていません");
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
var isPaid = receipt.isPaid, productId = receipt.productId;
|
|
321
|
+
if (!productId) {
|
|
322
|
+
console.warn("レシートにproductIdがありません");
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
var paymentState = isPaid ? "paid" : "wait";
|
|
326
|
+
if (productId === freeId) {
|
|
327
|
+
dispatch({ type: "setting/updateAllFreeState", payload: paymentState });
|
|
328
|
+
}
|
|
194
329
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
var isPaid = receipt.isPaid, productId = receipt.productId;
|
|
200
|
-
var paymentState = isPaid ? "paid" : "wait";
|
|
201
|
-
if (productId === freeId) {
|
|
202
|
-
dispatch({ type: "setting/updateAllFreeState", payload: paymentState });
|
|
330
|
+
catch (error) {
|
|
331
|
+
console.error("updateAllFreeState エラー: ", error);
|
|
332
|
+
console.error("receipt: ", receipt);
|
|
333
|
+
// エラーをthrowせずにログだけ出力
|
|
203
334
|
}
|
|
204
335
|
}; };
|
|
205
336
|
exports.updateAllFreeState = updateAllFreeState;
|
|
206
|
-
// 93. purchaseStateAndroidの判定(
|
|
337
|
+
// 93. purchaseStateAndroidの判定(1: 支払済み, 2: 支払い待ち, その他: キャンセル)
|
|
207
338
|
var getAndroidPurchaseState = function (purchase) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
case 1:
|
|
339
|
+
try {
|
|
340
|
+
if (!purchase)
|
|
341
|
+
return "canceled";
|
|
342
|
+
if (purchase.platform === "ios")
|
|
213
343
|
return "paid";
|
|
214
|
-
|
|
215
|
-
return "wait";
|
|
216
|
-
default:
|
|
344
|
+
if (purchase.platform !== "android")
|
|
217
345
|
return "canceled";
|
|
346
|
+
switch (purchase.purchaseStateAndroid) {
|
|
347
|
+
case 1:
|
|
348
|
+
return "paid";
|
|
349
|
+
case 2:
|
|
350
|
+
return "wait";
|
|
351
|
+
default:
|
|
352
|
+
return "canceled";
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
console.error("getAndroidPurchaseState エラー: ", error);
|
|
357
|
+
return "canceled";
|
|
218
358
|
}
|
|
219
359
|
};
|
|
220
360
|
exports.getAndroidPurchaseState = getAndroidPurchaseState;
|
|
221
361
|
// 94. Androidの後払いアイテムの承認をするか否か
|
|
222
362
|
var checkIsAcknowledgedAndroid = function (purchase) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
363
|
+
try {
|
|
364
|
+
if (!purchase)
|
|
365
|
+
return false;
|
|
366
|
+
if (purchase.platform === "ios")
|
|
367
|
+
return false; // iOSでは常に未承認(finishは自動で行われる)
|
|
368
|
+
if (purchase.platform !== "android")
|
|
369
|
+
return false;
|
|
370
|
+
var state = (0, exports.getAndroidPurchaseState)(purchase);
|
|
371
|
+
return state === "paid" && !purchase.isAcknowledgedAndroid;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
console.error("checkIsAcknowledgedAndroid エラー: ", error);
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
227
377
|
};
|
|
@@ -24,12 +24,20 @@ var CoinPageComponent = function (_a) {
|
|
|
24
24
|
<WaitingPayBanner_1.default currentPage="coin"/>
|
|
25
25
|
|
|
26
26
|
{products.map(function (product, index) {
|
|
27
|
+
console.log("UI\u3067\u8868\u793A\u3059\u308B\u5546\u54C1[".concat(index, "]:"), {
|
|
28
|
+
id: product.id,
|
|
29
|
+
productId: product.productId,
|
|
30
|
+
title: product.title,
|
|
31
|
+
});
|
|
27
32
|
var name = isAndroid
|
|
28
33
|
? product.nameAndroid || product.title
|
|
29
34
|
: product.title;
|
|
30
35
|
var price = product.displayPrice;
|
|
31
36
|
var title = "".concat(name, " ").concat(price);
|
|
32
|
-
return (<common_1.RectangleCard key={index} title={title} note={product.description} left={<common_1.IconInCircle name="gift"/>} color={isAllfreePaid ? "ltBlack" : "blue"} onPress={function () {
|
|
37
|
+
return (<common_1.RectangleCard key={index} title={title} note={product.description} left={<common_1.IconInCircle name="gift"/>} color={isAllfreePaid ? "ltBlack" : "blue"} onPress={function () {
|
|
38
|
+
console.log("購入前: ", product.id);
|
|
39
|
+
isAllfreePaid ? null : onPurchase(product.id);
|
|
40
|
+
}}/>);
|
|
33
41
|
})}
|
|
34
42
|
<react_native_1.View style={styles.txtContainer}>
|
|
35
43
|
<common_1.MyText fsize="sm" color="gray">
|
|
@@ -3,22 +3,52 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.validatePurchaseClientSide = exports.unifyReceipt = void 0;
|
|
4
4
|
// 01. レシートの形式を統一
|
|
5
5
|
var unifyReceipt = function (receipt) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
productId
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
try {
|
|
7
|
+
// 必須フィールドの検証
|
|
8
|
+
if (!receipt || !receipt.productId) {
|
|
9
|
+
console.warn("無効なレシートデータ: productIdが不足しています", receipt);
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (!receipt.transactionId) {
|
|
13
|
+
console.warn("無効なレシートデータ: transactionIdが不足しています", receipt);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (receipt.platform === "android") {
|
|
17
|
+
if (!receipt.purchaseToken) {
|
|
18
|
+
console.warn("無効なAndroidレシート: purchaseTokenが不足しています");
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
transactionId: receipt.transactionId,
|
|
23
|
+
productId: receipt.productId,
|
|
24
|
+
transactionDate: Number(receipt.transactionDate) || Date.now(),
|
|
25
|
+
receipt: receipt.purchaseToken,
|
|
26
|
+
isPaid: receipt.purchaseStateAndroid === 1, // 1: PURCHASED(支払済み), 2: PENDING(支払い待ち)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
else if (receipt.platform === "ios") {
|
|
30
|
+
if (!receipt.transactionReceipt) {
|
|
31
|
+
console.warn("無効なiOSレシート: transactionReceiptが不足しています");
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
transactionId: receipt.transactionId,
|
|
36
|
+
productId: receipt.productId,
|
|
37
|
+
transactionDate: Number(receipt.transactionDate) || Date.now(),
|
|
38
|
+
receipt: receipt.transactionReceipt,
|
|
39
|
+
isPaid: true, // iOSでは即時完了
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.warn("未知のプラットフォーム: ", receipt);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error("unifyReceipt エラー: ", error);
|
|
49
|
+
console.error("問題のあるレシートデータ: ", receipt);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
22
52
|
};
|
|
23
53
|
exports.unifyReceipt = unifyReceipt;
|
|
24
54
|
// 02. レシートの検証
|
package/dist/page/CoinPage.js
CHANGED
|
@@ -98,27 +98,36 @@ var CoinPage = function (_a) {
|
|
|
98
98
|
_a.label = 1;
|
|
99
99
|
case 1:
|
|
100
100
|
_a.trys.push([1, 6, 7, 8]);
|
|
101
|
+
console.log("購入処理開始: ", productId);
|
|
101
102
|
return [4 /*yield*/, (0, CoinFnc_1.handlePurchase)(productId)];
|
|
102
103
|
case 2:
|
|
103
104
|
purchase = _a.sent();
|
|
104
105
|
if (!purchase) {
|
|
105
|
-
console.warn(
|
|
106
|
+
console.warn("購入がキャンセルまたは失敗しました");
|
|
106
107
|
return [2 /*return*/];
|
|
107
108
|
}
|
|
109
|
+
console.log("購入成功、レシート処理開始");
|
|
108
110
|
receipt = (0, ReceiptFnc_1.unifyReceipt)(purchase);
|
|
109
111
|
if (!receipt) return [3 /*break*/, 4];
|
|
112
|
+
console.log("レシート情報: ", {
|
|
113
|
+
productId: receipt.productId,
|
|
114
|
+
isPaid: receipt.isPaid,
|
|
115
|
+
paymentState: receipt.isPaid ? "paid" : "wait",
|
|
116
|
+
});
|
|
110
117
|
return [4 /*yield*/, stores_1.coinStorage.savePurchasedItems(receipt)];
|
|
111
118
|
case 3:
|
|
112
119
|
_a.sent();
|
|
113
120
|
dispatch((0, CoinFnc_1.updateAllFreeState)(receipt));
|
|
121
|
+
console.log("レシート保存完了");
|
|
114
122
|
return [3 /*break*/, 5];
|
|
115
123
|
case 4:
|
|
116
|
-
console.error(
|
|
124
|
+
console.error("レシートの統一に失敗しました", purchase);
|
|
117
125
|
_a.label = 5;
|
|
118
126
|
case 5: return [3 /*break*/, 8];
|
|
119
127
|
case 6:
|
|
120
128
|
error_1 = _a.sent();
|
|
121
|
-
console.error(
|
|
129
|
+
console.error("購入処理中にエラーが発生しました", error_1);
|
|
130
|
+
console.error("エラーの詳細: ", error_1 instanceof Error ? error_1.message : String(error_1));
|
|
122
131
|
return [3 /*break*/, 8];
|
|
123
132
|
case 7:
|
|
124
133
|
dispatch(stores_1.settingStorage.saveSetting());
|
|
@@ -138,18 +147,24 @@ var CoinPage = function (_a) {
|
|
|
138
147
|
_a.label = 1;
|
|
139
148
|
case 1:
|
|
140
149
|
_a.trys.push([1, 3, 4, 5]);
|
|
150
|
+
console.log("復元処理開始");
|
|
141
151
|
return [4 /*yield*/, (0, CoinFnc_1.restorePurchases)(dispatch, true)];
|
|
142
152
|
case 2:
|
|
143
153
|
receipts = _a.sent();
|
|
144
154
|
if (receipts) {
|
|
155
|
+
console.log("復元されたアイテム: ", receipts.length, "件");
|
|
145
156
|
receipts.forEach(function (receipt) {
|
|
146
157
|
dispatch((0, CoinFnc_1.updateAllFreeState)(receipt));
|
|
147
158
|
});
|
|
148
159
|
}
|
|
160
|
+
else {
|
|
161
|
+
console.log("復元するアイテムがありませんでした");
|
|
162
|
+
}
|
|
149
163
|
return [3 /*break*/, 5];
|
|
150
164
|
case 3:
|
|
151
165
|
error_2 = _a.sent();
|
|
152
|
-
console.error(
|
|
166
|
+
console.error("復元処理中にエラーが発生しました", error_2);
|
|
167
|
+
console.error("エラーの詳細: ", error_2 instanceof Error ? error_2.message : String(error_2));
|
|
153
168
|
return [3 /*break*/, 5];
|
|
154
169
|
case 4:
|
|
155
170
|
dispatch(stores_1.settingStorage.saveSetting());
|