# 1 请求结构

# 1.1 请求地址

  • 备注: 以下SDK请求地址都是正式环境,无测试环境,游戏测试时也使用SDK正式环境地址
区域 请求地址
加速 http://uglobal.ultrasdk.com/hu/v1/

# 1.2 请求方法

USDK服务端API支持POST请求方法

# 2 签名机制

# 2.1 密钥获取

请先从后台获取以下参数,用于签名使用:

  • productKey:SDK服务端为每个应用分配的私钥
  • productCode:SDK服务端为每个应用分配的项目id
  • callbackKey:SDK服务端为每个应用分配的同步的秘钥 支付专用

# 2.2 签名生成

  1. 签名参数说明
参数 含义
productKey SDK服务端为每个应用分配的私钥,后台获取
pcode SDK服务端为每个应用分配的项目id,后台获取
data 请求的数据内容,生成规则见下面签名示例中data的拼接
timestamp 当前 Unix 时间戳,单位为秒, 可见下面签名示例
  1. 签名算法 sign = md5(data={data}&pcode={pcode}&timestamp={timestamp}&productKey) 注意这里的参数顺序按上行算法固定,最后的productKey只连接值本身,不需要'productKey='

  2. data拼接

  • 1)请求参数按字母顺序参与拼接,其中productKey和timestamp不参与,参考示例markData(Key1,Val1,Key2,Val2,Key3,Val3....),
  • 2)拼接后转为json串,并进行Base64编码得到临时密串
  • 3)对临时密串进行对称换位,得到最终data (具体换的位置参考示例markDataFlag)

# 2.3 签名示例

  1. Java 签名示例代码 更多语言代码示例

    private static final String K_SIGN = "sign";
    
    /** 计算sign */
    private static String markSign(String appKey, String... key_val)
    {
    	HashMap<String, String> map = new HashMap<String, String>();
    	for (int i = 1; i < key_val.length; i += 2)
    		if (key_val[i] != null && key_val[i - 1] != null)
    			map.put(key_val[i - 1], key_val[i]);
    	return markSignFlag(appKey, map);
    }
    
    /** 具体执行计算sign */
    private static String markSignFlag(String appKey, Map<String, String> params)
    {
    	ArrayList<String> keys = new ArrayList<String>(params.keySet());
    	keys.remove(K_SIGN);
    	Collections.sort(keys);
    	StringBuilder builder = new StringBuilder();
    
    	for (int i = 0; i < keys.size(); i++)
    	{
    		final String key = keys.get(i);
    		final String value = params.get(key);
    		if (key != null && key.length() > 0)
    		{
    			builder.append(key).append("=").append(value).append('&');
    		}
    	}
    	builder.append(appKey);
    	String srcData = builder.toString();
    	return SignUtil.encrypt(SignUtil.MD5, srcData);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
  2. Java data拼接示例代码 更多语言代码示例

    private static final String CHAR_CODE = "UTF-8";
    
    /** 计算Data */
    private static String markData(Object... key_val) throws Exception
    {
    
    	HashMap<String, Object> map = new HashMap<String, Object>();
    	for (int i = 1; i < key_val.length; i += 2)
    		if (key_val[i] != null && key_val[i - 1] != null)
    			map.put(key_val[i - 1] + "", key_val[i]);
    	return markDataFlag(map);
    }
    
    /** 具体执行计算Data */
    private static String markDataFlag(Map<String, Object> params) throws Exception
    {
    	JSONObject nameValuePairs = new JSONObject();
    
    	for (Map.Entry<String, Object> entry : params.entrySet())
    	{
    		String key = entry.getKey();
    		if (key == null)
    		{
    			throw new NullPointerException("key == null");
    		}
    		nameValuePairs.put(key, entry.getValue());
    	}
    	//将数组转化为 json 字符串
    	String jsonStr = nameValuePairs.toString();
    
    	// 对 jsonStrbase64 进行  编码
    	String tmpData = Base64.encodeToString(jsonStr.getBytes(CHAR_CODE), Base64.DEFAULT);
    	Logger.i("markDataFlag and json to base64 is" + tmpData);
    
    	// 将 tmpData 进行对称换位 ,  得到结果就是 data 密文数据
    	String finalData;
    	if (tmpData.length() > 51)
    	{
    		char[] chars = changeArray(tmpData.toCharArray(), 1, 33, 10, 42, 18, 50, 19, 51);
    		finalData = new String(chars);
    	}
    	else
    	{
    		finalData = tmpData;
    	}
    	return finalData;
    }
    
    /** 换位 */
    public static char[] changeArray(char[] chars, int... index) {
    	for (int i = 1; i < index.length; i += 2) {
    		final int l = index[i - 1];
    		final int r = index[i];
    		char c = chars[l];
    		chars[l] = chars[r];
    		chars[r] = c;
    	}
    	return chars;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
  3. java签名工具类SignUtil

    SignUtil.java

# 2.4 签名失败

返回码为-1表示签名失败

# 3 支付通知解密算法

# 3.1 基本规则

  1. markSign(callbackKey, Key1,Val1) 生成签名
    • callbackKey对应callbackKey: SDK服务端为每个应用分配的支付回调秘钥
    • 主要签名字段包括 data
  2. 生成后的签名与回调里的参数sign 进行比较
  3. 签名验证成功后, 将data参数用base64解密,即可得到支付结果数据
  4. 具体可参考示例中的回调部分 示例参考

# 3.2 解密示例

  • callbackkey:SDK服务端为游戏的同步的秘钥,从usdk后台获取

  • 签名规则见上文

  • java代码示例 更多语言代码示例

    String dataStr = ""; // 获取的data参数
    String dataSign = SignUtils.markSign(callbackkey, "data", dataStr);
    String signStr = getPara("sign");
    if (StrKit.equals(dataSign, signStr))
    {
    	renderText("FAIL sign fail");
    	return;
    }
    String data = new String(Base64.decodeBase64(dataStr.getBytes()));
    JSONObject jsonObject = new JSONObject(data);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 3.3 解密后数据示例

  • data的值:

    {
    	"amount": 6,
    	"gameOrder": "cpOrderId_1505271109529",
    	"orderNo": "HUA10000000277",
    	"selfDefine": "透传参数",
    	"status": 0, // 0代表成功,不为0代表失败
    	"channelUid": "c4ca4238a0b923820dcc509a6f75849b",
    	"payTime": 1505271109000,
    	"channel": "sample" 
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
本文档对解决你的问题有所帮助?