微信支付 APP集成SDK 签名(sign)生成小结

仔细阅读:

(1)https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml

(2)https://developers.weixin.qq.com/doc/oplatform/Downloads/Android_Resource.html

准备工作

"com.tencent.mm.opensdk:wechat-sdk-android:6.8.0"
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
<!-- for mta statistics -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

app注册到微信

    fun Application.initWechatPayRegister(
    ) {
        val api = WXAPIFactory.createWXAPI(appContext, null)
        // 将该app注册到微信
        api.registerApp(appId)
    }

必要方法

  1. 生成-随机字符串

private fun createNonceStr(): String {
        val s = UUID.randomUUID().toString()
        // 去掉“-”符号
        return s.replace("\\-".toRegex(), "").uppercase(Locale.getDefault())
}
  1. 生成-时间戳

  fun getTimeStampSecond(): String {
        val totalMilliSeconds = System.currentTimeMillis()
        //求出现在的秒
        return (totalMilliSeconds / 1000).toString()
  }
  1. 生成-签名

   fun sign(privateKey: PrivateKey, input: String): String {
        //获取数字签名实例对象
        val signature = Signature.getInstance("SHA256withRSA")
        //初始化签名
        signature.initSign(privateKey)
        //设置数据源
        signature.update(input.toByteArray(Charsets.UTF_8))
        //签名
        val sign = signature.sign()
        return Base64.getEncoder().encodeToString(sign)
    }
public static String sign(String content, PrivateKey privateKey) throws Exception {
    Signature signature = Signature.getInstance("SHA256withRSA");
    signature.initSign(privateKey);
    signature.update(content.getBytes(Charsets.UTF_8));
    byte[] signed = signature.sign();
    return Base64.encode(signed);
}

注意defaultConfig{minminSdk 26}

  1. 签名私钥字符串 to PrivateKey

  /**
     * 解码PrivateKey
     * @param key
     * @return
     */
    private fun getPrivateKey(key: String): PrivateKey? {
        try {
            val byteKey = Base64.getDecoder().decode(key)
            val x509EncodedKeySpec = PKCS8EncodedKeySpec(byteKey)
            val keyFactory: KeyFactory = KeyFactory.getInstance("RSA")
            return keyFactory.generatePrivate(x509EncodedKeySpec)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }
/**
     * 解码PrivateKey
     * @param key
     * @return
     */
    private fun getPrivateKey( String privateKeyStr): PrivateKey? {
        try {
            byte[] keyBytes = Base64.decode(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

具体实现

/**
     * 调起微信支付
     * @param prepayId 预支付交易会话ID
     */
    fun reqVxPay(prepayId: String) {
        val request = PayReq()
        request.appId = appId //appId
        request.partnerId = merchantId//商户号
        request.prepayId = prepayId//预支付交易会话ID
        request.nonceStr = createNonceStr()//随机字符串
        request.packageValue = "Sign=WXPay"//固定内容
        request.timeStamp = getTimeStampSecond()//时间戳 秒

        val value = "${appId}\n${request.timeStamp}\n${request.nonceStr}\n${request.prepayId}\n"
        val singleAcct = sign(getPrivateKey(privateKeyValue)!!, value)

        request.sign = singleAcct

        api.sendReq(request)
    }

私钥字符串是根据“apiclient_key.pem”解码获得,几百字节长度

不建议将签名方法在app端实现,因为不安全,被反编译很容易暴露

校验签名

echo -n -e \
"wx8888888888888888\n1414561699\n5K8264ILTKCH16CQ2502SI8ZNMTM67VS\nWX1217752501201407033233368018\n" \
  | openssl dgst -sha256 -sign apiclient_key.pem \
  | openssl base64 -A

猜你喜欢

转载自blog.csdn.net/m0_63587743/article/details/129201947