米洛SDK产品概述

米洛SDK是一款专业的手游聚合发行平台SDK,为游戏开发者提供从渠道接入、用户管理、支付聚合到数据分析的一站式解决方案。

为什么选择米洛SDK?

  • 一次接入,多渠道分发 - 支持200+主流渠道,无需重复开发
  • 快速上线 - 标准化接口,平均3天完成接入
  • 稳定可靠 - 99.99%系统可用性,7×24小时技术支持
  • 完全免费 - 无前期接入费用,降低开发成本

适用场景

重度RPG

高并发支付保障、跨服交易、深度运营体系

休闲游戏

批量管理、广告聚合、轻量级SDK

出海发行

多币种支付、多语言本地化、全球渠道对接

核心功能

1. 聚合渠道SDK

一次接入即可在200+渠道分发,包括:

  • 硬核联盟 - 华为、OPPO、vivo、小米、魅族等
  • 应用商店 - App Store、Google Play、应用宝、360手机助手等
  • 第三方平台 - 九游、TapTap、好游快爆等

2. 统一支付系统

多渠道支付聚合,智能路由分配:

  • 支持微信、支付宝、银联等主流支付方式
  • 智能支付路由,自动选择最优支付通道
  • 实时对账清算,支付成功率98%+
  • 支持50+币种,满足海外发行需求

3. 智能数据平台

全方位数据分析,驱动精细化运营:

  • 实时数据监控,秒级延迟
  • 多维度分析报表(留存、付费、LTV等)
  • AI驱动的运营决策支持
  • 自定义事件追踪与漏斗分析

4. 用户管理中心

统一账号体系,多方式登录:

  • 手机号、邮箱、第三方账号登录
  • 用户画像与分群管理
  • 精准消息推送与触达

快速接入指南

仅需4步,最快3天即可完成SDK接入并上线。

01

需求沟通

联系商务团队,明确您的游戏类型与发行需求,我们将量身定制最优方案。

02

获取SDK

从开发者平台下载对应平台的SDK包,包含SDK文件、Demo示例和完整文档。

SDK下载
// Android SDK
implementation 'com.miluosdk:core:5.0.0'
implementation 'com.miluosdk:payment:5.0.0'

// iOS (CocoaPods)
pod 'MiluoSDK', '~> 5.0.0'
pod 'MiluoSDK/Payment', '~> 5.0.0'
03

技术对接

按照文档指引完成SDK初始化、登录、支付等核心功能接入。我们提供一对一技术支持。

04

联调上线

完成联合测试后,提交审核上线。整个过程有专属技术团队全程跟进。

Android SDK 接入文档

环境要求

  • Android 5.0 (API Level 21) 及以上
  • Gradle 4.0+ 或 Maven
  • 支持 armeabi-v7a、arm64-v8a、x86_64 架构

1. 集成SDK

build.gradle
dependencies {
    // 核心SDK
    implementation 'com.miluosdk:core:5.0.0'
    // 支付模块(可选)
    implementation 'com.miluosdk:payment:5.0.0'
    // 数据统计模块(可选)
    implementation 'com.miluosdk:analytics:5.0.0'
}

2. 初始化SDK

Application.java
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 初始化配置
        MiluoConfig config = new MiluoConfig.Builder()
            .appId("YOUR_APP_ID")
            .appKey("YOUR_APP_KEY")
            .channelId("default")
            .debug(BuildConfig.DEBUG)
            .build();
        
        // 初始化SDK
        MiluoSDK.init(this, config);
    }
}

3. 实现登录功能

LoginActivity.java
// 发起登录
MiluoSDK.login(new MiluoCallback<MiluoUser>() {
    @Override
    public void onSuccess(MiluoUser user) {
        // 登录成功
        String userId = user.getUserId();
        String token = user.getToken();
        // 将token发送到您的游戏服务器验证
    }
    
    @Override
    public void onError(int code, String message) {
        // 登录失败
        Log.e("MiluoSDK", "Login failed: " + message);
    }
    
    @Override
    public void onCancel() {
        // 用户取消登录
    }
});

4. 实现支付功能

PaymentActivity.java
// 创建支付订单
MiluoPayOrder order = new MiluoPayOrder.Builder()
    .productId("product_001")
    .productName("100钻石")
    .amount(1000) // 单位:分
    .roleId("player_123")
    .roleName("玩家昵称")
    .serverId("server_01")
    .callbackUrl("https://your-server.com/pay/callback")
    .build();

// 发起支付
MiluoSDK.pay(order, new MiluoCallback<MiluoPayResult>() {
    @Override
    public void onSuccess(MiluoPayResult result) {
        // 支付成功
        Toast.makeText(context, "支付成功", Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onError(int code, String message) {
        // 支付失败
        Toast.makeText(context, "支付失败: " + message, Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onCancel() {
        // 用户取消支付
    }
});

5. 数据统计

Analytics示例
// 自定义事件
MiluoAnalytics.trackEvent("level_complete", 
    new HashMap<String, Object>() {{
        put("level", 10);
        put("score", 5000);
        put("time", 120);
    }}
);

// 用户属性设置
MiluoAnalytics.setUserProperty("vip_level", "5");
MiluoAnalytics.setUserProperty("total_pay", "10000");

iOS SDK 接入文档

环境要求

  • iOS 12.0 及以上
  • Xcode 13.0+
  • 支持 CocoaPods 或手动集成

1. 集成SDK (CocoaPods)

Podfile
platform :ios, '12.0'

target 'YourApp' do
  use_frameworks!
  
  pod 'MiluoSDK', '~> 5.0.0'
  pod 'MiluoSDK/Payment', '~> 5.0.0'
  pod 'MiluoSDK/Analytics', '~> 5.0.0'
end

2. 初始化SDK

AppDelegate.swift
import MiluoSDK

func application(_ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: 
    [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    let config = MiluoConfig(
        appId: "YOUR_APP_ID",
        appKey: "YOUR_APP_KEY",
        channelId: "default",
        debug: true
    )
    
    MiluoSDK.initialize(config: config)
    
    return true
}

3. 登录与支付

Swift示例
// 登录
MiluoSDK.login { result in
    switch result {
    case .success(let user):
        print("登录成功: \(user.userId)")
        // 发送token到游戏服务器
    case .failure(let error):
        print("登录失败: \(error.localizedDescription)")
    case .cancelled:
        print("用户取消登录")
    }
}

// 支付
let order = MiluoPayOrder(
    productId: "product_001",
    productName: "100钻石",
    amount: 1000,
    roleId: "player_123",
    roleName: "玩家昵称"
)

MiluoSDK.pay(order: order) { result in
    switch result {
    case .success:
        print("支付成功")
    case .failure(let error):
        print("支付失败: \(error.localizedDescription)")
    case .cancelled:
        print("用户取消支付")
    }
}

Unity SDK 接入文档

环境要求

  • Unity 2019.4 及以上版本
  • 支持Android和iOS双平台

1. 导入SDK

从开发者平台下载Unity SDK包(.unitypackage),导入到您的Unity项目中。

2. 初始化SDK

C# 示例
using MiluoSDK;

public class GameManager : MonoBehaviour
{
    void Start()
    {
        // 初始化配置
        MiluoConfig config = new MiluoConfig
        {
            AppId = "YOUR_APP_ID",
            AppKey = "YOUR_APP_KEY",
            ChannelId = "default",
            Debug = true
        };
        
        // 初始化SDK
        MiluoSDK.Initialize(config);
    }
}

3. 登录与支付

C# 示例
// 登录
public void OnLoginButton()
{
    MiluoSDK.Login(
        onSuccess: (user) => {
            Debug.Log($"登录成功: {user.UserId}");
            // 处理登录成功逻辑
        },
        onError: (code, message) => {
            Debug.LogError($"登录失败: {message}");
        },
        onCancel: () => {
            Debug.Log("用户取消登录");
        }
    );
}

// 支付
public void OnPayButton()
{
    var order = new MiluoPayOrder
    {
        ProductId = "product_001",
        ProductName = "100钻石",
        Amount = 1000,
        RoleId = "player_123",
        RoleName = "玩家昵称"
    };
    
    MiluoSDK.Pay(order,
        onSuccess: (result) => {
            Debug.Log("支付成功");
        },
        onError: (code, message) => {
            Debug.LogError($"支付失败: {message}");
        },
        onCancel: () => {
            Debug.Log("用户取消支付");
        }
    );
}

HarmonyOS SDK 接入文档

环境要求

  • HarmonyOS NEXT 及以上
  • DevEco Studio 4.0+
  • API Version 9+

1. 集成SDK

oh-package.json5
{
  "dependencies": {
    "@miluosdk/core": "^5.0.0",
    "@miluosdk/payment": "^5.0.0"
  }
}

2. 初始化与使用

ArkTS 示例
import { MiluoSDK, MiluoConfig } from '@miluosdk/core';

// 初始化
let config = new MiluoConfig({
  appId: 'YOUR_APP_ID',
  appKey: 'YOUR_APP_KEY',
  channelId: 'default',
  debug: true
});

MiluoSDK.initialize(config);

// 登录
MiluoSDK.login({
  onSuccess: (user) => {
    console.log('登录成功:', user.userId);
  },
  onError: (code, message) => {
    console.error('登录失败:', message);
  }
});

服务端接入概述

服务端SDK负责处理支付回调验证、签名校验、订单查询等核心业务逻辑,确保交易安全性和数据一致性。

为什么需要服务端接入?

  • 安全验证 - 验证支付回调的真实性,防止伪造请求
  • 订单管理 - 查询订单状态、退款处理
  • 数据同步 - 实时接收支付结果,更新用户账户
  • 防重放攻击 - 通过签名和时序验证确保请求唯一性

支持的语言

Java

Maven/Gradle依赖,支持Spring Boot

PHP

Composer包,支持Laravel/ThinkPHP

Python

pip安装,支持Django/Flask

Node.js

npm包,支持Express/Koa

Go

go get安装,支持Gin/Beego

C#

NuGet包,支持.NET Core

服务端初始化配置

1. Java SDK

Maven依赖
<dependency>
    <groupId>com.miluosdk</groupId>
    <artifactId>server-sdk</artifactId>
    <version>5.0.0</version>
</dependency>
初始化示例
import com.miluosdk.server.MiluoServerSDK;
import com.miluosdk.server.config.MiluoConfig;

public class MiluoInitializer {
    public static void init() {
        // 配置参数
        MiluoConfig config = new MiluoConfig();
        config.setAppId("YOUR_APP_ID");
        config.setAppKey("YOUR_APP_KEY");
        config.setServerKey("YOUR_SERVER_KEY");
        config.setNotifyUrl("https://your-server.com/api/miluo/callback");
        
        // 初始化SDK
        MiluoServerSDK.initialize(config);
    }
}

2. PHP SDK

Composer安装
composer require miluosdk/server-sdk
初始化示例
<?php
require_once 'vendor/autoload.php';

use MiluoSDK\ServerSDK;
use MiluoSDK\Config\MiluoConfig;

$config = new MiluoConfig([
    'app_id' => 'YOUR_APP_ID',
    'app_key' => 'YOUR_APP_KEY',
    'server_key' => 'YOUR_SERVER_KEY',
    'notify_url' => 'https://your-server.com/api/miluo/callback'
]);

ServerSDK::initialize($config);
?>

3. Python SDK

pip安装
pip install miluosdk-server
初始化示例
from miluosdk import MiluoServerSDK
from miluosdk.config import MiluoConfig

config = MiluoConfig(
    app_id='YOUR_APP_ID',
    app_key='YOUR_APP_KEY',
    server_key='YOUR_SERVER_KEY',
    notify_url='https://your-server.com/api/miluo/callback'
)

MiluoServerSDK.initialize(config)

4. Node.js SDK

npm安装
npm install @miluosdk/server-sdk
初始化示例
const MiluoServerSDK = require('@miluosdk/server-sdk');

const config = {
    appId: 'YOUR_APP_ID',
    appKey: 'YOUR_APP_KEY',
    serverKey: 'YOUR_SERVER_KEY',
    notifyUrl: 'https://your-server.com/api/miluo/callback'
};

MiluoServerSDK.initialize(config);

签名验证机制

米洛SDK采用HMAC-SHA256签名算法,确保数据传输的完整性和真实性。

重要提示

  • ServerKey保密 - 严禁在客户端代码中使用ServerKey
  • 验证签名 - 所有服务端回调必须验证签名
  • 时序验证 - 检查请求时间戳,防止重放攻击(有效期5分钟)
  • 参数完整 - 不要修改或遗漏任何回调参数

签名算法说明

签名生成步骤:

  1. 将所有参数按字母顺序排序
  2. 拼接成 key1=value1&key2=value2 格式
  3. 在末尾追加 &server_key=YOUR_SERVER_KEY
  4. 对拼接后的字符串进行 HMAC-SHA256 加密
  5. 转换为小写十六进制字符串

1. Java 验签示例

SignatureUtil.java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;

public class SignatureUtil {
    
    /**
     * 验证签名
     */
    public static boolean verifySignature(Map<String, String> params, String serverKey, String sign) {
        // 生成签名
        String calculatedSign = generateSignature(params, serverKey);
        // 比较签名(不区分大小写)
        return calculatedSign.equalsIgnoreCase(sign);
    }
    
    /**
     * 生成签名
     */
    public static String generateSignature(Map<String, String> params, String serverKey) {
        try {
            // 1. 参数按字母顺序排序(使用TreeMap自动排序)
            Map<String, String> sortedParams = new TreeMap<>(params);
            
            // 2. 拼接参数
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
                if (sb.length() > 0) {
                    sb.append("&");
                }
                sb.append(entry.getKey()).append("=").append(entry.getValue());
            }
            
            // 3. 追加ServerKey
            sb.append("&server_key=").append(serverKey);
            String stringToSign = sb.toString();
            
            // 4. HMAC-SHA256加密
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(
                serverKey.getBytes(StandardCharsets.UTF_8), 
                "HmacSHA256"
            );
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
            
            // 5. 转换为小写十六进制
            return bytesToHex(hash).toLowerCase();
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败", e);
        }
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }
}
回调验签使用示例
@PostMapping("/api/miluo/callback")
public String handlePaymentCallback(HttpServletRequest request) {
    // 1. 获取所有参数
    Map<String, String> params = new HashMap<>();
    Enumeration<String> parameterNames = request.getParameterNames();
    while (parameterNames.hasMoreElements()) {
        String name = parameterNames.nextElement();
        params.put(name, request.getParameter(name));
    }
    
    // 2. 获取签名
    String sign = params.get("sign");
    if (sign == null) {
        return "fail: signature missing";
    }
    
    // 3. 验证时间戳(防止重放攻击)
    long timestamp = Long.parseLong(params.get("timestamp"));
    long currentTime = System.currentTimeMillis() / 1000;
    if (Math.abs(currentTime - timestamp) > 300) { // 5分钟有效期
        return "fail: timestamp expired";
    }
    
    // 4. 验证签名
    String serverKey = "YOUR_SERVER_KEY";
    if (!SignatureUtil.verifySignature(params, serverKey, sign)) {
        return "fail: invalid signature";
    }
    
    // 5. 处理业务逻辑
    String orderId = params.get("order_id");
    String status = params.get("status");
    
    if ("success".equals(status)) {
        // 更新订单状态,发货等
        processOrderSuccess(orderId);
    }
    
    // 6. 返回成功响应
    return "success";
}

2. PHP 验签示例

SignatureUtil.php
<?php
class SignatureUtil {
    
    /**
     * 验证签名
     */
    public static function verifySignature($params, $serverKey, $sign) {
        $calculatedSign = self::generateSignature($params, $serverKey);
        return strcasecmp($calculatedSign, $sign) === 0;
    }
    
    /**
     * 生成签名
     */
    public static function generateSignature($params, $serverKey) {
        // 1. 参数按字母顺序排序
        ksort($params);
        
        // 2. 拼接参数
        $stringToSign = '';
        foreach ($params as $key => $value) {
            if ($stringToSign !== '') {
                $stringToSign .= '&';
            }
            $stringToSign .= $key . '=' . $value;
        }
        
        // 3. 追加ServerKey
        $stringToSign .= '&server_key=' . $serverKey;
        
        // 4. HMAC-SHA256加密
        $hash = hash_hmac('sha256', $stringToSign, $serverKey);
        
        // 5. 返回小写十六进制
        return strtolower($hash);
    }
}
?>
回调验签使用示例
<?php
require_once 'vendor/autoload.php';
use MiluoSDK\Util\SignatureUtil;

// 获取所有POST参数
$params = $_POST;

// 获取签名
$sign = $params['sign'] ?? '';
if (empty($sign)) {
    http_response_code(400);
    echo json_encode(['error' => 'signature missing']);
    exit;
}

// 验证时间戳
$timestamp = intval($params['timestamp'] ?? 0);
$currentTime = time();
if (abs($currentTime - $timestamp) > 300) {
    http_response_code(400);
    echo json_encode(['error' => 'timestamp expired']);
    exit;
}

// 验证签名
$serverKey = 'YOUR_SERVER_KEY';
if (!SignatureUtil::verifySignature($params, $serverKey, $sign)) {
    http_response_code(400);
    echo json_encode(['error' => 'invalid signature']);
    exit;
}

// 处理业务逻辑
$orderId = $params['order_id'];
$status = $params['status'];

if ($status === 'success') {
    // 更新订单状态
    processOrderSuccess($orderId);
}

// 返回成功
echo json_encode(['status' => 'success']);
?>

3. Python 验签示例

signature_util.py
import hmac
import hashlib
import time
from collections import OrderedDict

class SignatureUtil:
    
    @staticmethod
    def verify_signature(params, server_key, sign):
        """验证签名"""
        calculated_sign = SignatureUtil.generate_signature(params, server_key)
        return calculated_sign.lower() == sign.lower()
    
    @staticmethod
    def generate_signature(params, server_key):
        """生成签名"""
        # 1. 参数按字母顺序排序
        sorted_params = OrderedDict(sorted(params.items()))
        
        # 2. 拼接参数
        string_to_sign = '&'.join(
            f"{key}={value}" for key, value in sorted_params.items()
        )
        
        # 3. 追加ServerKey
        string_to_sign += f"&server_key={server_key}"
        
        # 4. HMAC-SHA256加密
        hmac_obj = hmac.new(
            server_key.encode('utf-8'),
            string_to_sign.encode('utf-8'),
            hashlib.sha256
        )
        
        # 5. 返回小写十六进制
        return hmac_obj.hexdigest().lower()
    
    @staticmethod
    def verify_timestamp(timestamp, max_age=300):
        """验证时间戳(防止重放攻击)"""
        current_time = int(time.time())
        return abs(current_time - timestamp) <= max_age
Flask回调示例
from flask import Flask, request, jsonify
from signature_util import SignatureUtil

app = Flask(__name__)

@app.route('/api/miluo/callback', methods=['POST'])
def handle_callback():
    # 获取所有参数
    params = request.form.to_dict()
    
    # 获取签名
    sign = params.get('sign')
    if not sign:
        return jsonify({'error': 'signature missing'}), 400
    
    # 验证时间戳
    timestamp = int(params.get('timestamp', 0))
    if not SignatureUtil.verify_timestamp(timestamp):
        return jsonify({'error': 'timestamp expired'}), 400
    
    # 验证签名
    server_key = 'YOUR_SERVER_KEY'
    if not SignatureUtil.verify_signature(params, server_key, sign):
        return jsonify({'error': 'invalid signature'}), 400
    
    # 处理业务逻辑
    order_id = params.get('order_id')
    status = params.get('status')
    
    if status == 'success':
        # 更新订单状态
        process_order_success(order_id)
    
    return jsonify({'status': 'success'})

if __name__ == '__main__':
    app.run(port=5000)

4. Node.js 验签示例

signature.js
const crypto = require('crypto');

class SignatureUtil {
    
    /**
     * 验证签名
     */
    static verifySignature(params, serverKey, sign) {
        const calculatedSign = this.generateSignature(params, serverKey);
        return calculatedSign.toLowerCase() === sign.toLowerCase();
    }
    
    /**
     * 生成签名
     */
    static generateSignature(params, serverKey) {
        // 1. 参数按字母顺序排序
        const sortedKeys = Object.keys(params).sort();
        
        // 2. 拼接参数
        const stringToSign = sortedKeys
            .map(key => `${key}=${params[key]}`)
            .join('&');
        
        // 3. 追加ServerKey
        const signString = `${stringToSign}&server_key=${serverKey}`;
        
        // 4. HMAC-SHA256加密
        const hmac = crypto.createHmac('sha256', serverKey);
        hmac.update(signString, 'utf8');
        
        // 5. 返回小写十六进制
        return hmac.digest('hex').toLowerCase();
    }
    
    /**
     * 验证时间戳
     */
    static verifyTimestamp(timestamp, maxAge = 300) {
        const currentTime = Math.floor(Date.now() / 1000);
        return Math.abs(currentTime - timestamp) <= maxAge;
    }
}

module.exports = SignatureUtil;
Express回调示例
const express = require('express');
const SignatureUtil = require('./signature');

const app = express();
app.use(express.urlencoded({ extended: true }));

app.post('/api/miluo/callback', (req, res) => {
    const params = req.body;
    
    // 获取签名
    const sign = params.sign;
    if (!sign) {
        return res.status(400).json({ error: 'signature missing' });
    }
    
    // 验证时间戳
    const timestamp = parseInt(params.timestamp || 0);
    if (!SignatureUtil.verifyTimestamp(timestamp)) {
        return res.status(400).json({ error: 'timestamp expired' });
    }
    
    // 验证签名
    const serverKey = 'YOUR_SERVER_KEY';
    if (!SignatureUtil.verifySignature(params, serverKey, sign)) {
        return res.status(400).json({ error: 'invalid signature' });
    }
    
    // 处理业务逻辑
    const orderId = params.order_id;
    const status = params.status;
    
    if (status === 'success') {
        // 更新订单状态
        processOrderSuccess(orderId);
    }
    
    res.json({ status: 'success' });
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

5. Go 验签示例

signature.go
package miluosdk

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math"
	"sort"
	"time"
)

type SignatureUtil struct{}

// VerifySignature 验证签名
func (s *SignatureUtil) VerifySignature(params map[string]string, serverKey, sign string) bool {
	calculatedSign := s.GenerateSignature(params, serverKey)
	return calculatedSign == sign
}

// GenerateSignature 生成签名
func (s *SignatureUtil) GenerateSignature(params map[string]string, serverKey string) string {
	// 1. 参数按字母顺序排序
	keys := make([]string, 0, len(params))
	for k := range params {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	
	// 2. 拼接参数
	var stringToSign string
	for i, key := range keys {
		if i > 0 {
			stringToSign += "&"
		}
		stringToSign += fmt.Sprintf("%s=%s", key, params[key])
	}
	
	// 3. 追加ServerKey
	stringToSign += fmt.Sprintf("&server_key=%s", serverKey)
	
	// 4. HMAC-SHA256加密
	mac := hmac.New(sha256.New, []byte(serverKey))
	mac.Write([]byte(stringToSign))
	
	// 5. 返回小写十六进制
	return hex.EncodeToString(mac.Sum(nil))
}

// VerifyTimestamp 验证时间戳
func (s *SignatureUtil) VerifyTimestamp(timestamp int64, maxAge int64) bool {
	currentTime := time.Now().Unix()
	return int64(math.Abs(float64(currentTime-timestamp))) <= maxAge
}
Gin回调示例
package main

import (
	"net/http"
	"miluosdk"
	"github.com/gin-gonic/gin"
)

var sigUtil = &miluosdk.SignatureUtil{}

func handleCallback(c *gin.Context) {
	// 获取所有参数
	params := make(map[string]string)
	for key, values := range c.Request.Form {
		if len(values) > 0 {
			params[key] = values[0]
		}
	}
	
	// 获取签名
	sign, exists := params["sign"]
	if !exists {
		c.JSON(http.StatusBadRequest, gin.H{"error": "signature missing"})
		return
	}
	
	// 验证时间戳
	timestamp := parseInt64(params["timestamp"])
	if !sigUtil.VerifyTimestamp(timestamp, 300) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "timestamp expired"})
		return
	}
	
	// 验证签名
	serverKey := "YOUR_SERVER_KEY"
	if !sigUtil.VerifySignature(params, serverKey, sign) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid signature"})
		return
	}
	
	// 处理业务逻辑
	orderId := params["order_id"]
	status := params["status"]
	
	if status == "success" {
		// 更新订单状态
		processOrderSuccess(orderId)
	}
	
	c.JSON(http.StatusOK, gin.H{"status": "success"})
}

func main() {
	r := gin.Default()
	r.POST("/api/miluo/callback", handleCallback)
	r.Run(":8080")
}

支付回调处理

回调参数说明

参数名 类型 必填 说明
order_id string 商户订单号
miluo_order_id string 米洛平台订单号
amount int 支付金额(单位:分)
status string 支付状态:success/failed
pay_channel string 支付渠道:wechat/alipay/unionpay
pay_time string 支付时间(YYYY-MM-DD HH:mm:ss)
timestamp long 请求时间戳(秒级)
sign string 签名值
extra string 扩展参数(JSON格式)

回调响应格式

您的服务器收到回调后,必须返回以下格式:

成功响应
{
    "status": "success"
}

如果处理失败,可以返回:

失败响应
{
    "status": "fail",
    "error": "错误描述"
}

重试机制

  • 如果未收到成功响应,米洛服务器将自动重试回调
  • 重试间隔:1分钟、5分钟、15分钟、30分钟、1小时
  • 最多重试5次
  • 请确保您的接口具有幂等性,避免重复处理

完整回调处理示例(Java)

PaymentCallbackController.java
@RestController
@RequestMapping("/api/miluo")
public class PaymentCallbackController {
    
    @Autowired
    private OrderService orderService;
    
    @Value("${miluo.server-key}")
    private String serverKey;
    
    @PostMapping("/callback")
    public String handleCallback(HttpServletRequest request) {
        try {
            // 1. 获取参数
            Map<String, String> params = getParams(request);
            
            // 2. 验证签名
            String sign = params.get("sign");
            if (sign == null || !SignatureUtil.verifySignature(params, serverKey, sign)) {
                log.error("签名验证失败");
                return buildResponse("fail", "invalid signature");
            }
            
            // 3. 验证时间戳
            long timestamp = Long.parseLong(params.get("timestamp"));
            if (!isTimestampValid(timestamp)) {
                log.error("时间戳过期");
                return buildResponse("fail", "timestamp expired");
            }
            
            // 4. 处理订单(保证幂等性)
            String orderId = params.get("order_id");
            String status = params.get("status");
            
            if ("success".equals(status)) {
                orderService.processPaymentSuccess(
                    orderId,
                    params.get("miluo_order_id"),
                    Integer.parseInt(params.get("amount")),
                    params.get("pay_channel"),
                    params.get("pay_time")
                );
            } else {
                orderService.processPaymentFailed(orderId);
            }
            
            // 5. 返回成功
            return buildResponse("success", null);
            
        } catch (Exception e) {
            log.error("处理回调异常", e);
            return buildResponse("fail", "internal error");
        }
    }
    
    private Map<String, String> getParams(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            params.put(name, request.getParameter(name));
        }
        return params;
    }
    
    private boolean isTimestampValid(long timestamp) {
        long currentTime = System.currentTimeMillis() / 1000;
        return Math.abs(currentTime - timestamp) <= 300; // 5分钟
    }
    
    private String buildResponse(String status, String error) {
        if ("success".equals(status)) {
            return "{\"status\":\"success\"}";
        }
        return "{\"status\":\"fail\",\"error\":\"" + error + "\"}";
    }
}

服务端API接口

1. 查询订单状态

接口信息
URL: https://api.miluosdk.com/v1/order/query
Method: POST
Content-Type: application/json

请求参数:

参数 类型 必填 说明
app_id string 应用ID
order_id string 商户订单号
timestamp long 当前时间戳
sign string 签名

响应示例:

{
    "code": 200,
    "message": "success",
    "data": {
        "order_id": "ORDER_20241215001",
        "miluo_order_id": "ML202412150001",
        "amount": 1000,
        "status": "paid",
        "pay_channel": "wechat",
        "pay_time": "2024-12-15 10:30:00"
    }
}

2. 申请退款

接口信息
URL: https://api.miluosdk.com/v1/order/refund
Method: POST
Content-Type: application/json

请求参数:

参数 类型 必填 说明
app_id string 应用ID
order_id string 原订单号
refund_amount int 退款金额(分)
reason string 退款原因
timestamp long 当前时间戳
sign string 签名

3. 查询用户信息

接口信息
URL: https://api.miluosdk.com/v1/user/info
Method: POST
Content-Type: application/json

常见问题 - 验签问题

验签失败怎么办?

验签失败通常由以下原因导致:

  1. ServerKey配置错误 - 检查服务器端配置的ServerKey是否与米洛后台一致
  2. 参数被篡改 - 确保回调参数完整未被修改
  3. 签名算法版本 - 确认使用最新版本的签名算法(HMAC-SHA256)
  4. 编码问题 - 确保所有参数使用UTF-8编码
  5. 参数排序 - 参数必须按字母顺序排序

建议:使用我们提供的SDK进行验签,避免手动实现出错。

回调地址如何配置?

在米洛开发者后台配置回调地址:

  1. 登录米洛开发者平台
  2. 进入应用管理 → 应用配置
  3. 设置"支付回调URL"
  4. 确保URL可公网访问且使用HTTPS

示例:https://your-server.com/api/miluo/callback

如何处理回调超时?

米洛服务器等待回调响应的时间为5秒。如果超时:

  • 系统会按照重试机制进行重试
  • 请优化您的业务逻辑,快速返回响应
  • 耗时的操作(如发送通知)建议异步处理
// 推荐做法:先返回成功,再异步处理
@PostMapping("/callback")
public String callback(HttpServletRequest request) {
    // 1. 快速验证签名
    if (!verifySign(request)) {
        return "fail";
    }
    
    // 2. 异步处理业务逻辑
    CompletableFuture.runAsync(() -> {
        processOrder(request);
    });
    
    // 3. 立即返回成功
    return "success";
}
如何保证回调的幂等性?

由于网络重试机制,同一订单可能收到多次回调。建议:

  1. 数据库唯一约束 - 订单号设置唯一索引
  2. 状态检查 - 处理前检查订单当前状态
  3. 分布式锁 - 高并发场景使用Redis锁
// Java示例:使用数据库事务保证幂等性
@Transactional
public void processPayment(String orderId) {
    Order order = orderMapper.selectById(orderId);
    
    // 检查订单状态
    if ("PAID".equals(order.getStatus())) {
        log.info("订单已处理:{}", orderId);
        return; // 已处理,直接返回
    }
    
    // 更新订单状态
    order.setStatus("PAID");
    orderMapper.updateById(order);
    
    // 其他业务处理...
}
签名时是否包含sign参数本身?

不包含。生成签名时,sign参数本身不参与签名计算。

验签步骤:

  1. 从请求参数中取出sign值
  2. 移除参数中的sign字段
  3. 对其余参数进行签名计算
  4. 将计算结果与sign值对比

常见问题 - 一般问题

米洛SDK支持哪些游戏引擎?

米洛SDK全面支持以下平台和引擎:

  • 原生开发 - Android (Java/Kotlin)、iOS (Swift/Objective-C)
  • 游戏引擎 - Unity、Cocos Creator、LayaAir
  • 鸿蒙系统 - HarmonyOS NEXT (ArkTS)
  • H5/页游 - JavaScript SDK
接入米洛SDK需要多长时间?

通常情况下,基础功能接入(登录+支付)仅需1-3天。具体时间取决于:

  • 游戏引擎类型(原生SDK最快,Unity次之)
  • 需要接入的功能模块数量
  • 是否有定制化需求

我们提供完整的Demo示例和一对一技术支持,确保快速顺利接入。

米洛SDK的收费模式是什么?

目前完全免费使用,无任何前期接入费用。我们致力于降低游戏开发者的接入门槛,助力游戏快速发行。

未来可能针对大型企业客户推出增值服务,但基础功能将永远保持免费。

米洛SDK支持海外发行吗?

完全支持。我们提供完整的出海发行方案:

  • 支持50+币种支付
  • 多语言本地化支持
  • 海外渠道对接(Google Play、App Store、Facebook等)
  • 各地区合规与审计支持

已帮助多款游戏成功覆盖15+国家和地区。

米洛SDK的系统稳定性如何?

米洛SDK采用云服务架构和分布式部署,提供:

  • 99.99% 系统可用性保障
  • 100+ 全球服务节点
  • 50ms 平均响应时间
  • 7×24小时 不间断运行监控
  • 1000万+ 日处理请求能力

常见问题 - 技术问题

如何处理SDK初始化失败?

初始化失败通常由以下原因导致:

  1. AppID/AppKey错误 - 请检查是否正确配置
  2. 网络问题 - 确保设备网络连接正常
  3. 权限缺失 - 检查AndroidManifest.xml是否添加必要权限
// 检查初始化状态
if (!MiluoSDK.isInitialized()) {
    Log.e("MiluoSDK", "SDK未初始化");
    // 重新初始化
}
登录回调没有响应怎么办?

请按以下步骤排查:

  1. 确保在主线程中调用登录接口
  2. 检查是否正确注册了回调函数
  3. 查看Logcat/Xcode控制台是否有错误日志
  4. 确认渠道配置是否正确
支付成功后如何发货?

推荐方案:服务器端回调

  1. 在创建支付订单时设置callbackUrl
  2. 支付成功后,米洛服务器会向您的服务器发送POST请求
  3. 您的服务器验证签名后,执行发货逻辑
  4. 返回成功响应

备用方案:客户端回调

在客户端onSuccess回调中发货,但需处理网络异常等边界情况。

SDK包体大小会影响游戏吗?

米洛SDK采用模块化设计,按需引入:

  • 核心SDK - 约1.5MB
  • 支付模块 - 约800KB
  • 数据统计模块 - 约500KB

您可以根据实际需求选择引入的模块,最小化包体影响。我们持续优化SDK体积,确保对游戏包体的影响降到最低。

常见问题 - 支付问题

支付失败如何处理?

支付失败常见原因及解决方案:

  • 网络超时 - 提示用户检查网络,稍后重试
  • 余额不足 - 提示用户充值或更换支付方式
  • 订单重复 - SDK已自动处理幂等性,无需额外操作
  • 渠道限制 - 某些渠道可能有支付限制,查看具体渠道文档
如何实现测试支付?

在开发阶段,您可以通过以下方式测试支付:

  1. 在初始化SDK时设置debug=true
  2. 使用测试账号进行测试
  3. 测试环境不会产生真实扣费
  4. 正式上线前务必切换到生产环境
支付回调验签失败怎么办?

验签失败通常由以下原因导致:

  1. AppKey配置错误 - 检查服务器端配置的AppKey是否正确
  2. 参数被篡改 - 确保回调参数完整未被修改
  3. 签名算法版本 - 确认使用最新版本的签名算法

请参考《服务端接入文档》中的验签示例代码。

支持哪些支付方式?

米洛SDK支持以下支付方式:

  • 国内支付 - 微信支付、支付宝、银联云闪付、QQ钱包
  • 海外支付 - PayPal、Stripe、Apple Pay、Google Pay
  • 运营商代扣 - 移动、联通、电信(部分地区)
  • 虚拟货币 - 各渠道钱包(如华为币、小米币等)

SDK会自动根据用户地区和渠道智能选择最优支付方式。

更新日志

v5.0.0 2024-12-15 最新
  • 新增 - HarmonyOS NEXT 原生支持
  • 优化 - 智能路由引擎升级,接入效率提升200%
  • 修复 - iOS 17兼容性问题
  • 改进 - SDK体积优化,减少30%包体大小
v4.5.0 2024-09-20
  • 新增 - 支持Unity 2023版本
  • 新增 - 自定义事件追踪功能
  • 优化 - 支付成功率提升至98%+
  • 修复 - Android 14权限问题
v4.0.0 2024-06-01
  • 新增 - AI驱动的运营决策支持
  • 新增 - 50+币种海外支付
  • 优化 - 数据上报性能提升

技术支持

遇到技术问题?我们的技术团队随时为您服务。

邮件支持

767146962@qq.com

工作日24小时内回复

QQ技术支持

767146962

工作日 9:00-18:00

电话咨询

18905733489

工作日 9:00-18:00

微信支持

18905733489

扫码添加客服微信

专属技术支持

对于已接入的游戏,我们提供一对一专属技术顾问,确保您在接入和运营过程中遇到的任何问题都能得到及时响应和解决。