java 集成小米,华为推送

72 篇文章 0 订阅
10 篇文章 0 订阅

小米:

添加依赖或者jar包

jar包下载地址:http://admin.xmpush.xiaomi.com/zh_CN/mipush/downpage/java-http2

工具类:

package com.xxx.admin.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaomi.xmpush.server.Constants;
import com.xiaomi.xmpush.server.Message;
import com.xiaomi.xmpush.server.Result;
import com.xiaomi.xmpush.server.Sender;
import org.apache.log4j.Logger;

import java.util.Map;

public class XMiPushUtil {

    private static Logger logger = Logger.getLogger(XMiPushUtil.class);

    /**
     * 小米生产环境常量
     */
    public static  boolean xiaomiProd=false;

    public static  String xiaomiPackageName="me.gaoshou1.ssh";

    public static String xiaomiAppSecretKey="/IqKJWX3vatE+Fk3gRyP4A==";

    /**
     * 指定alias推送(单个或多个)
     *
     * @param messagePayload 消息
     * @param title          消息标题
     * @param description    消息描述
     * @param aliasList      指定alias
     */
    public static Result xiaomiBatchPush(String messagePayload, String title, String description, String aliasList,String targetPath, String action) {
        logger.info("小米设备:{}"+aliasList.toString());
        try {
            JSONObject result = builderMessageAndSender(title, description,action);
            Message message = (Message) result.get("message");
            Sender sender = (Sender) result.get("sender");
            Result pushResult = sender.send(message, aliasList, 3);
            logger.info("++++推送到小米结果为:{}"+pushResult.toString());
            if (pushResult != null && pushResult.getErrorCode().getValue()==0) {
                return pushResult;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("小米指定alias失败:", e);
        }
        return null;
    }

    public static JSONObject builderMessageAndSender(String title,String description,String action) {
        boolean isProd = XMiPushUtil.xiaomiProd;
        Constants.useOfficial();
        // 构建消息      //Constants.EXTRA_PARAM_NOTIFY_EFFECT默认不设置,就可以正常点击事件
        JSONObject actionJson= JSON.parseObject(action);
        Map map = (Map<String, Object>)actionJson;
        Message message = new Message.Builder()
                .title(title)
                .description(description)
                .payload(action)
                .extra(Constants.EXTRA_PARAM_NOTIFY_FOREGROUND, "1")//是否开启弹窗 1开启0关闭
                //.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_ACTIVITY)  //打开aap内任意ui
                .extra(Constants.EXTRA_PARAM_INTENT_URI, "intent:#Intent;component=me.gaoshou1.ssh.ui.activity.TaskEvaluateCompleteActivity;end")//ui 地址
                //.extra(Constants.EXTRA_PARAM_NOTIFY_EFFECT, Constants.NOTIFY_LAUNCHER_ACTIVITY) //打开点击
                .extra(map)
                .passThrough(0)
                .restrictedPackageName(XMiPushUtil.xiaomiPackageName)
                // 使用默认提示音提示
                .notifyType(1)
                .build();
        // 构建发送
        Sender sender = new Sender(XMiPushUtil.xiaomiAppSecretKey);
        JSONObject result = new JSONObject();
        result.put("message", message);
        result.put("sender", sender);
        return result;
    }

    public static   void sendMessage() throws Exception {
        Constants.useOfficial();
        //Constants.useSandbox();
        Sender sender = new Sender(XMiPushUtil.xiaomiAppSecretKey);
        String messagePayload="This is a message";
        String title = "notification title";
        String description = "notification description";
        Message message = new Message.Builder()
                .title(title)
                .description(description).payload(messagePayload)
                .restrictedPackageName(XMiPushUtil.xiaomiPackageName)
                .notifyType(1)     // 使用默认提示音提示
                .build();
        Result pushResult = sender.send(message, "t3yYJeEMLhr12+CQHiEBDjSFFUqywQ6rdqlZYwDUyqgeEt/DjxM5FIi3L+WdOJmg", 3); //根据regID,发送消息到指定设备上
        logger.info("++++推送到小米结果为:{}"+pushResult.toString());
    }

    public static void main(String[] args) throws Exception{
        String action="{\"purchaseTask\":{\n" +
                "        \"code\":1,\n" +
                "        \"title\":\"任务!\",\n" +
                "        \"content\":\"xxxxx\",\n" +
                "        \"action\":{\n" +
                "            \"openType\":\"3\",\n" +
                "            \"targetPath\":\"ui.activity.ProcurementTaskApplyActivity\",\n" +
                "            \"push_key\":{\n" +
                "                \"id\":\"%s\"\n" +
                "            },\n" +
                "            \"isLogin\":true,\n" +
                "            \"index\":0\n" +
                "        }\n" +
                "    }\n" +
                "}"; //自定义参数
                String title="小米测试";
                String description="这是一条测试消息";//导航栏描述
                String aliasList="W121SCaZBuU7/wP539695asKDKgIpsRqalm0U7WTwhu6Rg3DKyNtqap0ZkVN/sWX";//小米token
                String messagePayload="成功";
        xiaomiBatchPush(messagePayload,title,description,aliasList,"ui.activity.ProcurementTaskApplyActivity",action);
        //sendMessage();
    }
}

 参考文档:小米推送文档

 华为Dome: 

注意华为的推送分为通知和穿透.穿透手机不会有反应,单app控制台会有日志也可以接收到自定义参数

package com.xxx.admin.util;


import com.alibaba.fastjson.JSONObject;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;


public class HuaWeiPushUtil {

    private static Logger logger = Logger.getLogger(HuaWeiPushUtil.class);

    private static String appSecret = "xxxxx";//用户在华为开发者联盟申请Push服务获取的服务参数
    private static  String appId = "xxxx";//用户在华为开发者联盟申请Push服务获取的服务参数
    private static  String tokenUrl = "https://login.cloud.huawei.com/oauth2/v2/token"; //获取认证Token的URL
    private static  String apiUrl = "https://api.push.hicloud.com/pushsend.do"; //应用级消息下发API
    private static  String accessToken;//下发通知消息的认证Token
    private static  long tokenExpiredTime;  //accessToken的过期时间


    public static void refreshToken() {
        try {
            String msgBody = MessageFormat.format("grant_type=client_credentials&client_secret={0}&client_id={1}", URLEncoder.encode(appSecret, "UTF-8"), appId);
            String response = HttpUtil.getJsonDataTB(msgBody,tokenUrl);
            JSONObject obj = JSONObject.parseObject(response);
            accessToken = obj.getString("access_token");
            tokenExpiredTime = System.currentTimeMillis()+(obj.getLong("expires_in")-5 * 60)*1000;
            logger.info(obj+"--------");
            //logger.info(accessToken+"--------");
        } catch (Exception e) {
            logger.error("HvPush -- >> 认证Token获取失败!原因:e = {}", ExceptionUtil.unwrapThrowable(e));
        }
       return ;
    }

    public static String sendPut(String regId,String title,String content,String class1,String action){
        if(tokenExpiredTime <=System.currentTimeMillis())
        {
            refreshToken();
        }
        String postUrl="https://push-api.cloud.huawei.com/v1/"+appId+"/messages:send";
        try {
            JSONObject postBody=new JSONObject(); //整个请求体
            postBody.put("validate_only",false);//控制当前是否为测试消息
            JSONObject message=new JSONObject();//推送体
            message.put("data",action);
            //推送类容
            JSONObject notification=new JSONObject();
            notification.put("title",title);//标题
            notification.put("body",content);//内容
            notification.put("notify_icon","http://i.shihuowang.com/ui/mtzqlogo1024.png");//图标
            message.put("notification",notification);

            //推送设置
            JSONObject android=new JSONObject();
            android.put("collapse_key",-1);//是否缓存消息(离线) 0默认保留一条
            android.put("urgency","HIGH");//是否紧急  HIGH 紧急 NORMAL一般
            //android.put("category","PLAY_VOICE");//标识高优先级透传消息的特殊场景,取值如下:PLAY_VOICE:语音播报 VOIP:VoIP电话
            android.put("ttl","1448s");//离线小时保持时常 单位s
            android.put("bi_tag","Trump"); //批量任务消息标识,消息回执时会返回给应用服务器,应用服务器可以识别bi_tag对消息的下发情况进行统计分析
            android.put("fast_app_target",2);//1:开发态2:生产态
            JSONObject notification1=new JSONObject();
            //notification1.put("image",); //自定义通知栏消息右侧大图标URL,功能和其他地方一样,URL使用的协议必须是HTTPS协议1
            notification1.put("icon","/res/app_icon");//自定义通知栏左侧小图标,此处设置的图标文件必须存放在应用的/res/raw路径下,例如“/raw/ic_launcher”,对应应用本地的“/res/raw/ic_launcher.xxx”文件,支持的文件格式目前包括PNG、JPG
            notification1.put("color","#FFEEFF");//自定义通知栏按钮颜色,以#RRGGBB格式,其中RR代表红色的16进制色素,GG代表绿色的16进制色素,BB代表蓝色的16进制色素,样例:#FFEEFF
            notification1.put("sound","/res/dispatchvoice");//自定义消息通知铃声,在新创建渠道时有效,此处设置的铃声文件必须存放在应用的/res/raw路径下,例如设置为“/raw/shake”,对应应用本地的“/res/raw/shake.xxx”文件,支持的文件格式包括MP3、WAV、MPEG等,如果不设置使用默认系统铃声
            notification1.put("default_sound",false);//默认铃声控制开关,取值如下: true:使用系统默认铃声 false:使用sound自定义铃声
            notification1.put("importance","NORMAL");//Android通知消息分类,决定用户设备消息通知行为,取值如下: LOW:资讯营销类消息 NORMAL:服务与通讯类消息
            JSONObject click_action=new JSONObject();
            click_action.put("type",1);//消息点击行为类型,取值如下: 1:打开应用自定义页面 2:点击后打开特定URL 3:点击后打开应用
            //click_action.put("intent",); //自定义页面中intent的实现,请参见指定intent参数​。 当type为1时,字段intent和action至少二选一
            //click_action.put("url","");//当type为2时必选
            click_action.put("action","ui.activity.TaskEvaluateCompleteActivity"); //app内部自定义页面
            notification1.put("click_action",click_action);
            //notification1.put("body_loc_key","demo_title_new2");
            //List<String> body_loc_args=new ArrayList<>();//本地化body的可变参数,具体使用请参见通知消息本地化。样例:"body_loc_args":["1","2","3"]
            //body_loc_args.add("Boy");
            //body_loc_args.add("Dog");
            //body_loc_args.add("ff");
            //notification1.put("body_loc_args",body_loc_args);
            //notification1.put("title_loc_key","demo_title_new2");
            //List<String> title_loc_args=new ArrayList<>();//本地化body的可变参数,具体使用请参见通知消息本地化。样例:"title_loc_args":["1","2","3"]
            //title_loc_args.add();
            //title_loc_args.add();
            //title_loc_args.add();
            //notification1.put("title_loc_args",title_loc_args);

            //notification1.put("channel_id",);//(普通通知、营销通知)
            notification1.put("auto_clear",300000);//消息展示时长,超过后自动清除,单位:毫秒
            notification1.put("notify_summary",title);//Android通知栏消息简要描述
            notification1.put("style",0);//通知栏样式,取值如下:0:默认样式1:大文本样式3:Inbox样式
            notification1.put("big_title",title); //Android通知栏消息大文本标题,当style为1时必选,设置big_title后通知栏展示时,使用big_title而不用title
            notification1.put("big_body",content);//Android通知栏消息大文本内容,当style为1时必选,设置big_body后通知栏展示时,使用big_body而不用body
            notification1.put("notify_id",-1);//每条消息在通知显示时的唯一标识。不携带时或者设置-1时,Push NC自动为给每条消息生成一个唯一标识;不同的通知栏消息可以拥有相同的notifyId,实现新的消息覆盖上一条消息功能
            notification1.put("group","Espace");//消息分组,例如发送10条带有同样group字段的消息,手机上只会展示该组消息中最新的一条和当前该组接收到的消息总数目,不会展示10条消息

            JSONObject badge=new JSONObject();
            badge.put("add_num",1);//应用角标累加数字非应用角标实际显示数字,为大于0小于100的整数。 例如,某应用当前有N条未读消息,若add_num设置为3,则每发一次消息,应用角标显示的数字累加3,为N+3
            badge.put("class",class1); //应用入口Activity类全路径。 样例:com.example.hmstest.MainActivity
            notification1.put("badge",badge);

            notification1.put("foreground_show",false);
            //notification1.put("ticker",);//设备收到通知消息后状态栏上显示的内容提示。受Android系统原生机制的限制,在Android 5.0版本(API Level 21)之后的设备上,设置了该字段也不会显示
            //notification1.put("when",);//设置通知栏消息的到达时间,如果您同时发送多条消息,Android通知栏中的消息根据这个值进行排序,同时将排序后的消息在通知栏上显示。该时间戳为UTC时间戳,样例:2014-10-02T15:01:23.045123456Z
            //notification1.put("local_only",);
            notification1.put("use_default_vibrate",false);//是否使用系统默认振动模式控制开关。
            notification1.put("use_default_light",false);//是否使用默认呼吸灯模式控制开关
            /**
             * Android通知栏消息可见性,取值如下:
             *
             * “VISIBILITY_UNSPECIFIED”:未指定“visibility”,效果等同于设置了“PRIVATE”。
             * “PUBLIC”:锁屏时收到通知栏消息,显示消息内容。
             * “SECRET”:锁屏时收到通知栏消息,不提示收到通知消息。
             * “PRIVATE”:设置了锁屏密码,“锁屏通知”(导航:“设置 > 通知 > 隐藏通知内容”)选择“隐藏通知内容”时收到通知消息,不显示消息内容。
             */
            notification1.put("visibility","PRIVATE");

            /**
             * Android自定义通知消息振动模式,每个数组元素按照“[0-9]+|[0-9]+[sS]|[0-9]+[.][0-9]{1,9}|[0-9]+[.][0-9]{1,9}[sS]”格式,取值样例["3.5S","2S","1S","1.5S"],数组元素最多支持10个,每个元素数值整数大于0小于等于60。暂不支持EMUI 11。样例:"vibrate_config":["1","3"]
             */
//            List<String> vibrate_config=new ArrayList<>();
//            vibrate_config.add("1");
//            vibrate_config.add("3");
//            notification1.put("vibrate_config",vibrate_config);

            JSONObject light_settings=new JSONObject();

            JSONObject color=new JSONObject();//设置呼吸灯颜色
            color.put("alpha",0);//RGB颜色中的alpha设置,默认值为1,取值范围[0, 1]
            color.put("red",0);
            color.put("green",1);
            color.put("blue",0.1);
            light_settings.put("color",color);
            light_settings.put("light_on_duration","3.5");
            light_settings.put("light_off_duration","5s");
            notification1.put("light_settings",light_settings);
            android.put("notification",notification1);
            message.put("android",android);
            //用户推送标识
            List<String> token=new ArrayList<>();
            token.add(regId);
            message.put("token",token);
            postBody.put("message",message);
            String post =getJsonDataHW(postBody.toJSONString(),postUrl,accessToken);
            logger.info("华为推送 -- >> 返回结果:" + post);
            return post;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }

    public static String sendPut1(String regId,String title,String content,String class1,String action){
        if(tokenExpiredTime <=System.currentTimeMillis())
        {
            refreshToken();
        }
        String postUrl="https://push-api.cloud.huawei.com/v1/"+appId+"/messages:send";
        try {
            String postBody="{\n" +
                    "    \"validate_only\": false,\n" +
                    "    \"message\": {\n" +
                    "        \"notification\": {\n" +
                    "            \"title\": \"title\",\n" +
                    "            \"body\": \"body\"\n" +
                    "        },\n" +
                    "        \"android\": {\n" +
                    "            \"notification\": {\n" +
                    "                \"title\": \"android title\",\n" +
                    "                \"body\": \"android body\",\n" +
                    "                \"click_action\": {\n" +
                    "                    \"type\": 1,\n" +
                    "                    \"intent\": \"intent://com.huawei.codelabpush/deeplink?#Intent;scheme=pushscheme;launchFlags=0x04000000;i.age=180;S.name=abc;end\"\n" +
                    "                }\n" +
                    "            }\n" +
                    "        },\n" +
                    "        \"token\": [\n" +
                    "            \""+regId+"\",\n" +
                    "        ]\n" +
                    "    }\n" +
                    "}";
            String post =getJsonDataHW(postBody,postUrl,accessToken);
            logger.info("华为推送 -- >> 返回结果:" + post);
            return post;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }



    /**
     * 调用淘宝店铺
     * @param jsonParam
     * @param urls
     * @return
     */
    public static String getJsonDataHW(String jsonParam,String urls,String token) {
        StringBuffer sb=new StringBuffer();
        try {
            // 创建url资源
            URL url = new URL(urls);
            // 建立http连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置允许输出
            conn.setDoOutput(true);
            // 设置允许输入
            conn.setDoInput(true);
            // 设置不用缓存
            conn.setUseCaches(false);
            // 设置传递方式
            conn.setRequestMethod("POST");
            // 设置维持长连接
            conn.setRequestProperty("Connection", "Keep-Alive");
            // 设置文件字符集:
            conn.setRequestProperty("Charset", "UTF-8");
            // 转换为字节数组
            byte[] data = (jsonParam).getBytes();
            // 设置文件长度
            conn.setRequestProperty("Content-Language","zh");
            // 设置文件类型:
            conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            conn.setRequestProperty("Authorization", "Bearer "+token);
            // 开始连接请求
            conn.connect();
            OutputStream out = new DataOutputStream(conn.getOutputStream()) ;
            // 写入请求的字符串
            out.write((jsonParam).getBytes());
            out.flush();
            out.close();

            System.out.println(conn.getResponseCode());

            // 请求返回的状态
            if (HttpURLConnection.HTTP_OK == conn.getResponseCode()){
                System.out.println("连接成功");
                // 请求返回的数据
                InputStream in1 = conn.getInputStream();
                try {
                    String readLine=new String();
                    BufferedReader responseReader=new BufferedReader(new InputStreamReader(in1,"UTF-8"));
                    while((readLine=responseReader.readLine())!=null){
                        sb.append(readLine).append("\n");
                    }
                    responseReader.close();
                    System.out.println(sb.toString());

                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            } else {
                System.out.println("error++");

            }

        } catch (Exception e) {

        }

        return sb.toString();

    }


    public static void main(String[] args) {
        String regId="IQAAAACy0jW4AABMF-D61rDUc4jlzDqGfBaNriVUxzmaZa5wF7VNOtVPyj7vL_UPdUtgeeAjjrQJYvl7vE0eEM4fX1vB_N_Zwf0vv_TjmmcsDABI1Q";
        String title="测试";
        String content="ces";
        String action="{\"purchaseTask\":{\n" +
                "        \"code\":1,\n" +
                "        \"title\":\"任务!\",\n" +
                "        \"content\":\"请在10分钟内点击\",\n" +
                "        \"action\":{\n" +
                "            \"openType\":\"3\",\n" +
                "            \"targetPath\":\"ui.activity.ProcurementTaskApplyActivity\",\n" +
                "            \"push_key\":{\n" +
                "                \"id\":\"%s\"\n" +
                "            },\n" +
                "            \"isLogin\":true,\n" +
                "            \"index\":0\n" +
                "        }\n" +
                "    }\n" +
                "}";
        sendPut(regId,title,content,"ui.activity.ProcurementTaskApplyActivity",action);
    }

}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的无activity应用,用于增强QQ的小米服务、vivo服务、OPPO服务、华为服务,并且用if语句判断省电政策是否关闭的Java代码示例: ```java public class App extends Application { private static final String TAG = "PushService"; @Override public void onCreate() { super.onCreate(); if (!isIgnoringBatteryOptimizations()) { requestIgnoreBatteryOptimizations(); } // 小米服务 if (shouldUseMiPush()) { MiPushClient.registerPush(this, "APP_ID", "APP_KEY"); Log.i(TAG, "MiPushClient initialized"); } // vivo服务 if (shouldUseVivoPush()) { PushClient.getInstance(getApplicationContext()).initialize(); Log.i(TAG, "VivoPushClient initialized"); } // OPPO服务 if (shouldUseOppoPush()) { PushManager.getInstance().register(this, "APP_ID", "APP_KEY"); Log.i(TAG, "OppoPushClient initialized"); } // 华为服务 if (shouldUseHuaweiPush()) { HMSAgent.init(this); Log.i(TAG, "HuaweiPushClient initialized"); } } private boolean isIgnoringBatteryOptimizations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { return false; } } return true; } private void requestIgnoreBatteryOptimizations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Intent intent = new Intent(); String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); if (pm != null && !pm.isIgnoringBatteryOptimizations(packageName)) { intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); } } } private boolean shouldUseMiPush() { // 判断是否是小米设备,如果是,则返回true,否则返回false return Build.MANUFACTURER.equalsIgnoreCase("Xiaomi"); } private boolean shouldUseVivoPush() { // 判断是否是vivo设备,如果是,则返回true,否则返回false String manufacturer = Build.MANUFACTURER; String model = Build.MODEL; return (manufacturer.equalsIgnoreCase("vivo") || model.toUpperCase().startsWith("VIVO")); } private boolean shouldUseOppoPush() { // 判断是否是OPPO设备,如果是,则返回true,否则返回false return Build.MANUFACTURER.equalsIgnoreCase("OPPO"); } private boolean shouldUseHuaweiPush() { // 判断是否是华为设备,如果是,则返回true,否则返回false return Build.MANUFACTURER.equalsIgnoreCase("Huawei") || Build.MANUFACTURER.equalsIgnoreCase("Honor"); } } ``` 上述代码中,我们创建了一个名为`App`的类,继承自`Application`类,并重写了`onCreate`方法。在`onCreate`方法中,我们首先判断省电政策是否关闭,如果没有关闭,则请求关闭省电政策。然后,我们根据设备厂商的不同,选择使用小米、vivo、OPPO、华为服务中的一个或多个。在使用服务时,我们需要根据各个厂商的要求,进行相应的初始化操作,例如在使用小米服务时,需要调用`MiPushClient.registerPush`方法进行注册;在使用vivo服务时,需要调用`PushClient.getInstance(getApplicationContext()).initialize()`方法进行初始化;在使用OPPO服务时,需要调用`PushManager.getInstance().register`方法进行注册;在使用华为服务时,需要调用`HMSAgent.init`方法进行初始化。需要注意的是,我们在使用`shouldUseXXXPush`方法判断是否选择使用某个厂商的服务时,要根据实际情况进行判断。同时,如果需要使用多个厂商的服务,也可以在代码中添加相应的判断语句。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值