C# 对微信请求Encode编码

本文介绍了一种使用C#实现的URL编码方法,通过UTF-8编码将字符串转换为适用于URL的格式。文章详细展示了如何遍历字节并将其转换为十六进制表示,最后拼接成完整的编码字符串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        public static string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //默认是System.Text.Encoding.Default.GetBytes(str)
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }

            return (sb.ToString());
        }

 

<think>首先,用户的问题是基于之前的引用内容。引用[1]讨论了微信步数的解密,引用[2]提到了获取手机号的后端PHP代码,引用[3]和[4]是关于其他语言的解密示例。用户现在明确要求:"我想获取与给定前端函数对应的后端PHP解密代码",具体是"微信小程序获取手机号码后端PHP解密代码示例"。 用户提供了前端代码片段,在引用[2]中: ```javascript getPhoneNumber: function (e) { console.log(e) if (e.detail.errMsg == 'getPhoneNumber:fail') { console.log(ErrMsg); that.showToast_fail('未获取到手机号码'); return false; } else if (e.detail.iv == undefined || !e.detail.iv) { that.showToast_fail('授权失败'); return false; } else { // 解密手机号接口 var url = "/getTelNumber.php"; var params = { session_key: wx.getStorageSync('session_key'), encryptedData: e.detail.encryptedData, iv: e.detail.iv }; util.request(url, 'post', params, '', (res) => { that.setData({ phone: res.data.phoneNumber, }) wx.reLaunch({ url: '../index/index', }) }, function () { that.showToast_fail('获取手机号失败'); }) } } ``` 前端函数发送一个POST请求到`/getTelNumber.php`,参数包括`session_key`、`encryptedData`和`iv`。后端PHP需要解密`encryptedData`来获取手机号码。 根据微信官方文档,解密算法是AES-128-CBC解密,使用`session_key`作为密钥,`iv`作为初始化向量。解密后得到一个JSON对象,其中包含`phoneNumber`字段。 引用[1]中提到微信提供了示例代码,包括PHP版本。我需要参考那个来构建解密代码。 官方文档链接:https://developers.weixin.qq.com/miniprogram/dev/guide/open-ability/signature.html#%E5%8A%A0%E5%AF%86%E6%95%B0%E6%8D%AE%E8%A7%A3%E5%AF%86%E7%AE%97%E6%B3%95 示例代码下载:https://res.wx.qq.com/wxdoc/dist/assets/media/aes-sample.eae1f364.zip 解压后,PHP文件是`wxBizDataCrypt.php`。 在引用[2]中,后端接口是`getTelNumber.php`,所以我需要提供一个类似的文件。 关键点: - 接收POST参数:`session_key`、`encryptedData`、`iv` - 使用AES解密 - 返回解密后的手机号 解密步骤: 1. Base64解码`session_key`、`encryptedData`和`iv`。 2. 使用AES-128-CBC解密。 3. 解密后的数据是JSON字符串,解析后提取`phoneNumber`。 在PHP中,可以使用`openssl_decrypt`函数。 示例代码从官方下载: - `wxBizDataCrypt.php` 包含一个类 `WXBizDataCrypt`。 - 它有一个方法 `decryptData`。 为了简化,我可以直接提供一个简单的PHP脚本。 结构: - 后端PHP文件:`getTelNumber.php` - 接收POST数据 - 解密 - 返回JSON响应 错误处理: - 如果解密失败,返回错误信息。 在引用[3]中,有Python示例,但用户需要PHP。 引用[4]提到C#,但不相关。 所以,我需要生成一个PHP解密代码示例。 确保代码安全: - 验证输入。 - 使用正确的AES模式。 PHP代码示例: ```php <?php // getTelNumber.php // 获取POST参数 $sessionKey = $_POST['session_key']; $encryptedData = $_POST['encryptedData']; $iv = $_POST['iv']; // 验证参数 if (empty($sessionKey) || empty($encryptedData) || empty($iv)) { echo json_encode(['error' => 'Missing parameters']); exit; } // Base64解码 $sessionKey = base64_decode($sessionKey); $encryptedData = base64_decode($encryptedData); $iv = base64_decode($iv); // 解密 $decrypted = openssl_decrypt($encryptedData, 'AES-128-CBC', $sessionKey, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { echo json_encode(['error' => 'Decryption failed']); exit; } // 解析JSON $data = json_decode($decrypted, true); if (json_last_error() !== JSON_ERROR_NONE || !isset($data['phoneNumber'])) { echo json_encode(['error' => 'Invalid decrypted data']); exit; } // 返回手机号 echo json_encode(['phoneNumber' => $data['phoneNumber']]); ?> ``` 但官方示例使用了更严格的检查,比如数据长度和PKCS7填充。 参考官方`wxBizDataCrypt.php`: - 它处理了错误和异常。 - 使用PKCS7填充。 在官方代码中,`decryptData`方法包括: - 检查数据长度。 - 使用mcrypt或openssl。 - 去除PKCS7填充。 由于PHP 7+,openssl是标准。 改进版本: ```php <?php // getTelNumber.php // 获取POST参数 $sessionKey = $_POST['session_key'] ?? ''; $encryptedData = $_POST['encryptedData'] ?? ''; $iv = $_POST['iv'] ?? ''; if (empty($sessionKey) || empty($encryptedData) || empty($iv)) { header('Content-Type: application/json'); echo json_encode(['error' => 'Missing parameters']); exit; } // Base64解码 $sessionKey = base64_decode($sessionKey); $encryptedData = base64_decode($encryptedData); $iv = base64_decode($iv); // 使用AES-128-CBC解密 $decrypted = openssl_decrypt($encryptedData, 'AES-128-CBC', $sessionKey, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { header('Content-Type: application/json'); echo json_encode(['error' => 'Decryption failed: ' . openssl_error_string()]); exit; } // 去除PKCS7填充 $pad = ord($decrypted[strlen($decrypted) - 1]); $decrypted = substr($decrypted, 0, -$pad); // 解析JSON $data = json_decode($decrypted, true); if (json_last_error() !== JSON_ERROR_NONE) { header('Content-Type: application/json'); echo json_encode(['error' => 'JSON parse error: ' . json_last_error_msg()]); exit; } if (!isset($data['phoneNumber'])) { header('Content-Type: application/json'); echo json_encode(['error' => 'Phone number not found']); exit; } // 返回成功响应 header('Content-Type: application/json'); echo json_encode(['phoneNumber' => $data['phoneNumber']]); ?> ``` 注意:官方文档可能不需要手动去除填充,因为openssl_decrypt会自动处理填充如果指定了选项,但默认是PKCS7填充,并且openssl_decrypt会去除它。在PHP中,openssl_decrypt默认处理PKCS7填充,所以不需要手动去除。但在某些版本,可能需要设置选项。 在官方示例中,他们使用了: ```php $result = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $aesIV); ``` 但OPENSSL_ZERO_PADDING可能不是正确的;应该是PKCS7。 在微信官方PHP示例中,他们使用了: ```php $result = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, OPENSSL_RAW_DATA, $aesIV); ``` 然后检查错误。 在下载的示例中,`wxBizDataCrypt.php`: ```php public function decryptData( $encryptedData, $iv ) { if (strlen($this->sessionKey) != 24) { throw new \Exception('sessionKey error'); } $aesKey=base64_decode($this->sessionKey); if (strlen($iv) != 24) { throw new \Exception('iv error'); } $aesIV=base64_decode($iv); $aesCipher=base64_decode($encryptedData); $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV); $dataObj=json_decode( $result ); if( $dataObj == NULL ) { throw new \Exception('Illegal buffer'); } if( $dataObj->watermark->appid != $this->appid ) { throw new \Exception('Illegal watermark'); } $data = $result; return $data; } ``` 注意:这里使用了`openssl_decrypt` with `1` which is `OPENSSL_RAW_DATA`, but no padding removal. And they check the appid in watermark. 在解密手机号时,也需要检查watermark的appid是否匹配,以确保数据安全。 在解密后的数据中,有一个watermark对象,包含appid,应该与小程序appid比较。 所以,在代码中,我需要小程序appid。 但用户的前端没有提供appid。在解密时,appid应该从后端配置。 所以,后端需要知道小程序的appid。 修改代码: - 添加appid配置。 - 解密后检查watermark。 更新PHP代码: ```php <?php // getTelNumber.php // 配置小程序appid $appid = 'your_appid'; // 替换为实际appid // 获取POST参数 $sessionKey = $_POST['session_key'] ?? ''; $encryptedData = $_POST['encryptedData'] ?? ''; $iv = $_POST['iv'] ?? ''; if (empty($sessionKey) || empty($encryptedData) || empty($iv)) { header('Content-Type: application/json'); echo json_encode(['error' => 'Missing parameters']); exit; } // Base64解码 $sessionKey = base64_decode($sessionKey); $encryptedData = base64_decode($encryptedData); $iv = base64_decode($iv); // 解密 $decrypted = openssl_decrypt($encryptedData, 'AES-128-CBC', $sessionKey, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { header('Content-Type: application/json'); echo json_encode(['error' => 'Decryption failed: ' . openssl_error_string()]); exit; } // 解析JSON $data = json_decode($decrypted, true); if (json_last_error() !== JSON_ERROR_NONE) { header('Content-Type: application/json'); echo json_encode(['error' => 'JSON parse error: ' . json_last_error_msg()]); exit; } // 检查watermark if (!isset($data['watermark']['appid']) || $data['watermark']['appid'] != $appid) { header('Content-Type: application/json'); echo json_encode(['error' => 'Invalid watermark']); exit; } // 获取手机号 if (!isset($data['phoneNumber'])) { header('Content-Type: application/json'); echo json_encode(['error' => 'Phone number not found']); exit; } // 返回成功响应 header('Content-Type: application/json'); echo json_encode(['phoneNumber' => $data['phoneNumber']]); ?> ``` 在官方文档中,解密后的数据包括: ```json { "phoneNumber": "13580006666", "purePhoneNumber": "13580006666", "countryCode": "86", "watermark": { "appid": "APPID", "timestamp": TIMESTAMP } } ``` 所以,提取`phoneNumber`。 现在,关于填充:在PHP的openssl_decrypt中,使用AES-128-CBC和PKCS7填充,它会自动处理填充,所以不需要手动去除。 在代码中,我直接使用json_decode,没问题。 错误处理:捕获可能的异常。 在响应中,返回JSON格式。 用户前端期望:在引用[2]中,前端处理响应: ```javascript util.request(url, 'post', params, '', (res) => { that.setData({ phone: res.data.phoneNumber, }) // ... }, function () { that.showToast_fail('获取手机号失败'); }) ``` 所以,后端应该返回`{ "phoneNumber": "13580006666" }` 或错误。 在我的代码中,错误时返回`{ "error": "message" }`,前端需要处理。 现在,生成相关问题。 根据系统指令: - 使用中文回答。 - 结构清晰。 - 生成相关问题。 回答结构: 1. 解释后端解密过程。 2. 提供PHP代码示例。 3. 注意事项。 4. 生成相关问题。 相关问题: - 如何获取session_key? - 解密失败的可能原因? - 如何在小程序后端配置appid? - 其他语言的解密实现? 参考引用: - 引用[1]:微信步数解密,类似。 - 引用[2]:前端代码。 - 引用[3]:Python示例。 - 引用[4]:C#示例。 在回答中,末尾添加引用标识。 最终回答。</think>### 微信小程序获取手机号的后端PHP解密代码示例 根据微信官方文档和引用内容,微信小程序获取手机号的后端解密过程涉及AES-128-CBC算法。前端通过 `wx.getPhoneNumber` 获取加密数据(`encryptedData` 和 `iv`),结合 `session_key` 发送到后端。后端需用PHP解密数据,提取手机号。以下是完整的后端PHP解密代码示例,基于官方解密算法实现[^1][^2]。 #### 后端PHP解密代码 (`getTelNumber.php`) ```php <?php // 配置小程序AppID(需替换为实际值) $appid = 'wx_your_appid_here'; // 从微信小程序后台获取 // 接收前端POST参数 $sessionKey = $_POST['session_key'] ?? ''; $encryptedData = $_POST['encryptedData'] ?? ''; $iv = $_POST['iv'] ?? ''; // 验证参数完整性 if (empty($sessionKey) || empty($encryptedData) || empty($iv)) { header('Content-Type: application/json'); echo json_encode(['error' => '参数缺失:session_key, encryptedData, iv 不能为空']); exit; } try { // Base64解码参数 $decodedSessionKey = base64_decode($sessionKey); $decodedEncryptedData = base64_decode($encryptedData); $decodedIv = base64_decode($iv); // AES-128-CBC解密 $decrypted = openssl_decrypt( $decodedEncryptedData, 'AES-128-CBC', $decodedSessionKey, OPENSSL_RAW_DATA, // 使用原始数据模式 $decodedIv ); if ($decrypted === false) { throw new Exception('解密失败: ' . openssl_error_string()); } // 解析JSON数据 $data = json_decode($decrypted, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('JSON解析错误: ' . json_last_error_msg()); } // 验证水印(确保数据来源合法) if (!isset($data['watermark']['appid']) || $data['watermark']['appid'] !== $appid) { throw new Exception('水印验证失败:AppID不匹配'); } // 提取手机号 if (!isset($data['phoneNumber'])) { throw new Exception('未找到手机号字段'); } // 返回成功响应 header('Content-Type: application/json'); echo json_encode(['phoneNumber' => $data['phoneNumber']]); } catch (Exception $e) { // 错误处理 header('Content-Type: application/json'); echo json_encode(['error' => $e->getMessage()]); } ?> ``` #### 关键说明 1. **参数说明**: - `session_key`: 前端通过 `wx.login` 获取的临时登录凭证,需调用微信接口 `code2Session` 换取(参考引用[3])。 - `encryptedData`: 加密的用户数据,包含手机号。 - `iv`: 加密算法的初始向量。 - `appid`: 小程序唯一标识,需从微信后台获取并硬编码在后端[^1][^2]。 2. **解密流程**: - Base64解码所有输入参数。 - 使用 `openssl_decrypt` 进行AES-128-CBC解密。 - 解析JSON并验证 `watermark.appid` 防止数据篡改。 - 提取 `phoneNumber` 字段返回。 3. **依赖要求**: - PHP 7.0 或更高版本(因 `openssl_decrypt` 的稳定性)。 - OpenSSL 扩展已启用(默认多数环境支持)。 - 前端需确保 `session_key` 有效且未过期(有效期约30分钟)[^1]。 4. **错误处理**: - 参数缺失时返回 `参数缺失` 错误。 - 解密失败时捕获OpenSSL错误。 - 水印验证失败或字段缺失时抛出异常。 #### 注意事项 - **安全风险**:`session_key` 是敏感信息,需通过HTTPS传输,避免泄露。 - **性能优化**:可缓存 `session_key` 减少微信接口调用。 - **测试建议**:先用微信官方示例数据测试解密逻辑[^1]。 - 完整流程参考官方文档:[加密数据解密算法](https://developers.weixin.qq.com/miniprogram/dev/guide/open-ability/signature.html#%E5%8A%A0%E5%AF%86%E6%95%B0%E6%8D%AE%E8%A7%A3%E5%AF%86%E7%AE%97%E6%B3%95)[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值