React Native如何获取用户App Store与Google Play商店的地区国别码
React Native 按 App Store/Google Play 商店地区限制内容实现方案
由于 react-native-localize 获取的是系统设置地区,与商店地区无关且易修改,要实现基于商店地区的内容限制,需针对 iOS 和 Android 分别通过原生能力获取真实商店地区。
iOS 实现方案
iOS 11+ 提供了 SKStorefront API,可直接获取当前用户的 App Store 地区代码,该代码与用户 Apple ID 绑定,无法轻易修改。
1. 原生模块实现
创建 React Native 原生模块调用 StoreKit 接口:
// RCTStoreRegionManager.h #import <React/RCTBridgeModule.h> @interface RCTStoreRegionManager : NSObject <RCTBridgeModule> @end // RCTStoreRegionManager.m #import "RCTStoreRegionManager.h" #import <StoreKit/StoreKit.h> @implementation RCTStoreRegionManager RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(getStoreCountryCode:(RCTResponseSenderBlock)callback) { if (@available(iOS 11.0, *)) { SKStorefront *storefront = [SKPaymentQueue defaultQueue].storefront; NSString *countryCode = storefront.countryCode; callback(@[[NSNull null], countryCode]); } else { callback(@[@{@"error": @"仅支持 iOS 11.0 及以上版本"}, [NSNull null]]); } } @end
2. React Native 端调用
import { NativeModules } from 'react-native'; const { StoreRegionManager } = NativeModules; const getiOSStoreCountry = async () => { try { const [error, countryCode] = await StoreRegionManager.getStoreCountryCode(); if (error) throw error; return countryCode; // 返回如 "US"、"CN" 等地区码 } catch (err) { console.error('获取 iOS 商店地区失败:', err); return null; } };
注意事项
- 必须使用真实设备测试,模拟器无法获取 App Store 地区信息
- 需确保设备已登录对应地区的 Apple ID
Android 实现方案
Android 需借助 Google Play Billing Library 获取与用户 Google 账号绑定的商店地区,该地区同样无法随意修改。
1. 配置依赖与权限
在 app/build.gradle 中添加 Billing 库依赖:
dependencies { implementation 'com.android.billingclient:billing:6.0.1' }
在 AndroidManifest.xml 中添加权限:
<uses-permission android:name="com.android.vending.BILLING" />
2. 原生模块实现
// StoreRegionManagerModule.java package com.yourappname; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.Promise; import com.android.billingclient.api.BillingClient; import com.android.billingclient.api.BillingClientStateListener; import com.android.billingclient.api.BillingResult; import com.android.billingclient.api.PurchaseHistoryResponseListener; import com.android.billingclient.api.PurchaseHistoryRecord; import java.util.List; public class StoreRegionManagerModule extends ReactContextBaseJavaModule { private BillingClient billingClient; public StoreRegionManagerModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "StoreRegionManager"; } @ReactMethod public void getStoreCountryCode(final Promise promise) { billingClient = BillingClient.newBuilder(getReactApplicationContext()) .setListener((billingResult, purchases) -> {}) .enablePendingPurchases() .build(); billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, new PurchaseHistoryResponseListener() { @Override public void onPurchaseHistoryResponse(BillingResult result, List<PurchaseHistoryRecord> records) { if (result.getResponseCode() == BillingClient.BillingResponseCode.OK && records != null && !records.isEmpty()) { String countryCode = records.get(0).getCountryCode(); promise.resolve(countryCode); } else { promise.reject("NO_RECORDS", "无购买记录,无法获取商店地区"); } billingClient.endConnection(); } }); } else { promise.reject("SETUP_FAILED", "Billing 服务连接失败: " + billingResult.getDebugMessage()); billingClient.endConnection(); } } @Override public void onBillingServiceDisconnected() { promise.reject("DISCONNECTED", "Billing 服务连接断开"); } }); } }
3. React Native 端调用
import { NativeModules } from 'react-native'; const { StoreRegionManager } = NativeModules; const getAndroidStoreCountry = async () => { try { const countryCode = await StoreRegionManager.getStoreCountryCode(); return countryCode; } catch (err) { console.error('获取 Android 商店地区失败:', err); return null; } };
注意事项
- 若用户无任何 Google Play 购买记录,无法直接获取地区,可提示用户登录 Google Play 或添加测试内购项目
- 需使用真实设备测试,模拟器无法连接 Google Play 服务
跨平台统一封装
import { Platform } from 'react-native'; // 统一获取商店地区码 export const getStoreCountryCode = async () => { if (Platform.OS === 'ios') { return await getiOSStoreCountry(); } else if (Platform.OS === 'android') { return await getAndroidStoreCountry(); } return null; }; // 地区权限校验示例 const checkRegionAccess = async () => { const countryCode = await getStoreCountryCode(); const allowedRegions = ['US', 'CN', 'JP']; // 允许展示内容的地区 if (allowedRegions.includes(countryCode)) { // 展示受限内容 console.log('地区合规,展示内容'); } else { // 隐藏内容或提示用户 console.log('地区受限,无法展示内容'); } };
内容的提问来源于stack exchange,提问作者Good Morning
相关产品推荐
相关产品推荐

