Binance Pay创建订单API签名无效问题求助(Kotlin Android)
Binance Pay创建订单API签名无效(错误码400002)排查
我在Kotlin Android应用中调用Binance Pay创建订单API实现支付功能,严格遵循官方API协议规则构建请求载荷与签名,但始终请求失败,收到错误响应:
{"status": "FAIL", "code": "400002", "errorMessage": "Signature for this request is not valid."}
相关代码
签名生成函数
private fun createSignature(payload: String, secretKey: String): String { val sha512HMAC = Mac.getInstance("HmacSHA512") val secretKeySpec = SecretKeySpec(secretKey.toByteArray(), "HmacSHA512") sha512HMAC.init(secretKeySpec) val digest = sha512HMAC.doFinal(payload.toByteArray()) return digest.toHex() }
请求构建逻辑
val timestamp = System.currentTimeMillis() + clockOffset val nonceStr = generateNonce() val body = Gson().toJson( OrderRequest( Env("APP"), merchantTradeNb, 0.02, "USDT", Goods("01", "D000", "7876763A3C", "phone", "Good new phone") ) ) val payload = timestamp.toString() + "\n" + nonceStr + "\n" + body + "\n" val signature: String = createSignature( payload.toByteArray(Charsets.UTF_8).toString(), secretKey ).uppercase() val retrofitData = retrofitBuilder.binanceApi.createOrder( "application/json", timestamp, nonceStr, certSn, signature, body ) retrofitData.enqueue(object : Callback<OrderResponse> { override fun onResponse( call: Call<OrderResponse>, response: Response<OrderResponse>, ) { response.body() } override fun onFailure(call: Call<OrderResponse>, t: Throwable) { } })
Retrofit接口定义
interface BinancePayApi { @POST("/binancepay/openapi/v2/order") fun createOrder( @Header("Content-type") contentType: String, @Header("BinancePay-Timestamp") timestamp: Long, @Header("BinancePay-Nonce") nonce: String, @Header("BinancePay-Certificate-SN") apiKey: String, @Header("BinancePay-Signature") signature: String, @Body request: String ): Call<OrderResponse> }
问题排查关键点
- 载荷编码错误:调用
createSignature时,将payload转成UTF-8字节数组后又调用toString(),会导致字节被错误解码(默认用平台编码而非UTF-8),直接破坏签名原始数据。应直接传入原始payload字符串,或在签名函数中统一用UTF-8编码处理。 - 签名载荷格式:Binance要求载荷格式为
timestamp\nnonce\nbody\n,必须确保换行符是\n(Unix格式),且末尾保留一个空行,不能多也不能少。 - JSON序列化一致性:Gson默认序列化的字段顺序可能和服务器预期不符,需确保
body的JSON输出和官方示例完全一致(包括字段顺序、空格、数值格式),建议显式指定字段顺序或使用官方推荐的序列化方式。 - 时间戳准确性:
clockOffset必须准确,若本地时间与Binance服务器时间差超过5分钟,签名会直接失效,建议调用Binance的时间同步接口校准时间。 - 密钥配对检查:确认
certSn是正确的API Key,secretKey是对应的密钥,二者必须严格配对,不能混淆。 - 签名函数编码统一:签名函数中,
secretKey和payload都应该用UTF-8编码转字节数组,避免因编码不一致导致签名错误。
修正后的核心代码示例
修正的签名函数
private fun createSignature(payload: String, secretKey: String): String { val sha512HMAC = Mac.getInstance("HmacSHA512") // 统一用UTF-8编码处理密钥和载荷 val secretKeySpec = SecretKeySpec(secretKey.toByteArray(Charsets.UTF_8), "HmacSHA512") sha512HMAC.init(secretKeySpec) val digest = sha512HMAC.doFinal(payload.toByteArray(Charsets.UTF_8)) return digest.toHex().uppercase() }
修正的载荷调用
val payload = "$timestamp\n$nonceStr\n$body\n" // 直接传入payload字符串,无需转字节再转字符串 val signature = createSignature(payload, secretKey)
内容的提问来源于stack exchange,提问作者Shadi Amine
相关产品推荐
相关产品推荐

