Xử lý lỗi trong Capacitor SDK
Mọi lỗi được SDK trả về đều là một instance của AdaptyError. Dưới đây là ví dụ:
Bật verbose logs trước khi debug. Hầu hết các AdaptyError đều bao bọc một lỗi cơ bản từ StoreKit, Play Billing, mạng hoặc backend. Khi bật verbose logs (adapty.setLogLevel({ logLevel: 'verbose' }) — xem Logging), lỗi đó sẽ được in ra console, thường cho bạn biết nguyên nhân thực sự. Thuộc tính detail trên AdaptyError luôn được điền bất kể mức log — verbose logs chỉ giúp hiển thị nó ra console.
try {
const result = await adapty.makePurchase({ product });
// Handle purchase result
if (result.type === 'success') {
console.log('Purchase successful:', result.profile);
} else if (result.type === 'user_cancelled') {
console.log('User cancelled the purchase');
} else if (result.type === 'pending') {
console.log('Purchase is pending');
}
} catch (error) {
if (error instanceof AdaptyError) {
console.error('Adapty error:', error.adaptyCode, error.localizedDescription);
// Handle specific error codes
switch (error.adaptyCode) {
case ErrorCodeName.cantMakePayments:
console.log('In-app purchases are not allowed on this device');
break;
case ErrorCodeName.notActivated:
console.log('Adapty SDK is not activated');
break;
case ErrorCodeName.productPurchaseFailed:
console.log('Purchase failed:', error.detail);
break;
default:
console.log('Other error occurred:', error.detail);
}
} else {
console.error('Non-Adapty error:', error);
}
}
Thuộc tính của lỗi
Lớp AdaptyError cung cấp các thuộc tính sau:
| Thuộc tính | Kiểu | Mô tả |
|---|---|---|
adaptyCode | number | Mã lỗi dạng số (ví dụ: 1003 cho cantMakePayments) |
localizedDescription | string | Thông báo lỗi thân thiện với người dùng |
detail | string | undefined | Thông tin chi tiết bổ sung về lỗi (tùy chọn) |
message | string | Thông báo lỗi đầy đủ bao gồm mã và mô tả |
Mã lỗi
SDK xuất các hằng số và tiện ích để làm việc với mã lỗi:
Hằng số ErrorCodeName
Ánh xạ các định danh chuỗi sang mã số:
ErrorCodeName.cantMakePayments // 1003
ErrorCodeName.notActivated // 2002
ErrorCodeName.networkFailed // 2005
Hằng số ErrorCode
Ánh xạ mã số sang định danh chuỗi:
ErrorCode[1003] // 'cantMakePayments'
ErrorCode[2002] // 'notActivated'
ErrorCode[2005] // 'networkFailed'
Các hàm hỗ trợ
// Get numeric code from string name:
getErrorCode('cantMakePayments') // 1003
// Get string name from numeric code:
getErrorPrompt(1003) // 'cantMakePayments'
So sánh mã lỗi
Lưu ý quan trọng: error.adaptyCode là một số, vì vậy hãy so sánh trực tiếp với mã số:
// Option 1: Use ErrorCodeName constant (recommended) ✅
if (error.adaptyCode === ErrorCodeName.cantMakePayments) {
console.log('Cannot make payments');
}
// Option 2: Compare with numeric literal ✅
if (error.adaptyCode === 1003) {
console.log('Cannot make payments');
}
// NOT like this ❌ - compares number to string and will never match
if (error.adaptyCode === ErrorCode[1003]) {
}
Trình xử lý lỗi toàn cục
Bạn có thể thiết lập một trình xử lý lỗi toàn cục để bắt tất cả các lỗi từ Adapty:
// Set up global error handler
AdaptyError.onError = (error: AdaptyError) => {
console.error('Global Adapty error:', {
code: error.adaptyCode,
message: error.localizedDescription,
detail: error.detail
});
// Handle specific error types globally
if (error.adaptyCode === ErrorCodeName.notActivated) {
// SDK not activated - maybe retry activation
console.log('SDK not activated, attempting to reactivate...');
}
};
Các mẫu xử lý lỗi phổ biến
Xử lý lỗi mua hàng
async function handlePurchase(product: AdaptyPaywallProduct) {
try {
const result = await adapty.makePurchase({ product });
if (result.type === 'success') {
console.log('Purchase successful:', result.profile);
} else if (result.type === 'user_cancelled') {
console.log('User cancelled the purchase');
} else if (result.type === 'pending') {
console.log('Purchase is pending');
}
} catch (error) {
if (error instanceof AdaptyError) {
switch (error.adaptyCode) {
case ErrorCodeName.cantMakePayments:
console.log('In-app purchases not allowed');
break;
case ErrorCodeName.productPurchaseFailed:
console.log('Purchase failed:', error.detail);
break;
default:
console.error('Purchase error:', error.localizedDescription);
}
}
}
}
Xử lý lỗi mạng
async function fetchFlow(placementId: string) {
try {
const flow = await adapty.getFlow({ placementId });
return flow;
} catch (error) {
if (error instanceof AdaptyError) {
switch (error.adaptyCode) {
case ErrorCodeName.networkFailed:
console.log('Network error, retrying...');
// Implement retry logic
break;
case ErrorCodeName.serverError:
console.log('Server error:', error.detail);
break;
case ErrorCodeName.notActivated:
console.log('SDK not activated');
break;
default:
console.error('Paywall fetch error:', error.localizedDescription);
}
}
throw error;
}
}
Mã StoreKit hệ thống
| Lỗi | Mã | Mô tả |
|---|---|---|
| unknown | 0 | Lỗi này cho biết đã xảy ra lỗi không xác định hoặc không mong muốn. |
| clientInvalid | 1 | Mã lỗi này cho biết client không được phép thực hiện hành động đã thử. |
| paymentCancelled | 2 | Mã lỗi này cho biết người dùng đã hủy yêu cầu thanh toán. Không cần thực hiện hành động nào, nhưng về mặt logic nghiệp vụ, bạn có thể đề nghị giảm giá cho người dùng hoặc nhắc họ sau. |
| paymentInvalid | 3 | Lỗi này cho biết một trong các tham số thanh toán không được cửa hàng nhận dạng. |
| paymentNotAllowed | 4 | Mã lỗi này cho biết người dùng không được phép xác nhận thanh toán. Các nguyên nhân có thể: - Thanh toán không được hỗ trợ ở quốc gia của người dùng. - Người dùng là trẻ vị thành niên. |
| storeProductNotAvailable | 5 | Mã lỗi này cho biết sản phẩm yêu cầu không có trong App Store. Hãy đảm bảo sản phẩm khả dụng ở quốc gia đang dùng. |
| cloudServicePermissionDenied | 6 | Mã lỗi này cho biết người dùng chưa cho phép truy cập thông tin dịch vụ Cloud. |
| cloudServiceNetworkConnectionFailed | 7 | Mã lỗi này cho biết thiết bị không thể kết nối mạng. |
| cloudServiceRevoked | 8 | Mã lỗi này cho biết người dùng đã thu hồi quyền sử dụng dịch vụ cloud này. |
| privacyAcknowledgementRequired | 9 | Mã lỗi này cho biết người dùng chưa xác nhận chính sách quyền riêng tư của cửa hàng. |
| unauthorizedRequestData | 10 | Mã lỗi này cho biết yêu cầu được xây dựng không đúng cách. |
| invalidOfferIdentifier | 11 | Mã định danh ưu đãi không hợp lệ. Các nguyên nhân có thể: - Bạn chưa thiết lập ưu đãi với mã định danh đó trong App Store. - Bạn đã thu hồi ưu đãi. - Bạn đã nhập sai mã ưu đãi. |
| invalidSignature | 12 | Mã lỗi này cho biết chữ ký trong phiếu giảm giá thanh toán không hợp lệ. Hãy đảm bảo bạn đã điền vào trường In-app purchase Key ID và tải lên tệp In-App Purchase Private Key. Tham khảo chủ đề Cấu hình tích hợp App Store để biết thêm chi tiết. |
| missingOfferParams | 13 | Lỗi này cho biết có vấn đề với tích hợp Adapty hoặc với các ưu đãi. Tham khảo Cấu hình tích hợp App Store và Ưu đãi để biết cách thiết lập. |
| invalidOfferPrice | 14 | Mã lỗi này cho biết mức giá bạn đã chỉ định trong cửa hàng không còn hợp lệ. Các ưu đãi phải luôn đại diện cho mức giá đã giảm. |
Mã Android tùy chỉnh
| Lỗi | Mã | Mô tả |
|---|---|---|
| adaptyNotInitialized | 20 | Bạn cần cấu hình Adapty SDK đúng cách bằng phương thức activate. Tìm hiểu cách thực hiện tại Cài đặt & cấu hình Adapty SDK. |
| productNotFound | 22 | Lỗi này cho biết sản phẩm yêu cầu mua không có trong cửa hàng. |
| currentSubscriptionToUpdateNotFoundInHistory | 24 | Không tìm thấy gói đăng ký gốc cần gia hạn. |
| billingServiceTimeout | 97 | Lỗi này cho biết yêu cầu đã đạt đến thời gian chờ tối đa trước khi Google Play có thể phản hồi. Nguyên nhân có thể là do trễ trong việc thực thi hành động được yêu cầu bởi lệnh gọi Play Billing Library. |
| featureNotSupported | 98 | Tính năng yêu cầu không được Play Store hỗ trợ trên thiết bị hiện tại. |
| billingServiceDisconnected | 99 | Lỗi nghiêm trọng này cho biết kết nối của ứng dụng client đến dịch vụ Google Play Store thông qua BillingClient đã bị ngắt. |
| billingServiceUnavailable | 102 | Lỗi tạm thời này cho biết dịch vụ Google Play Billing hiện không khả dụng. Trong hầu hết các trường hợp, điều này có nghĩa là có sự cố kết nối mạng ở đâu đó giữa thiết bị client và dịch vụ Google Play Billing. |
| billingUnavailable | 103 | Lỗi này cho biết đã xảy ra lỗi thanh toán của người dùng trong quá trình mua hàng. Ví dụ về khi điều này có thể xảy ra: 1. Ứng dụng Play Store trên thiết bị của người dùng đã lỗi thời. 2. Người dùng ở quốc gia không được hỗ trợ. 3. Người dùng là nhân viên doanh nghiệp và quản trị viên doanh nghiệp đã tắt tính năng mua hàng của người dùng. 4. Google Play không thể tính phí phương thức thanh toán của người dùng. Ví dụ: thẻ tín dụng của người dùng có thể đã hết hạn. 5. Người dùng chưa đăng nhập vào ứng dụng Play Store. |
| developerError | 105 | Đây là lỗi nghiêm trọng cho biết bạn đang sử dụng API không đúng cách. |
| billingError | 106 | Đây là lỗi nghiêm trọng cho biết có sự cố nội bộ với chính Google Play. |
| itemAlreadyOwned | 107 | Sản phẩm consumable đã được mua. |
| itemNotOwned | 108 | Lỗi này cho biết hành động yêu cầu trên mục đã thất bại. |
| billingNetworkError | 112 | Lỗi này cho biết có sự cố với kết nối mạng giữa thiết bị và hệ thống Play. |
Mã StoreKit tùy chỉnh
| Lỗi | Mã | Mô tả |
|---|---|---|
| noProductIDsFound | 1000 | Lỗi này cho biết không có sản phẩm nào trong paywall khả dụng trong cửa hàng. Nếu bạn gặp lỗi này, vui lòng làm theo các bước dưới đây để giải quyết: 1. Kiểm tra xem tất cả sản phẩm đã được thêm vào Adapty Dashboard chưa. 2. Đảm bảo Bundle ID của ứng dụng khớp với Bundle ID trong Apple Connect. 3. Xác minh rằng mã định danh sản phẩm từ các cửa hàng ứng dụng khớp với những gì bạn đã thêm vào Dashboard. Lưu ý rằng mã định danh không được chứa Bundle ID, trừ khi nó đã được bao gồm trong cửa hàng. 4. Xác nhận rằng trạng thái thanh toán của ứng dụng đang hoạt động trong cài đặt thuế Apple của bạn. Đảm bảo thông tin thuế của bạn được cập nhật và chứng chỉ của bạn còn hiệu lực. 5. Kiểm tra xem tài khoản ngân hàng đã được liên kết với ứng dụng chưa để đủ điều kiện kiếm tiền. 6. Kiểm tra xem sản phẩm có khả dụng ở tất cả các khu vực không. Ngoài ra, đảm bảo sản phẩm của bạn ở trạng thái “Ready to Submit”. |
| productRequestFailed | 1002 | Không thể tải danh sách sản phẩm khả dụng vào lúc này. Nguyên nhân có thể: - Chưa có cache nào được tạo và đồng thời không có kết nối internet. |
| cantMakePayments | 1003 | In-app purchase không được phép trên thiết bị này. |
| noPurchasesToRestore | 1004 | Lỗi này cho biết Google Play không tìm thấy giao dịch mua để khôi phục. |
| cantReadReceipt | 1005 | Không có biên lai hợp lệ nào trên thiết bị. Đây có thể là sự cố trong quá trình kiểm thử sandbox. Không cần thực hiện hành động nào, nhưng về mặt logic nghiệp vụ, bạn có thể đề nghị giảm giá cho người dùng hoặc nhắc họ sau. |
| productPurchaseFailed | 1006 | Mua sản phẩm thất bại. Lỗi này bao gồm một lỗi StoreKit cơ bản — đọc lỗi được bao gồm (hoặc bật verbose logs để xem trong console) để biết lý do thực sự. Lỗi được bao gồm thường là một trong các mã StoreKit 0–14 trong bảng trên — thường gặp nhất là paymentCancelled, paymentInvalid, paymentNotAllowed hoặc invalidOfferPrice. Nếu bạn không thể xác định nguyên nhân cụ thể, hãy thử một hồ sơ sandbox mới; nếu vẫn thất bại, hãy liên hệ hỗ trợ Apple. |
| refreshReceiptFailed | 1010 | Lỗi này cho biết biên lai không được nhận. Chỉ áp dụng cho StoreKit 1. |
| receiveRestoredTransactionsFailed | 1011 | Khôi phục giao dịch mua thất bại. |
Mã mạng tùy chỉnh
| Lỗi | Mã | Mô tả |
|---|---|---|
| notActivated | 2002 | Bạn cần cấu hình Adapty SDK đúng cách bằng phương thức activate. Tìm hiểu cách thực hiện tại Cài đặt & cấu hình Adapty SDK. |
| badRequest | 2003 | Yêu cầu không hợp lệ. |
| serverError | 2004 | Lỗi máy chủ. |
| networkFailed | 2005 | Yêu cầu mạng thất bại. |
| decodingFailed | 2006 | Lỗi này cho biết quá trình giải mã phản hồi thất bại. |
| encodingFailed | 2009 | Lỗi này cho biết quá trình mã hóa yêu cầu thất bại. |
| analyticsDisabled | 3000 | Chúng tôi không thể xử lý các sự kiện analytics vì bạn đã tắt tính năng này. Tham khảo chủ đề Tích hợp Analytics để biết thêm chi tiết. |
| wrongParam | 3001 | Lỗi này cho biết một số tham số của bạn không đúng: để trống khi không được phép hoặc sai kiểu dữ liệu, v.v. |
| activateOnceError | 3005 | Không thể gọi phương thức .activate nhiều hơn một lần. |
| profileWasChanged | 3006 | Hồ sơ người dùng đã thay đổi trong quá trình thực hiện thao tác. |
| unsupportedData | 3007 | Lỗi này cho biết định dạng dữ liệu không được SDK hỗ trợ. |
| persistingDataError | 3100 | Đã xảy ra lỗi khi lưu dữ liệu. |
| fetchTimeoutError | 3101 | Lỗi này có nghĩa là paywall không thể được tải trong giới hạn thời gian đã đặt. Để tránh tình huống này, thiết lập fallback cục bộ. |
| operationInterrupted | 9000 | Thao tác này đã bị hệ thống ngắt. |