仔细阅读:
(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)
}
必要方法
生成-随机字符串
private fun createNonceStr(): String {
val s = UUID.randomUUID().toString()
// 去掉“-”符号
return s.replace("\\-".toRegex(), "").uppercase(Locale.getDefault())
}
生成-时间戳
fun getTimeStampSecond(): String {
val totalMilliSeconds = System.currentTimeMillis()
//求出现在的秒
return (totalMilliSeconds / 1000).toString()
}
生成-签名
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}
签名私钥字符串 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
