Gerrit Replication自动同步代码到Gitlab

该方案旨在实现在不同的 Git 代码托管平台( Gerrit 和 GitLab)之间的代码迁移和同步。在这里插入图片描述

一、部署Gerrit

切换root用户

sudo su

新建gerrit用户

sudo adduser gerrit                          # 创建gerrit用户
sudo usermod -aG sudo gerrit    # 赋予sudo管理权限
su gerrit                                                # 切换到gerrit用户

OpenJdk8

sudo apt install -y openjdk-8-jdk

Nginx

sudo apt install -y nginx
apache2-utils
apt udapte
sudo apt install -y apache2-utils

Gerrit

mkdir ~/gerrit_server
cd gerrit_server
wget https://gerrit-releases.storage.googleapis.com/gerrit-3.0.0.war
java -jar gerrit*.war init -d review_site

Nginx代理

cat /etc/nginx/nginx.conf 
events {
    # 定义事件处理参数,如 worker_connections
    worker_connections  1024;
}

http {
    # 设置日志格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # 设置访问日志路径和格式
    access_log  /var/log/nginx/access.log  main;

    # 设置错误日志路径
    error_log  /var/log/nginx/error.log  error;

    # 设置默认服务器
    server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # 设置默认服务器的根目录
        root /var/www/html;

        # 设置默认服务器的主页
        index index.html index.htm index.nginx-debian.html;

        # 处理默认服务器的请求
        location / {
            try_files $uri $uri/ =404;
        }
    }

    # 设置访问代理
    server {
        # 设置访问代理端口
        listen *:8443;
        server_name localhost;

        location / {
            auth_basic              "Welcome to Gerrit Code Review Site";
            auth_basic_user_file    /home/gerrit/gerrit_server/review_site/etc/passwd;
            proxy_pass              http://localhost:8081;
            proxy_set_header        X-Forwarded-For $remote_addr;
            proxy_set_header        Host $host;
        }

        location /login/ {
            proxy_pass              http://localhost:8081;
            proxy_set_header        X-Forwarded-For $remote_addr;
            proxy_set_header        Host $host;
        }
    }
}

报错记录:
查看报错日志

sudo  cat /var/log/nginx/error.log
2024/04/29 15:09:41 [crit] 68075#68075: *48 open() "/home/gerrit/gerrit_server/review_site/etc/passwd" failed (13: Permission denied), client: 59.33.175.234, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "106.53.*.*:8443", referrer: "http://106.53.*.*:8443/"
此时访问报错500 原因是nginx进程用户是nobody,但是/home/gerrit/gerrit_server/review_site/etc/passwd是gerrit权限:
解决方法:
sudo chmod o+r /home/gerrit/gerrit_server/review_site/etc/passwd
sudo nginx -s reload

再次访问正常。

二、部署Gitlab

sudo su
sudo apt install -y curl openssh-server ca-certificates postfix
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.linuxtechi.net" apt install gitlab-ce
sudo dpkg -i gitlab-ce_15.10.0-ce.0_amd64.deb
cat /etc/gitlab/gitlab.rb
external_url 'http://106.53.*.*'
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
  • 用户名:root
  • 密码:从 /etc/gitlab/initial_root_password 获取密码
**************************************=

三、权限配置

ssh-keygen -m PEM -t rsa -C "wzk@test.com" 注意要使用PEM
gerrit--->gitlab
ssh-copy-id ubuntu@106.53.*.*
gitlab--->gerrit
ssh-copy-id gerrit@106.53.*.*

设置gerrit同步gitlab的配置文件(配置gitlab服务器的访问权限)

vi ~/.ssh/config
HOST 106.53.*.*
    User ubuntu
    Port 22
    IdentityFile ~/.ssh/id_rsa
    PreferredAuthentications publickey
    PubkeyAcceptedKeyTypes +ssh-rsa
HOST 106.53.*.*
    User gerrit
    PubkeyAcceptedKeyTypes +ssh-rsa
    IdentityFile ~/.ssh/id_rsa
    Port 29418

三、replication插件配置

  1. 在gerrit的git仓库目录内删除wangzk-test仓库
sudo rm -rf wangzk-test.git
  1. 下载gitlab的wangzk-test仓库,需要指定–bare进行独立拉取以便脱离远程分支
git clone --bare ssh://git@106.53.*.*/root/wangzk-test.git
  1. 自动同步项目配置
vim ~/gerrit_server/review_site/etc/replication.config 
[remote "wangzk-test"]
        rescheduleDelay = 15

        projects = wangzk-test

        url = ssh://git@106.53.*.*/root/wangzk-test.git

        push = +refs/heads/*:refs/heads/*

        push = +refs/tags/*:refs/tags/*

        push = +refs/changes/*:refs/changes/*

        threads = 3

保存退出, 并重启

~/gerrit_server/review_site/bin/gerrit.sh restart

五、gerrit拉取并修改同步项目

git clone "ssh://gerrit@106.53.*.*:29418/wangzk-test" && scp -p -P 29418 gerrit@106.53.*.*:hooks/commit-msg "wangzk-test/.git/hooks/"

报错记录:
报错:

[sudo] password for gerrit: 
Cloning into 'wangzk-test'...
gerrit@106.53.*.*: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

原因:在Gerrit服务器的OpenSSH的版本号,如果版本≥8.8,就会出现这个问题,终端执行ssh -V查看,发现版本号≥8.8,就需要如下操作:

cat ~/.ssh/config 
HOST 106.53.*.*
    User ubuntu    #gitlab服务器用户名
    Port 22    # gitlab 访问端口, 如果默认22 将不用添加该项
    IdentityFile /home/ubuntu/.ssh/id_rsa     # 秘钥在服务器的路径
    PreferredAuthentications publickey  # 首选认证方式
HOST 106.53.*.*
    User gerrit
    PubkeyAcceptedKeyTypes +ssh-rsa
    IdentityFile ~/.ssh/id_rsa
    Port 29418

再重新拉取,就可以拉取成功了。

报错:cat ~/gerrit_server/review_site/logs/replication_log
[2024-04-30 11:56:52,166] [74c4c4b0] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 11:56:52,166] [74c4c4b0] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 11:56:52,167] [74c4c4b0] Cannot replicate to ssh://git@106.53.*.*/root/wangzk-test.git
org.eclipse.jgit.errors.TransportException: ssh://git@106.53.*.*/root/wangzk-test.git: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa     # 秘钥在服务器的路径 (Permission denied)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:191)
        at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:140)
        at org.eclipse.jgit.transport.TransportGitSsh$SshPushConnection.<init>(TransportGitSsh.java:339)
        at org.eclipse.jgit.transport.TransportGitSsh.openPush(TransportGitSsh.java:176)
        at org.eclipse.jgit.transport.PushProcess.execute(PushProcess.java:160)
        at org.eclipse.jgit.transport.Transport.push(Transport.java:1346)
        at org.eclipse.jgit.transport.Transport.push(Transport.java:1392)
        at com.googlesource.gerrit.plugins.replication.PushOne.pushVia(PushOne.java:462)
        at com.googlesource.gerrit.plugins.replication.PushOne.runImpl(PushOne.java:432)
        at com.googlesource.gerrit.plugins.replication.PushOne.runPushOperation(PushOne.java:316)
        at com.googlesource.gerrit.plugins.replication.PushOne.lambda$run$0(PushOne.java:282)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$cleanup$1(RequestScopePropagator.java:182)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$context$0(RequestScopePropagator.java:170)
        at com.google.gerrit.server.git.PerThreadRequestScope$Propagator.lambda$scope$0(PerThreadRequestScope.java:70)
        at com.googlesource.gerrit.plugins.replication.PushOne.run(PushOne.java:285)
        at com.google.gerrit.server.logging.LoggingContextAwareRunnable.run(LoggingContextAwareRunnable.java:72)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at com.google.gerrit.server.git.WorkQueue$Task.run(WorkQueue.java:610)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)
Caused by: com.jcraft.jsch.JSchException: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa     # 秘钥在服务器的路径 (Permission denied)
        at com.jcraft.jsch.KeyPair.load(KeyPair.java:543)
        at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
        at com.jcraft.jsch.JSch.addIdentity(JSch.java:407)
        at com.jcraft.jsch.JSch.addIdentity(JSch.java:367)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:399)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:335)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:208)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:138)
        ... 23 more
Caused by: java.io.FileNotFoundException: /home/ubuntu/.ssh/id_rsa     # 秘钥在服务器的路径 (Permission denied)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at com.jcraft.jsch.Util.fromFile(Util.java:508)
        at com.jcraft.jsch.KeyPair.load(KeyPair.java:540)
        ... 30 more

解决方法:

gerrit@VM-12-16-ubuntu:/home/ubuntu$ cat ~/.ssh/config 
HOST 106.53.*.*
    User ubuntu    #gitlab服务器用户名
    Port 22
    IdentityFile ~/.ssh/id_rsa
    PreferredAuthentications publickey
    PubkeyAcceptedKeyTypes +ssh-rsa
HOST 106.53.*.*
    User gerrit
    PubkeyAcceptedKeyTypes +ssh-rsa
    IdentityFile ~/.ssh/id_rsa
    Port 29418

查看已加载的插件配置

ssh -p 29418 106.53.*.* gerrit plugin ls
Name                           Version    Status   File
-------------------------------------------------------------------------------
codemirror-editor              v3.0.0     ENABLED  codemirror-editor.jar
commit-message-length-validator v3.0.0     ENABLED  commit-message-length-validator.jar
delete-project                 v3.0.0     ENABLED  delete-project.jar
download-commands              v3.0.0     ENABLED  download-commands.jar
gitiles                        v3.0.0     ENABLED  gitiles.jar
hooks                          v3.0.0     ENABLED  hooks.jar
plugin-manager                 v3.0.0     ENABLED  plugin-manager.jar
replication                    v3.0.0     ENABLED  replication.jar
reviewnotes                    v3.0.0     ENABLED  reviewnotes.jar
singleusergroup                v3.0.0     ENABLED  singleusergroup.jar
webhooks                       v3.0.0     ENABLED  webhooks.jar
报错:[2024-04-30 13:54:53,279] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 13:54:53,280] [ab022398] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 13:54:53,284] [ab022398] Cannot replicate to ssh://git@106.53.*.*/root/wangzk-test.git
org.eclipse.jgit.errors.TransportException: ssh://git@106.53.*.*/root/wangzk-test.git: invalid privatekey: [B@61d70fa2
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:191)
        at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:140)
        at org.eclipse.jgit.transport.TransportGitSsh$SshPushConnection.<init>(TransportGitSsh.java:339)
        at org.eclipse.jgit.transport.TransportGitSsh.openPush(TransportGitSsh.java:176)
        at org.eclipse.jgit.transport.PushProcess.execute(PushProcess.java:160)
        at org.eclipse.jgit.transport.Transport.push(Transport.java:1346)
        at org.eclipse.jgit.transport.Transport.push(Transport.java:1392)
        at com.googlesource.gerrit.plugins.replication.PushOne.pushVia(PushOne.java:462)
        at com.googlesource.gerrit.plugins.replication.PushOne.runImpl(PushOne.java:432)
        at com.googlesource.gerrit.plugins.replication.PushOne.runPushOperation(PushOne.java:316)
        at com.googlesource.gerrit.plugins.replication.PushOne.lambda$run$0(PushOne.java:282)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$cleanup$1(RequestScopePropagator.java:182)
        at com.google.gerrit.server.util.RequestScopePropagator.lambda$context$0(RequestScopePropagator.java:170)
        at com.google.gerrit.server.git.PerThreadRequestScope$Propagator.lambda$scope$0(PerThreadRequestScope.java:70)
        at com.googlesource.gerrit.plugins.replication.PushOne.run(PushOne.java:285)
        at com.google.gerrit.server.logging.LoggingContextAwareRunnable.run(LoggingContextAwareRunnable.java:83)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at com.google.gerrit.server.git.WorkQueue$Task.run(WorkQueue.java:610)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)
Caused by: com.jcraft.jsch.JSchException: invalid privatekey: [B@61d70fa2
        at com.jcraft.jsch.KeyPair.load(KeyPair.java:664)
        at com.jcraft.jsch.KeyPair.load(KeyPair.java:561)
        at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40)
        at com.jcraft.jsch.JSch.addIdentity(JSch.java:407)
        at com.jcraft.jsch.JSch.addIdentity(JSch.java:367)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getJSch(JschConfigSessionFactory.java:399)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:335)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.createSession(JschConfigSessionFactory.java:208)
        at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:138)
        ... 23 more

解决方法:
原因是生成密钥的时候使用openssh版本生成导致版本过高:

ssh-keygen -m PEM -t rsa 重新生成旧格式的key

再次重新加载配置

~/gerrit_server/review_site/bin/gerrit.sh restart

推送成功

[2024-04-30 14:06:55,545] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git started...
[2024-04-30 14:06:55,546] [ab022398] Push to ssh://git@106.53.*.*/root/wangzk-test.git references: [RemoteRefUpdate[remoteName=refs/heads/main, NOT_ATTEMPTED, (null)...5abe0ff4e36883fc6be6531479c423daa4de2461, srcRef=refs/heads/main, forceUpdate, message=null]]
[2024-04-30 14:07:00,034] [ab022398] Replication to ssh://git@106.53.*.*/root/wangzk-test.git completed in 4489ms, 857340ms delay, 14 retries

查看gitlab仓库,发现推送到gerrit的信息同步到了gitlab上:在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/78a721a23b44490ba7612e666b233e00.png在这里插入图片描述
在这里插入图片描述

四、测试:将gerrit已存在的项目同步到gitlab的空项目(同名项目已创建)

不可以将已存在的代码仓库直接replication同步到gitlab,需要如下操作步骤:
将 Gerrit 中的所有代码、分支和提交信息复制到 GitLab:

  1. 在 GitLab 中创建新项目:首先,在 GitLab 中创建一个新项目,以便将 Gerrit 中的代码复制过去。在 GitLab 的界面上,点击 “New Project” 或者 “New Repository”.
  2. 克隆 Gerrit 仓库:使用 Git 命令克隆 Gerrit 仓库到本地:
git clone --mirror "ssh://gerrit@106.53.*.*:29418/test0506" && scp -p -P 29418 gerrit@106.53.*.*2:hooks/commit-msg "test0506/.git/hooks/"

–mirror 是 Git 中用于克隆镜像仓库的选项。克隆镜像仓库时,会复制源仓库的所有引用(包括分支、标签等),并将它们作为裸仓库(bare repository)保存在本地。裸仓库不包含工作目录,只包含 Git 版本控制所需的文件。这意味着你不能在镜像仓库中进行常规的开发工作,但可以用于克隆和同步远程仓库的完整副本。
使用 --mirror 选项克隆镜像仓库的主要优点是它可以保持源仓库的完整性和一致性,包括所有的分支、标签和提交历史。这样,在需要备份或者迁移仓库时,镜像仓库可以提供一个完整的副本,确保不丢失任何数据。
具体来说,–mirror 选项会做以下几件事情:

  1. 复制所有引用:包括分支、标签和其他引用。
  2. 不创建工作目录:裸仓库不包含工作目录,只包含 Git 版本控制所需的文件。
  3. 保持完整性:保持源仓库的完整性和一致性,包括所有的分支、标签和提交历史。
    添加 GitLab 作为远程仓库:进入到克隆下来的 Gerrit 仓库目录中,然后将 GitLab 仓库添加为远程仓库:
    cd test0506.git
git remote add gitlab ssh://git@106.53.*.*:/root/test0506.git

推送代码、分支和提交信息到 GitLab:将本地仓库中的所有内容(包括所有分支、提交等)推送到 GitLab 仓库:

git push gitlab --all

推送标签:

git push gitlab --tags

在这里插入图片描述
开始gerrit与gitlab同步:

cd /home/gerrit/gerrit_server/review_site/git
ls -l
total 24
drwxrwxr-x+ 7 gerrit gerrit 4096 Apr 29 13:41 All-Projects.git
drwxrwxr-x+ 7 gerrit gerrit 4096 Apr 29 15:14 All-Users.git
drwxrwxr-x  7 gerrit gerrit 4096 Apr 29 15:23 test0429.git
drwxrwxr-x  7 gerrit gerrit 4096 May  6 16:20 test0506.git
drwxrwxr-x  7 gerrit gerrit 4096 Apr 30 14:53 test-two.git
drwxrwxr-x  8 gerrit gerrit 4096 May  6 16:02 wangzk-test.git
sudo rm -rf test0506.git
git clone --bare ssh://git@106.53.*.*/root/test0506.git
vim ~/gerrit_server/review_site/etc/replication.config
[remote "test0506"]
        rescheduleDelay = 15

        projects = test0506

        url = ssh://git@106.53.*.*:/root/test0506.git

        push = +refs/heads/*:refs/heads/*

        push = +refs/tags/*:refs/tags/*

重新加载replication配置:

~/gerrit_server/review_site/bin/gerrit.sh restart

上传文件到gerrit,观察gitlab:

git clone "ssh://gerrit@106.53.*.*:29418/test0506" && scp -p -P 29418 gerrit@106.53*.*:hooks/commit-msg "test0506/.git/hooks/"
Cloning into 'test0506'...
remote: Counting objects: 11, done
remote: Finding sources: 100% (11/11)
remote: Total 11 (delta 0), reused 11 (delta 0)
Receiving objects: 100% (11/11), done.
commit-msg                                                                             100% 1790   712.2KB/s   00:00    
gerrit@VM-12-16-ubuntu:~/test$ ls
test0506  test-two  wangzk-test
gerrit@VM-12-16-ubuntu:~/test$ cd test0506/
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
README.md
gerrit@VM-12-16-ubuntu:~/test/test0506$ git branch
* main
gerrit@VM-12-16-ubuntu:~/test/test0506$ git checkout master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Switched to a new branch 'master'
gerrit@VM-12-16-ubuntu:~/test/test0506$ git branch
  main
* master
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
11111.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ vim 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ ls
11111.txt  2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ git add .
gerrit@VM-12-16-ubuntu:~/test/test0506$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   2222.txt

gerrit@VM-12-16-ubuntu:~/test/test0506$ git commit -m'[2222.txt][upgrade][xxxxx][No ID][NA]'
[master 35ca15c] [2222.txt][upgrade][xxxxx][No ID][NA]
 1 file changed, 1 insertion(+)
 create mode 100644 2222.txt
gerrit@VM-12-16-ubuntu:~/test/test0506$ git push origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 324 bytes | 324.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Processing changes: refs: 1, done    
To ssh://106.53.*.*:29418/test0506
   c51dee1..35ca15c  master -> master
gerrit@VM-12-16-ubuntu:~/test/test0506$ 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
同步成功。

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值