Unity接入TopOn超详细!

Unity接入TopOn

注意:该文档以Unity2019为例。

1.下载SDK

进入官方文档:集成说明 - TopOn Document (toponad.com)
在这里插入图片描述

如上图来到3.1 。 点击SDK打包系统
在这里插入图片描述

目前集成国外版, 选择否。如上图
在这里插入图片描述

选择需要的广告平台。如上图
在这里插入图片描述

点击Integrate , 点击下载。
在这里插入图片描述

解压文件,获得这几个包。可以看到各个广告的适配包和topon核心包AnyThinkCore。

2.Unity集成TopOn

(1)将SDK导入Unity
在这里插入图片描述

将这几个包一个个拖入项目Assets文件夹下。如上图
在这里插入图片描述

托如核心包会出现上图页面。 点击Add Selected Registries
在这里插入图片描述

点击 Apply。
在这里插入图片描述

最终结果图。
(2)集成
在这里插入图片描述
注意:设置当前平台为android,如上图。
在这里插入图片描述

勾选后可看到下图两个文件。

launcherTemplate.gradle需增加以下配置:

android {
    ......
    defaultConfig {
        applicationId '**APPLICATIONID**'
        ......
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'

        multiDexEnabled true //添加此配置,是为了当代码行数超过64k的时候设置的
    }
    ......
}

在这里插入图片描述

在这里插入图片描述

添加以下代码到如上图两个文件中

buildscript {
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
**BUILD_SCRIPT_DEPS**}
}

在这里插入图片描述

launcherTemplate 如上图 mainTemplate同理。
在这里插入图片描述

打开Preferences

设置Gradle版本。如图。 如果没有gradle-6.7.1 自行百度下载。
在这里插入图片描述

设置SDK版本如下图。
在这里插入图片描述

按照下图,生成LauncherManifest.xml文件。
在这里插入图片描述

注意:复制以下代码到生成后的LauncherManifest.xml。

<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools"
    android:installLocation="preferExternal">

    <!--必须要有的权限-->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <supports-screens
        android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true"
        android:anyDensity="true"/>

    <application android:label="@string/app_name"
                 android:icon="@mipmap/app_icon"
                 tools:replace="android:networkSecurityConfig"
                 android:networkSecurityConfig="@xml/network_security_config_unity">
        <!--这个设置主要是为了适配9.0以上的机器(必须使用)-->
        <uses-library android:name="org.apache.http.legacy" android:required="false" />
    </application>
</manifest>

在Assets/Plugins/Android/res/xml目录下创建network_security_config_unity.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>

v5.7.2之前的版本可跳过此步骤。从v5.7.2开始,如果有聚合了Admob,则必须在LauncherManifest.xml中额外添加以下配置(value值需配置Admob后台创建的应用的ID):

<manifest>
    <application>
        <!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
</application>
</manifest>

按照下图,生成gradleTemplate.properties文件。
在这里插入图片描述

注意:针对生成后的gradleTemplate.properties需增加以下配置:
org.gradle.jvmargs=-XmxJVM_HEAP_SIZEM
org.gradle.parallel=trueADDITIONAL_PROPERTIES
//添加以下配置
android.enableJetifier=true
android.useAndroidX=true

依赖解析
从v5.6.5版本开始调整了广告平台SDK的依赖引入方式,请根据以下步骤进行操作:
确保已经生成mainTemplate.gradle文件
勾选 Patch mainTemplate.gradle 选项(Unity 菜单栏:Assets → External Dependency Manager → Android Resolver → Settings)
在这里插入图片描述
在这里插入图片描述

开始解析依赖(Unity 菜单栏:Assets → External Dependency Manager → Android Resolver → Resolve),解析成功后将在mainTemplate.gradle文件中引入依赖。如果解析后没有任何反应,请尝试点击 “Force Resolve” 进行重试
在这里插入图片描述
在这里插入图片描述

3.调用广告

新建MainScenes脚本,该脚本用来初始化topon广告。代码如下:
其中APPKEY 和 APPKID 需要改成自己广告的

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using AnyThinkAds.Api;
using UnityEngine.UI;
using System;

/// <summary>
/// 初始化TopOn
/// </summary>
public class MainScenes : MonoBehaviour {

    private string APPKEY = "对应KEY";
    private string APPKID = "对应ID";

    //private interstitialScenes intersScene;
    [NonSerialized]
    public vidoeScenes vidSce;
    [NonSerialized]
    public interstitialScenes intSce;
    [NonSerialized]
    public bannerScenes banSce;

    public static MainScenes instance;


    void Awake () {

        if (instance == null)
            instance = this;
        else
            Destroy(transform.gameObject);

        initSDK();
        DontDestroyOnLoad(this);

        vidSce = GetComponent<vidoeScenes>();
        intSce = GetComponent<interstitialScenes>();
        banSce = GetComponent<bannerScenes>();
    }
	
	void Update () {
		
	}

    private class InitListener : ATSDKInitListener
    {
        public void initSuccess()
        {
			Debug.Log("Developer Develop callback SDK initSuccess");
        }
        public void initFail(string msg)
        {
			Debug.Log("Developer callback SDK initFail:" + msg);

        }
    }

    private class GetLocationListener:ATGetUserLocationListener
    {
        public void didGetUserLocation(int location)
        {
            //Debug.Log("Developer callback didGetUserLocation(): " + location);
            if(location == ATSDKAPI.kATUserLocationInEU && ATSDKAPI.getGDPRLevel() == ATSDKAPI.UNKNOWN)
            {
                ATSDKAPI.showGDPRAuth();
            }
        }
    }

	public void initSDK(){
        /*Debug.Log ("*********init sdk");
		Debug.Log("Developer Version of the runtime: " + Application.unityVersion);
		Debug.Log ("Developer init sdk");
		Debug.Log(" Developer Screen size : {" + Screen.width + ", " + Screen.height + "}");
        */
        
        //ATSDKAPI.setChannel("unity3d_test_channel");
        //ATSDKAPI.setSubChannel("unity3d_test_Subchannel");
        //ATSDKAPI.initCustomMap(new Dictionary<string, string> { { "channel", "huawei" } });
        //ATSDKAPI.setCustomDataForPlacementID(new Dictionary<string, string> { { "unity3d_data_pl", "test_data_pl" } },"b5b728e7a08cd4");
        /**/ATSDKAPI.setLogDebug(true);

        //Debug.Log("Developer DataConsent: " + ATSDKAPI.getGDPRLevel());
        //Debug.Log("Developer isEUTrafic: " + ATSDKAPI.isEUTraffic());
       



        ATSDKAPI.getUserLocation(new GetLocationListener());


        #if UNITY_ANDROID
                ATSDKAPI.initSDK(APPKID, APPKEY, new InitListener());
        #endif

    }
}

新建bannerScenes脚本,该脚本用来加载banner 和 展现banner广告。
其中mPlacementId_banner_all需要更换成对应id

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using AnyThinkAds.Api;
using UnityEngine.UI;

using AnyThinkAds.ThirdParty.MiniJSON;
using System;

public class bannerScenes : MonoBehaviour {


#if UNITY_ANDROID
    static string mPlacementId_banner_all = "更换对应id";

    static string showingScenario = "f600e6039e152c";

#elif UNITY_IOS || UNITY_IPHONE
	static string mPlacementId_banner_all = "b5bacaccb61c29";
    //static string mPlacementId_banner_all = "b5bacaccb61c29";
    static string showingScenario = "";
#endif

    private int screenWidth;
    // Use this for initialization
    void Start () {
        this.screenWidth = Screen.width;
        loadBannerAd();
        showBannerAd();

    }
	
	// Update is called once per frame
	void Update () {
		
	}

    private void OnDestroy()
    {

    }

    static BannerCallback bannerCallback ;

    public void loadBannerAd() {

        if(bannerCallback == null){
            bannerCallback = new BannerCallback();
            ATBannerAd.Instance.setListener(bannerCallback);
        }

        Dictionary<string, object> jsonmap = new Dictionary<string,object>();


        #if UNITY_ANDROID
        
        ATSize bannerSize = new ATSize(screenWidth, 50* screenWidth/350, true);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraBannerAdSizeStruct, bannerSize);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveWidth, bannerSize.width);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveOrientation, ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveOrientationPortrait);
        #elif UNITY_IOS || UNITY_IPHONE
            ATSize bannerSize = new ATSize(320, 50, false);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraBannerAdSizeStruct, bannerSize);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveWidth, bannerSize.width);
            jsonmap.Add(ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveOrientation, ATBannerAdLoadingExtra.kATBannerAdLoadingExtraAdaptiveOrientationPortrait);
        
        #endif
        ATBannerAd.Instance.loadBannerAd(mPlacementId_banner_all, jsonmap);
    }

    public void showBannerAd() {
        //string adStatus = ATBannerAd.Instance.checkAdStatus(mPlacementId_banner_all);

        //Debug.Log("*************Developer checkAdStatus banner...." + adStatus);
        //Debug.Log("*************Developer show banner *************");

        // ATRect arpuRect = new ATRect(0,50, this.screenWidth, 300, true);
        // ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all, arpuRect);
        // ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all, ATBannerAdLoadingExtra.kATBannerAdShowingPisitionBottom);
        ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all, ATBannerAdLoadingExtra.kATBannerAdShowingPisitionBottom);

//        Dictionary<string, string> jsonmap = new Dictionary<string, string>();
//        jsonmap.Add(AnyThinkAds.Api.ATConst.SCENARIO, showingScenario);
//        //ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all, arpuRect, jsonmap);
//        ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all, ATBannerAdLoadingExtra.kATBannerAdShowingPisitionTop, jsonmap);

    }

    public void removeBannerAd() {
        ATBannerAd.Instance.cleanBannerAd(mPlacementId_banner_all);
    }

    public void hideBannerAd() {
        ATBannerAd.Instance.hideBannerAd(mPlacementId_banner_all);
    }

    /*
      Use this method when you want to reshow a banner that is previously hidden(by calling hideBannerAd)   
    */
public void reshowBannerAd() {
        ATBannerAd.Instance.showBannerAd(mPlacementId_banner_all);
    }

    class BannerCallback : ATBannerAdListener
    {
        public void onAdAutoRefresh(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onAdAutoRefresh :" +  placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onAdAutoRefreshFail(string placementId, string code, string message)
        {
            //Debug.Log("Developer callback onAdAutoRefreshFail : "+ placementId + "--code:" + code + "--msg:" + message);
        }

        public void onAdClick(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onAdClick :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onAdClose(string placementId)
        {
            //Debug.Log("Developer callback onAdClose :" + placementId);
        }

        public void onAdCloseButtonTapped(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onAdCloseButtonTapped :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onAdImpress(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onAdImpress :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onAdLoad(string placementId)
        {
            //Debug.Log("Developer callback onAdLoad :" + placementId);
        }

        public void onAdLoadFail(string placementId, string code, string message)
        {
            //Debug.Log("************Developer callback onAdLoadFail : : " + placementId + "--code:" + code + "--msg:" + message);
        }
    }
}

新建interstitialScenes脚本 , 该脚本用来加载插屏,并提供调用接口
其中mPlacementId_interstitial_all要跟换成对应id

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using AnyThinkAds.Api;
using UnityEngine.UI;

using AnyThinkAds.ThirdParty.MiniJSON;
using UnityEngine.EventSystems;
using System;

public class interstitialScenes : MonoBehaviour {

#if UNITY_ANDROID
    //static string mPlacementId_interstitial_all = "b5bbdc8e9ef916";

    static string mPlacementId_interstitial_all = "更换对应id";

    static string showingScenario = "f5e71c49060ab3";

#elif UNITY_IOS || UNITY_IPHONE
    static string mPlacementId_interstitial_all = "b5bacad26a752a";
    static string showingScenario = "f5e549727efc49";

#endif


    // Use this for initialization
    void Start () {
        loadInterstitialAd();

        //EventManager.ShowInterstitialAd.BoradCastEvent();
    }
	
	// Update is called once per frame
	void Update () {
		
	}

    static InterstitalCallback callback;
    public void loadInterstitialAd() {
        if(callback == null) {
            callback = new InterstitalCallback();
            ATInterstitialAd.Instance.setListener(callback);
        }
        //Debug.Log("**********loadInterstitialAd");

        Dictionary<string,string> jsonmap = new Dictionary<string,string>();
        jsonmap.Add(AnyThinkAds.Api.ATConst.USE_REWARDED_VIDEO_AS_INTERSTITIAL, AnyThinkAds.Api.ATConst.USE_REWARDED_VIDEO_AS_INTERSTITIAL_NO);
        //jsonmap.Add(AnyThinkAds.Api.ATConst.USE_REWARDED_VIDEO_AS_INTERSTITIAL, AnyThinkAds.Api.ATConst.USE_REWARDED_VIDEO_AS_INTERSTITIAL_YES);

        ATInterstitialAd.Instance.loadInterstitialAd(mPlacementId_interstitial_all, jsonmap);
    }

    public void isReady()
    {
        bool b = ATInterstitialAd.Instance.hasInterstitialAdReady(mPlacementId_interstitial_all);
        //Debug.Log("Developer isReady interstitial...." + b);

        string adStatus = ATInterstitialAd.Instance.checkAdStatus(mPlacementId_interstitial_all);
        //Debug.Log("Developer checkAdStatus interstitial...." + adStatus);
    }

    public void showInterstitialAd()
    {

        Dictionary<string, string> jsonmap = new Dictionary<string, string>();
        jsonmap.Add(AnyThinkAds.Api.ATConst.SCENARIO, showingScenario);

        ATInterstitialAd.Instance.showInterstitialAd(mPlacementId_interstitial_all, jsonmap);
    }

    private void OnDestroy()
    {


    }

    class InterstitalCallback : ATInterstitialAdListener
    {

        public void onInterstitialAdClick(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onInterstitialAdClick :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onInterstitialAdClose(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onInterstitialAdClose :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onInterstitialAdEndPlayingVideo(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onInterstitialAdEndPlayingVideo :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onInterstitialAdFailedToPlayVideo(string placementId, string code, string message)
        {
            //Debug.Log("Developer callback onInterstitialAdFailedToPlayVideo :" + placementId + "--code:" + code + "--msg:" + message);
        }

        public void onInterstitialAdLoad(string placementId)
        {
            //Debug.Log("Developer callback onInterstitialAdLoad :" + placementId);
        }

        public void onInterstitialAdLoadFail(string placementId, string code, string message)
        {

            //Debug.Log("*****Developer callback onInterstitialAdLoadFail :" + placementId + "--code:" + code + "--msg:" + message);
            //loadInterstitiaAd();
        }

        public void onInterstitialAdShow(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onInterstitialAdShow :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onInterstitialAdStartPlayingVideo(string placementId, ATCallbackInfo callbackInfo)
        {
            //Debug.Log("Developer callback onInterstitialAdStartPlayingVideo :" + placementId + "->" + Json.Serialize(callbackInfo.toDictionary()));

        }

        public void onInterstitialAdFailedToShow(string placementId)
        {
            //Debug.Log("Developer callback onInterstitialAdFailedToShow :" + placementId);

        }
    }

}

新建vidoeScenes脚本,该脚本用来加载激励视频,并提供调用接口
其中mPlacementId_rewardvideo_all更换成对应id

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using AnyThinkAds.Api;
using UnityEngine.UI;
using AnyThinkAds.ThirdParty.MiniJSON;
using System;

public class vidoeScenes : MonoBehaviour {

#if UNITY_ANDROID

    //static string mPlacementId_rewardvideo_all = "b5b449f75948c5";

    static string mPlacementId_rewardvideo_all = "更换对应id";
    static string showingScenario = "f5e71c46d1a28f";
#elif UNITY_IOS || UNITY_IPHONE
    static string mPlacementId_rewardvideo_all = "b5b44a0f115321";//"b5b44a0f115321";
    static string showingScenario = "f5e54970dc84e6";

#endif

    ATRewardedVideo rewardedVideo;
	
 
	// Use this for initialization
	void Start () {
        loadVideo();

    }
	
	// Update is called once per frame
	void Update () {
		
	}


    static ATCallbackListener callbackListener;
	public void loadVideo(){
        if(callbackListener == null){
            callbackListener = new ATCallbackListener();
            //Debug.Log("Developer init video....placementId:" + mPlacementId_rewardvideo_all);
            ATRewardedVideo.Instance.setListener(callbackListener);
        }

        //Debug.Log("**********loadVideo");

        ATSDKAPI.setCustomDataForPlacementID(new Dictionary<string, string> { { "placement_custom_key", "placement_custom" } }, mPlacementId_rewardvideo_all);

		Dictionary<string,string> jsonmap = new Dictionary<string,string>();
		jsonmap.Add(ATConst.USERID_KEY, "test_user_id");
		jsonmap.Add(ATConst.USER_EXTRA_DATA, "test_user_extra_data");


        ATRewardedVideo.Instance.loadVideoAd(mPlacementId_rewardvideo_all,jsonmap);
		
	}
	public void showVideo(){

        bool b = ATRewardedVideo.Instance.hasAdReady(mPlacementId_rewardvideo_all);
        if (!b)
        {
            //Debug.Log("******没有广告缓存重新 loadVideo");
            //loadVideo();
        }
        //Debug.Log (" ********************Developer show video.... ********************");

        Dictionary<string, string> jsonmap = new Dictionary<string, string>();
        jsonmap.Add(AnyThinkAds.Api.ATConst.SCENARIO, showingScenario);
        ATRewardedVideo.Instance.showAd(mPlacementId_rewardvideo_all, jsonmap);
		
	}

    private void OnDestroy()
    {

    }

    public void isReady(){

		// Debug.Log ("Developer isReady ?....");
        bool b = ATRewardedVideo.Instance.hasAdReady(mPlacementId_rewardvideo_all);
		//Debug.Log("Developer isReady video...." + b);

        string adStatus = ATRewardedVideo.Instance.checkAdStatus(mPlacementId_rewardvideo_all);
        //Debug.Log("Developer checkAdStatus video...." + adStatus);
    }

    class ATCallbackListener : ATRewardedVideoListener {

        public void onRewardedVideoAdLoaded(string placementId)
        {
            //Debug.Log("Developer onRewardedVideoAdLoaded------");
        }

        public void onRewardedVideoAdLoadFail(string placementId, string code, string message){
            //Debug.Log("***************Developer onRewardedVideoAdLoadFail------:code" + code + "--message:" + message);
        }

        public void onRewardedVideoAdPlayStart(string placementId, ATCallbackInfo callbackInfo){
            //Debug.Log("Developer onRewardedVideoAdPlayStart------" + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onRewardedVideoAdPlayEnd(string placementId, ATCallbackInfo callbackInfo){
            //Debug.Log("Developer onRewardedVideoAdPlayEnd------" + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onRewardedVideoAdPlayFail(string placementId, string code, string message){
            //Debug.Log("Developer onRewardedVideoAdPlayFail------code:" + code + "---message:" + message);
        }

        public void onRewardedVideoAdPlayClosed(string placementId, bool isReward, ATCallbackInfo callbackInfo){
            //Debug.Log("Developer onRewardedVideoAdPlayClosed------isReward:" + isReward + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onRewardedVideoAdPlayClicked(string placementId, ATCallbackInfo callbackInfo){
            //Debug.Log("Developer onRewardVideoAdPlayClicked------" + "->" + Json.Serialize(callbackInfo.toDictionary()));
        }

        public void onReward(string placementId, ATCallbackInfo callbackInfo){

        }
    }
}

创建空物体,取名AD将,将以上脚本添加到物体。

大功告成。 现在可以在任何地方通过以下代码调用广告。
调用banner

MainScenes.instance.banSce.showBannerAd();

调用插屏
MainScenes.instance.intSce.showInterstitialAd();

调用激励视频
MainScenes.instance.vidSce.showVideo();

4.测试集成

测试集成需要打开Debug模式,MainScenes脚本中已经打开,如下图。
在这里插入图片描述

直接打包apk,安装到手机 -> 手机打开开发者模式 -> 用数据线连接电脑。 ->

打开AndroidStudio 的 Logcat -> 运行应用, 查看日志, 日志如下图。
在这里插入图片描述

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值