You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:17:36