Home > Net >  { "status": "FAIL", "code": "400002", "errorMessage&quo
{ "status": "FAIL", "code": "400002", "errorMessage&quo

Time:02-03

Im trying to get "create order" api from binance pay api to make payments in my kotlin android application. I am following api documentation to build the payload and signature but unfortunately its not working. Im getting this error : "errorMessage": "Signature for this request is not valid."

Anyone can help?

 private fun createSignature(payload: String, secretKey: String): String {
        val sha512HMAC = Mac.getInstance("HmacSHA512")
        val secretKeySpec =
            SecretKeySpec(secretKey.toByteArray(), "HmacSHA512")  // bokra jarrib HMAC-SHA512
        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) {
                }
            })

        }
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>
}

CodePudding user response:

I guess the problem is in the signature as per the documentation you need to do this

String signature = hex(hmac("sha512", payload, secretKey)).toUpperCase()

So, to do this in kotlin you can do it as follows

fun hmac(algorithm: String, data: String, secretKey: String): ByteArray {
    val secret = SecretKeySpec(secretKey.toByteArray(), algorithm)
    val mac = Mac.getInstance(algorithm)
    mac.init(secret)
    return mac.doFinal(data.toByteArray())
}

Then you need to convert it to hex so you can create this method (I see that you are using this .toHex() but I don't know your implementation)

fun hex(bytes: ByteArray): String {
    val hexChars = "0123456789ABCDEF".toCharArray()
    val result = StringBuilder(bytes.size * 2)
    for (b in bytes) {
        result.append(hexChars[b.toInt().shr(4) and 0x0f])
        result.append(hexChars[b.toInt() and 0x0f])
    }
    return result.toString()
}

Then the only thing you need to do is wrap it up, you can do it as follows :

val signature = hex(hmac("SHA-512", payload, secretKey)).toUpperCase()

I'm wondering if the problem you are having is that you are using HmacSHA512 instead of SHA-512.

CodePudding user response:

I'm reading documentation you posted, and I read this example: (https://developers.binance.com/docs/binance-pay/app-integration)

String payload = "certSn=317c110ebf7baf641e8f49ab6851331737dbe98541947c53b9dbba27f8c8414f" "&" "merchantId=98765987" "&" "noncestr=5K8264ILTKCH16CQ2502SI8ZNMTM67VS" "&" "prepayId=98765987" "&" "timeStamp=1618302830073";String signature = hex(hmac("sha512", payload, secretKey)).toUpperCase();

And in your createSignature method I don't see this logic.

  • Related