视频一区二区三区自拍_千金肉奴隷1985未删减版在线观看_国产成人黄色视频在线播放_少女免费播放片高清在线观看_国产精品v欧美精品v


簽名相關(guān)


如何在程序中加載私鑰

推薦使用微信支付提供的SDK。你也可以查看下列編程語言的示例代碼。

  /**
  * 獲取私鑰。
  *
  * @param filename 私鑰文件路徑  (required)
  * @return 私鑰對象
  */
public static PrivateKey getPrivateKey(String filename) throws IOException {

  String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
  try {
    String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
        .replace("-----END PRIVATE KEY-----", "")
        .replaceAll("\\s+", "");

    KeyFactory kf = KeyFactory.getInstance("RSA");
    return kf.generatePrivate(
        new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
  } catch (NoSuchAlgorithmException e) {
    throw new RuntimeException("當(dāng)前Java環(huán)境不支持RSA", e);
  } catch (InvalidKeySpecException e) {
    throw new RuntimeException("無效的密鑰格式");
  }
}
    /**
* Read private key from file
*
* @param string    $filepath     PEM encoded private key file path
* 
* @return resource|bool     Private key resource identifier on success, or FALSE on error
*/
public static function getPrivateKey($filepath) {
    return openssl_get_privatekey(file_get_contents($filepath));
}
protected string sign(string message)
{
    // 需去除私鑰文件中的-----BEGIN/END PRIVATE KEY-----
    string privateKey = "MIIEvgIBADANBgkqhkiG...30HBe+GD1tntZgf6I1Y0ZpHZ";
    byte[] keyData = Convert.FromBase64String(privateKey);
    using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
    using (RSACng rsa = new RSACng(cngKey))
    {
        byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
        return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
    }
}
package main
import (
  "crypto/x509"
  "encoding/pem"
  "fmt"
  "log"
)

func main() {
  var pemData = []byte(`
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1yhh6LNB8nXmO
SxdGKWmDh0OxAM/wnGyHKSD9tcEhMQTe+wabce0POXzejCmwFBzZa7ZmxH5LoAey
T7Fpwb7pptbbDx58CxCYhNEdQ2XrFILUCq3daMj++KQlyDp8U0NspFKsO57gSlih
AJ49DzcXQb7Vs5daIvtLapIouPyixAE5uDL+afmJ+bXC11xP5sPWw1RfXynW3vbE
yfRol9hQyQWfmO15GSZi6TTAhTKaW31yKaQNChy06K+LsE9JAU+ESxihthtGiMbY
3fFRyhF9Ka2e0wIOz6UdcfwMjxXWRV4OLD1uFG9IYbUiugmYtDyIYZaFDPYdi/+R
jm10Ps5lAgMBAAECggEAb19kRZ2lEWOM8D9S//opGZrKPuvneVrsJpZtDuLGcqZM
fKvALYXLnZMzzEiE1cpMrmuOMUHaukxNytGGOOupIg7D/SszGv3QahCc6Ne83hwP
1wa/5DDpS0RblIYqRrbgTPQTbk+Mk48Y43K0f2YN82KlHtnLNT7PRDIDX42Nwc1X
8f4JcfyKUE/pOSn+YUlu5Edu6QYbWJWS7mlojEZ/wuWbSymbs6mVVkKeSWGTIh1v
4n2F3Gj6ckUDlt4aZWTVcBa2+ZvSE2h5frSH0snpdGV1bW44IqE3NkwfTQ7JI34C
VJdhb3goIyoTmiz6NGEZuiyr8gP9IOjqPfeP7GO5YQKBgQDuB1CT8ksO4SqR3skR
kdCQW7kOogZgDThei+3HUMOsHr8L42oYkJDmk2res1ow/mz6SoIV4w6mvvUSnACx
dtYA1AzUEs3jvltv8cQ1HAuDhLRslWrhSoxrQQh20yrVxxGN0J4DdCAGURSUwypz
UHR+mlfcjacPyxKUsT41+8zG+QKBgQDDg8ZGivuV794RuA3cfpitUFG+0nA0ZS3q
AZqlA3ufnCudHQixFIsf83Q7sX7pBob5PNONqsbv0OKpC3/xJRSPIwjWTBUPlDLX
rsGajKMhUPtkWo4zkfrSa8XaUpUVDU0qTzS71f9Aab3SkPH1d1o4cQxO08axGLbm
TV/46QCBzQKBgDd7ZQDXPT+epHmT4HJD9sVvW9dZVPsWmckP/MC0xqdcE1QGEjjf
mablPcfjLma1J1m//Ep1vniHkkBgNJkpBgDzbHoSWAN5335ccEug2d4yFIwq19rj
sY9efUaVOirSV/kiY3KSotRWGeIDC+YNHtpTx58VNZes0gvutH2Iz9ahAoGAUcoW
b/xEMv0dURxF8C+lfxtSlxlBhymsg3AYWV+Tn7mdJSS4Nhv592vI/A/Mn37zh+BC
P8lpX3lq2HzPEPoKF7b4Q22ggdvlSQT6SMT8mTtfbyPSyRAQdWZQZnyVkTD3TvPD
g7CKD1As8KFiFuXPAD2KgI9nVz6XhNBpjZ8rbyECgYEAsOrm1hbNZbvlNhnuUjw5
DTgTuJ3B0j1aK/7C2EQWR+mIG2q5TKDC6xNdszV0gK1/TbJk4RNgQo0JLkuZ2Xk2
Q8KhaNe+X8SYP9CFKIsXuhGrYI5ICjipov5oJqjESV4wle575eWwdPgF1ICabpIq
dnX2MxS9tkk830uXxPrXpRA=
-----END PRIVATE KEY-----`)

  block, rest := pem.Decode(pemData)
  if block == nil || block.Type != "PRIVATE KEY" {
    log.Fatal("failed to decode PEM block containing public key")
  }

  pri, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  if err != nil {
    log.Fatal(err)
  }

  fmt.Printf("Got a %T, with remaining data: %q", pri, rest)
}

為什么請求返回401 Unauthorized?

請根據(jù)報(bào)文中的message信息,在下表中找到錯(cuò)誤的原因和對應(yīng)的解決方案。

錯(cuò)誤描述 原因 解決方案
商戶未設(shè)置APIv3密鑰。 商戶未設(shè)置APIv3密鑰 請登錄商戶平臺設(shè)置APIv3密鑰
商戶未申請過證書。 商戶未申請過API證書 請參考什么是API證書?如何獲取API證書?
商戶證書序列號有誤。 使用了錯(cuò)誤的商戶證書,或者使用了已經(jīng)失效的歷史的商戶證書,或者獲取的商戶證書序列號有誤 請檢查商戶證書,可登錄商戶平臺查看正確的證書序列號。
商戶證書已過期。 使用了已經(jīng)過期的商戶證書和私鑰 請到商戶平臺進(jìn)行續(xù)期,使用續(xù)期后的新證書
商戶證書已作廢。 使用了商戶主動作廢的商戶證書和私鑰 請到商戶平臺重新申請證書后,使用新申請的證書
錯(cuò)誤的簽名,導(dǎo)致驗(yàn)簽失敗。 使用了錯(cuò)誤的商戶私鑰,或簽名串構(gòu)造不正確 請見下一問題
Http頭Authorization值格式錯(cuò)誤 缺少 Authorization頭,或其格式不正確 請檢查上送的 Authorization
Http頭Authorization認(rèn)證類型不正確 不支持 Authorization中聲明的簽名算法 請檢查上送的 Authorization,目前僅支持WECHATPAY2-SHA256-RSA2048
Http頭Authorization中的timestamp與發(fā)起請求的時(shí)間不得超過5分鐘 Authorization頭中的時(shí)間戳timestamp所示時(shí)間距離當(dāng)前時(shí)間超過5分鐘 請檢查系統(tǒng)時(shí)間是否準(zhǔn)確,或者獲取時(shí)間的邏輯是否正確
已更換證書,請使用新證書 商戶主動重新申請了商戶API證書 請使用新申請的商戶API證書

如何定位“錯(cuò)誤的簽名,導(dǎo)致驗(yàn)簽失敗”的錯(cuò)誤?

為了方便開發(fā)者定位,我們對于驗(yàn)簽失敗,會在應(yīng)答的錯(cuò)誤詳情detail中加入驗(yàn)簽信息。驗(yàn)簽信息是我們根據(jù)商戶的HTTP請求構(gòu)造簽名串的各種信息。

  • method,HTTP請求方法
  • url,請求的URL
  • truncated_sign_message,微信支付驗(yàn)簽時(shí)使用的簽名串(換行符顯示成\n)。為了方便查看,我們對最后的請求報(bào)文主體做了截?cái)?/li>
  • sign_message_length,微信支付驗(yàn)簽時(shí)使用的簽名串的字節(jié)長度
{
"code": "SIGN_ERROR",
"message": "錯(cuò)誤的簽名,驗(yàn)簽失敗",
"detail": {
    "field": "signature",
    "issue": "sign not match",
    "location": "authorization",
    "sign_information": {
        "method": "GET",
        "url": "/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ",
        "truncated_sign_message": "GET\n/payscore/user-service-state?service_id=500001&appid=wxeaf7bf1de621b0c2&openid=oWm9Z5JQwgV7BKAQUeKsUMVSjTpQ\n1559194069\n18a427e78d2344e1a71156a2690cc4d6\n\n",
        "sign_message_length": 157
    }
}
}

建議開發(fā)者在程序中將自己組裝的簽名串以及簽名串的字節(jié)長度在調(diào)試信息中輸出,跟微信支付返回的驗(yàn)簽信息進(jìn)行仔細(xì)對比,排查以下幾種常見的錯(cuò)誤:

簽名串的最后一行沒有附加換行符

如果請求報(bào)文主體為空(如GET請求),最后一行應(yīng)為一個(gè)換行符。

簽名串中的參數(shù),跟實(shí)際請求的參數(shù)不一致
  • 手工拼接的URL,和實(shí)際請求發(fā)送的不一致。我們建議的實(shí)現(xiàn)是,使用HTTP庫構(gòu)造請求對象或者URL對象,再使用相應(yīng)的方法取得URL。
  • 簽名和設(shè)置Authorization頭時(shí),使用了前后生成的兩個(gè)時(shí)間戳
  • 簽名和設(shè)置Authorization頭時(shí),使用了前后生成的兩個(gè)不同的隨機(jī)串。
  • 簽名和請求時(shí),使用了前后兩次序列化的JSON串作為請求主體。
商戶的開發(fā)者可以將關(guān)鍵參數(shù)生成并保存在變量中,簽名和發(fā)送請求時(shí)統(tǒng)一使用,避免前后生成的信息不一致。
文本的編碼不一致

生成簽名串使用了非UTF-8編碼或者未設(shè)置具體編碼。

構(gòu)建簽名串順序不對

構(gòu)建簽名串沒有按照文檔要求的順序進(jìn)行構(gòu)建。

使用了錯(cuò)誤的商戶私鑰

開發(fā)者可以使用如下的openssl命令檢查私鑰和商戶證書中的modulus(p、q兩個(gè)大素?cái)?shù)的乘積)是否一致。如果兩者一致,那么私鑰和證書是成對的。

$ openssl x509 -noout -modulus -in 1900009191_20180326_cert.pem
Modulus=C6D43C87B991...
$ openssl rsa -noout -modulus -in 1900009191_20180326_key.pem
Modulus=C6D43C87B991...
1.modulus長度為2048位,輸出為512個(gè)字節(jié)。
2.檢查密鑰匹配前,請先查看證書序列號,檢查是否是正確的商戶證書。

為什么微信支付的回調(diào)缺少簽名的幾個(gè)HTTP頭?

微信支付的回調(diào),在HTTP頭部包含了以下四個(gè)HTTP頭:

  • Wechatpay-Timestamp
  • Wechatpay-Nonce
  • Wechatpay-Signature
  • Wechatpay-Serial

某些代理服務(wù)器或CDN服務(wù)提供商,轉(zhuǎn)發(fā)時(shí)會“過濾”微信支付擴(kuò)展的HTTP頭,會導(dǎo)致驗(yàn)簽的應(yīng)用層無法取到微信支付的簽名信息。遇到這種情況時(shí),建議商戶調(diào)整代理服務(wù)器配置,或者通過直連的方式接受微信支付的回調(diào)。



技術(shù)咨詢

文檔反饋