📄 概述
小程序代码上传服务是一个用于自动化上传小程序代码到微信后台的云服务。通过本服务,开发者可以轻松实现 CI/CD 流程中的代码上传环节。
上传接口完全公开,无需登录和 Token 认证,任何用户均可直接调用。
工作流程
核心特性
| 特性 | 说明 |
|---|---|
| ✅ 无需认证 | 上传接口公开访问,无需登录和 Token |
| ✅ 异步处理 | 基于任务队列,支持高并发上传 |
| ✅ 密钥灵活 | 支持客户端提交密钥或服务器预配置 |
| ✅ 版本管理 | 语义化版本控制,支持版本历史查询 |
⚡ 快速开始
使用以下 cURL 命令快速测试上传接口:
curl -X POST https://up.umiyun.net/api/v1/upload \
-H "Accept: application/json" \
-F "appid=wx1234567890abcdef" \
-F "version=1.0.0" \
-F "description=首次发布版本" \
-F "codePackage=@/path/to/code.zip" \
-F "uploadKey=$(cat /path/to/private.key)"
🔧 API 文档
接口信息
| 项目 | 说明 |
|---|---|
接口 URL |
POST /api/v1/upload |
完整地址 |
https://up.umiyun.net/api/v1/upload |
认证方式 |
无需认证(公开接口) |
Content-Type |
multipart/form-data |
请求头说明
| 请求头 | 是否必填 | 说明 |
|---|---|---|
Content-Type |
必填 | 必须为 multipart/form-data |
Accept |
可选 | 建议设置为 application/json |
Authorization |
可选 | 无需设置,该接口为公开接口 |
📋 请求参数
表单字段
| 字段名 | 类型 | 必填 | 说明 | 示例值 |
|---|---|---|---|---|
appid |
string | 必填 | 小程序 AppID,以 wx 开头 | wx1234567890abcdef |
version |
string | 必填 | 版本号,格式 x.y.z | 1.0.0 |
description |
string | 可选 | 版本描述信息 | 修复登录bug |
codePackage |
file | 必填 | 代码包文件(最大 10MB) | ZIP 文件 |
uploadKey |
string | 条件必填 | 上传密钥(PEM 格式私钥) | 见下方说明 |
参数详细说明
uploadKey 是小程序代码上传密钥,需要从微信公众平台「开发管理」-「开发设置」中下载。下载后得到一个 .key 文件,文件内容即为 PEM 格式的私钥。
密钥配置方式
🔑 方式一:客户端提交(推荐)
- 在请求中提供 uploadKey 字段
- 密钥仅在本次上传中使用
- 任务完成后立即删除
- 适用于临时上传、动态密钥场景
💾 方式二:服务器预配置
- 管理员在服务器配置密钥
- 无需每次上传时提供
- 适用于固定密钥场景
- 需要联系管理员配置
客户端提交 > 服务器预配置。如果两者都未提供,请求将被拒绝。
📥 响应格式
成功响应(HTTP 201)
| 字段 | 类型 | 说明 |
|---|---|---|
success |
boolean | 请求是否成功,固定为 true |
data.taskId |
string | 任务 ID(UUID 格式) |
data.status |
string | 任务状态,初始为 queued |
data.createdAt |
string | 任务创建时间(ISO 8601) |
{
"success": true,
"data": {
"taskId": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"createdAt": "2026-01-14T10:00:00.000Z"
},
"timestamp": "2026-01-14T10:00:00.000Z"
}
任务状态说明
| 状态 | 说明 |
|---|---|
pending | 待处理,任务刚创建 |
queued | 已加入队列,等待处理 |
uploading | 上传中,正在上传到微信后台 |
success | 上传成功 |
failed | 上传失败 |
timeout | 上传超时 |
⚠ 错误码
HTTP 状态码
| 状态码 | 说明 |
|---|---|
201 | 创建成功,任务已加入队列 |
400 | 请求参数错误 |
404 | 资源不存在 |
413 | 请求体过大 |
500 | 服务器内部错误 |
507 | 存储空间不足 |
错误码详解
| 错误码 | HTTP | 说明 | 解决方案 |
|---|---|---|---|
MISSING_REQUIRED_FIELDS |
400 | 缺少必填字段 | 确保包含 appid 和 version |
MISSING_CODE_PACKAGE |
400 | 缺少代码包文件 | 确保包含 codePackage 文件 |
INVALID_VERSION_FORMAT |
400 | 版本号格式错误 | 使用 x.y.z 格式 |
INVALID_UPLOAD_KEY |
400 | 上传密钥格式无效 | 提供有效的 PEM 格式私钥 |
MISSING_UPLOAD_KEY |
400 | 未提供上传密钥 | 提供 uploadKey 或联系管理员 |
APPID_NOT_FOUND |
404 | appid 配置不存在 | 提供 uploadKey 或联系管理员 |
FILE_TOO_LARGE |
413 | 文件大小超过限制 | 压缩代码包或联系管理员 |
INSUFFICIENT_STORAGE |
507 | 存储空间不足 | 联系管理员清理服务器 |
📚 使用教程
准备工作
在开始使用上传服务之前,请确保已完成以下准备工作:
登录微信公众平台,在「开发管理」-「开发设置」中找到小程序的 AppID。AppID 以 wx 开头,共 18 位字符。
在「开发管理」-「开发设置」-「小程序代码上传」中,点击「生成」按钮下载上传密钥。下载后得到一个 .key 文件。
上传密钥非常重要,请妥善保管,不要泄露给他人。如果密钥泄露,请立即在公众平台重新生成。
在「开发管理」-「开发设置」-「小程序代码上传」中,配置服务器 IP 白名单。如果不配置白名单,上传请求将被微信拒绝。
将小程序代码打包为 ZIP 文件。确保 ZIP 文件包含完整的小程序代码,包括 app.json、app.js 等必要文件。
上传代码
完成准备工作后,使用以下命令上传代码:
curl -X POST https://up.umiyun.net/api/v1/upload \
-H "Accept: application/json" \
-F "appid=你的小程序AppID" \
-F "version=1.0.0" \
-F "description=版本描述" \
-F "codePackage=@/path/to/code.zip" \
-F "uploadKey=$(cat /path/to/private.key)"
验证上传结果
上传成功后,可以在微信公众平台「版本管理」中查看上传的代码。也可以通过任务查询接口查询上传状态(需要认证)。
💻 代码示例
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
async function uploadCodePackage(appid, version, description, codePackagePath, uploadKey = null) {
const form = new FormData();
form.append('appid', appid);
form.append('version', version);
form.append('description', description);
form.append('codePackage', fs.createReadStream(codePackagePath));
if (uploadKey) {
form.append('uploadKey', uploadKey);
}
try {
const response = await axios.post('https://up.umiyun.net/api/v1/upload', form, {
headers: {
...form.getHeaders(),
'Accept': 'application/json'
}
});
return response.data;
} catch (error) {
if (error.response) {
throw error.response.data;
}
throw error;
}
}
// 使用示例
(async () => {
try {
const result = await uploadCodePackage(
'wx1234567890abcdef',
'1.0.0',
'首次发布版本',
'./code.zip',
'-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----'
);
console.log('上传成功:', result);
} catch (error) {
console.error('上传失败:', error);
}
})();
import requests
def upload_code_package(appid, version, description, code_package_path, upload_key=None):
"""上传小程序代码包"""
url = 'https://up.umiyun.net/api/v1/upload'
files = {
'codePackage': ('code.zip', open(code_package_path, 'rb'), 'application/zip')
}
data = {
'appid': appid,
'version': version,
'description': description
}
if upload_key:
data['uploadKey'] = upload_key
headers = {'Accept': 'application/json'}
try:
response = requests.post(url, files=files, data=data, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
return e.response.json()
finally:
files['codePackage'][1].close()
# 使用示例
if __name__ == '__main__':
result = upload_code_package(
appid='wx1234567890abcdef',
version='1.0.0',
description='首次发布版本',
code_package_path='./code.zip',
upload_key='-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----'
)
print('上传结果:', result)
import okhttp3.*;
import java.io.File;
import java.io.IOException;
public class MiniProgramUploader {
private static final String UPLOAD_URL = "https://up.umiyun.net/api/v1/upload";
private final OkHttpClient client;
public MiniProgramUploader() {
this.client = new OkHttpClient();
}
public String uploadCodePackage(String appid, String version, String description,
String codePackagePath, String uploadKey) throws IOException {
File codePackage = new File(codePackagePath);
MultipartBody.Builder bodyBuilder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("appid", appid)
.addFormDataPart("version", version)
.addFormDataPart("description", description)
.addFormDataPart("codePackage", "code.zip",
RequestBody.create(codePackage, MediaType.parse("application/zip")));
if (uploadKey != null && !uploadKey.isEmpty()) {
bodyBuilder.addFormDataPart("uploadKey", uploadKey);
}
Request request = new Request.Builder()
.url(UPLOAD_URL)
.header("Accept", "application/json")
.post(bodyBuilder.build())
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
public static void main(String[] args) {
MiniProgramUploader uploader = new MiniProgramUploader();
try {
String result = uploader.uploadCodePackage(
"wx1234567890abcdef",
"1.0.0",
"首次发布版本",
"./code.zip",
"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
);
System.out.println("上传结果: " + result);
} catch (IOException e) {
System.err.println("上传失败: " + e.getMessage());
}
}
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func uploadCodePackage(appid, version, description, codePackagePath, uploadKey string) (map[string]interface{}, error) {
url := "https://up.umiyun.net/api/v1/upload"
var requestBody bytes.Buffer
writer := multipart.NewWriter(&requestBody)
writer.WriteField("appid", appid)
writer.WriteField("version", version)
writer.WriteField("description", description)
file, err := os.Open(codePackagePath)
if err != nil {
return nil, err
}
defer file.Close()
part, _ := writer.CreateFormFile("codePackage", "code.zip")
io.Copy(part, file)
if uploadKey != "" {
writer.WriteField("uploadKey", uploadKey)
}
writer.Close()
req, _ := http.NewRequest("POST", url, &requestBody)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Accept", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
return &result, nil
}
func main() {
result, err := uploadCodePackage(
"wx1234567890abcdef",
"1.0.0",
"首次发布版本",
"./code.zip",
"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
)
if err != nil {
fmt.Printf("上传失败: %v\n", err)
return
}
fmt.Printf("上传结果: %v\n", result)
}
<?php
function uploadCodePackage($appid, $version, $description, $codePackagePath, $uploadKey = null) {
$url = 'https://up.umiyun.net/api/v1/upload';
$codePackage = new CURLFile($codePackagePath, 'application/zip', 'code.zip');
$data = [
'appid' => $appid,
'version' => $version,
'description' => $description,
'codePackage' => $codePackage
];
if ($uploadKey !== null) {
$data['uploadKey'] = $uploadKey;
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Accept: application/json']
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($response, true);
return [
'success' => $httpCode === 201,
'data' => $result
];
}
// 使用示例
$result = uploadCodePackage(
'wx1234567890abcdef',
'1.0.0',
'首次发布版本',
'./code.zip',
"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
);
if ($result['success']) {
echo "上传成功: " . json_encode($result['data']) . "\n";
} else {
echo "上传失败: " . json_encode($result['data']) . "\n";
}
🔧 故障排除
以下是使用上传服务时可能遇到的常见问题及其解决方案:
MISSING_REQUIRED_FIELDS 缺少必填字段
问题描述:请求中缺少 appid 或 version 字段。
- 确保请求中包含
appid字段 - 确保请求中包含
version字段 - 检查字段名是否拼写正确
INVALID_VERSION_FORMAT 版本号格式错误
问题描述:版本号不符合语义化版本格式。
- 使用
x.y.z格式,如1.0.0、2.1.3 - 不要使用前导零,如
01.0.0 - 不要添加额外标签,如
1.0.0-beta
INVALID_UPLOAD_KEY 上传密钥格式无效
问题描述:提供的 uploadKey 不是有效的 PEM 格式私钥。
- 确保密钥以
-----BEGIN PRIVATE KEY-----开头 - 确保密钥以
-----END PRIVATE KEY-----结尾 - 检查密钥内容是否完整,没有被截断
- 如果是通过命令行传递,确保正确转义换行符
FILE_TOO_LARGE 文件大小超过限制
问题描述:上传的代码包文件超过 10MB 限制。
- 压缩代码包,删除不必要的文件
- 排除 node_modules、.git 等大型目录
- 联系管理员调整服务器配置
APPID_NOT_FOUND appid 配置不存在
问题描述:服务器未配置该 appid 的密钥,且请求中未提供 uploadKey。
- 在请求中提供
uploadKey字段 - 或联系管理员在服务器端配置该 appid 的密钥
上传成功但微信后台未显示
问题描述:接口返回成功,但微信公众平台「版本管理」中没有看到代码。
- 检查服务器 IP 是否已添加到微信公众平台的白名单
- 确认 uploadKey 是对应小程序的正确密钥
- 等待几分钟,微信后台可能有延迟
- 检查任务状态是否为
success
网络连接超时
问题描述:请求上传接口时出现连接超时或网络错误。
- 检查网络连接是否正常
- 确认域名
up.umiyun.net可以正常解析 - 检查防火墙是否阻止了请求
- 尝试使用代理或更换网络环境
❓ 常见问题
不需要。上传接口完全公开,无需登录和 Token 认证。任何用户均可直接调用该接口上传代码。
uploadKey 是小程序代码上传密钥,用于授权服务上传代码到微信后台。
获取方式:
- 登录微信公众平台
- 进入「开发管理」-「开发设置」
- 找到「小程序代码上传」部分
- 点击「生成」按钮下载密钥文件
上传成功后会返回 taskId,有以下方式查看结果:
- 微信公众平台:登录公众平台,在「版本管理」中查看上传的代码
- 任务查询接口:使用
GET /api/v1/tasks/:taskId查询任务状态(需要认证)
默认限制为 10MB。如果代码包超过此限制,可以:
- 压缩代码包,删除不必要的文件
- 排除 node_modules、.git 等大型目录
- 联系管理员调整服务器配置
版本号必须使用语义化版本格式 x.y.z,其中 x、y、z 均为非负整数。
✅ 有效示例:1.0.0、2.1.3、10.20.30
❌ 无效示例:1.0、v1.0.0、1.0.0-beta、01.0.0
可能的原因:
- IP 白名单未配置:需要在微信公众平台配置服务器 IP 白名单
- 密钥不匹配:确认 uploadKey 是对应小程序的正确密钥
- 处理延迟:微信后台可能有延迟,请等待几分钟
- 任务未完成:检查任务状态是否为
success
- 登录微信公众平台
- 进入「开发管理」-「开发设置」
- 找到「小程序代码上传」部分
- 在「IP白名单」中添加服务器 IP 地址
- 保存配置
如果不配置 IP 白名单,微信会拒绝上传请求,导致上传失败。
可以。本服务非常适合集成到 CI/CD 流程中:
- 无需登录认证,直接调用接口
- 支持命令行工具(如 cURL)调用
- 提供多种编程语言的 SDK 示例
- 支持异步处理,适合自动化流程
© 2026 小程序代码上传服务. All rights reserved.
如有问题,请联系技术支持