# 提现功能技术文档(微信支付API集成) ## 文档说明 本文档专注于**微信支付商家转账到零钱API**的集成方法,包括: - 微信支付官方API文档 - 签名生成算法 - 加密解密算法 - 完整代码实现 - 测试验证方法 **适用场景**:实现用户提现功能,将资金从商户号转账到用户微信零钱。 --- ## 目录 1. [业务场景](#业务场景) 2. [微信支付官方API文档](#微信支付官方api文档) 3. [前置准备](#前置准备) 4. [API集成](#api集成) 5. [签名算法](#签名算法) 6. [加密解密](#加密解密) 7. [代码实现](#代码实现) 8. [测试验证](#测试验证) --- ## 业务场景 ### 典型流程 ``` 用户申请提现 ↓ 系统审核通过 ↓ 调用微信支付【商家转账到零钱API】 ↓ 微信返回处理中(PROCESSING) ↓ 微信异步处理(7-15秒) ↓ 微信【主动回调】通知转账结果 ↓ 系统接收回调,验签、解密 ↓ 更新提现状态 ↓ 用户确认收款 ``` ### 关键步骤 1. **发起转账**:调用微信API发起转账 2. **接收回调**:接收微信异步通知 3. **验证签名**:验证回调的真实性 4. **解密数据**:解密回调中的加密数据 5. **查询状态**:主动查询转账状态 --- ## 微信支付官方API文档 ### 核心API | API名称 | 官方文档地址 | |--------|------------| | 🔥 **商家转账到零钱** | https://pay.weixin.qq.com/doc/v3/merchant/4012716434 | | 📋 **查询转账单(商户单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716456 | | 📋 **查询转账单(微信单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716457 | | 🔐 **签名生成与验证** | https://pay.weixin.qq.com/doc/v3/merchant/4013053249 | | 🔒 **敏感信息加密** | https://pay.weixin.qq.com/doc/v3/merchant/4012070130 | | 🔓 **回调通知解密** | https://pay.weixin.qq.com/doc/v3/merchant/4012071382 | | 📝 **转账场景报备** | https://pay.weixin.qq.com/doc/v3/merchant/4012716437 | | ❌ **错误码查询** | https://pay.weixin.qq.com/doc/v3/merchant/4012070193 | | 📜 **平台证书管理** | https://pay.weixin.qq.com/doc/v3/merchant/4012154180 | ### 开发指引 - **API V3 开发总览**:https://pay.weixin.qq.com/doc/v3/merchant/4012065168 - **PHP SDK 使用**:https://pay.weixin.qq.com/doc/v3/merchant/4012076511 --- ## 前置准备 ### 1. 获取配置信息 登录微信商户平台:https://pay.weixin.qq.com | 配置项 | 说明 | 获取路径 | |-------|------|---------| | **商户号(mch_id)** | 微信支付商户号 | 账户中心 → 商户信息 | | **APIv3密钥(api_v3_key)** | 32字节密钥,用于加密解密 | 账户中心 → API安全 → 设置APIv3密钥 | | **商户私钥(apiclient_key.pem)** | 用于请求签名 | 账户中心 → API安全 → 申请证书 | | **证书序列号(cert_serial_no)** | 商户证书标识 | 从证书文件提取 | | **平台证书(wechat_pay_pub_key)** | 用于验证回调签名 | 下载或通过API获取 | | **小程序AppId** | 小程序标识 | 小程序管理后台 | ### 2. 提取证书序列号 **使用OpenSSL命令**: ```bash openssl x509 -in apiclient_cert.pem -noout -serial ``` 输出: ``` serial=4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5 ``` **使用PHP**: ```php ``` ### 3. 配置IP白名单 路径:微信商户平台 → 账户中心 → API安全 → IP配置 添加服务器公网IP地址。 **获取服务器IP**: ```bash curl ifconfig.me ``` ### 4. 配置转账场景 路径:微信商户平台 → 产品中心 → 商家转账到零钱 → 前往功能 可选场景: - **1000**:现金营销 - **1005**:营销活动 ### 5. 环境要求 - PHP >= 7.0 - OpenSSL 扩展(必须) - cURL 扩展(必须) - JSON 扩展(必须) - TLS 1.2+ **检查环境**: ```bash php -v php -m | grep openssl php -m | grep curl ``` --- ## API集成 ### 1. 商家转账到零钱API #### 基本信息 - **接口地址**:`https://api.mch.weixin.qq.com/v3/transfer/batches` - **请求方法**:POST - **Content-Type**:application/json #### 请求头 ``` Authorization: WECHATPAY2-SHA256-RSA2048 mchid="商户号",nonce_str="随机字符串",signature="签名",timestamp="时间戳",serial_no="证书序列号" Content-Type: application/json Accept: application/json User-Agent: YourApp/1.0 ``` #### 请求参数 ```json { "appid": "wx6489c26045912fe1", "out_batch_no": "BATCH202601291234567890", "batch_name": "提现", "batch_remark": "用户提现", "total_amount": 5000, "total_num": 1, "transfer_detail_list": [ { "out_detail_no": "TX202601291234567890", "transfer_amount": 5000, "transfer_remark": "提现", "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk" } ], "transfer_scene_id": "1005", "transfer_scene_report_infos": [ { "info_type": "岗位类型", "info_content": "兼职人员" }, { "info_type": "报酬说明", "info_content": "当日兼职费" } ] } ``` **参数说明**: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | appid | string | 是 | 小程序AppId | | out_batch_no | string | 是 | 商户批次单号,商户下唯一 | | batch_name | string | 是 | 批次名称 | | batch_remark | string | 是 | 批次备注 | | total_amount | integer | 是 | 转账总金额,单位:**分** | | total_num | integer | 是 | 转账总笔数 | | transfer_detail_list | array | 是 | 转账明细列表 | | transfer_scene_id | string | 是 | 转账场景ID:1000或1005 | | transfer_scene_report_infos | array | 否 | 场景报备信息 | **transfer_detail_list说明**: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | out_detail_no | string | 是 | 商户明细单号 | | transfer_amount | integer | 是 | 转账金额,单位:**分** | | transfer_remark | string | 是 | 转账备注 | | openid | string | 是 | 收款用户OpenId | **场景报备信息(场景ID=1005)**: ```json [ { "info_type": "岗位类型", "info_content": "兼职人员" }, { "info_type": "报酬说明", "info_content": "当日兼职费" } ] ``` **重要**: - `info_type` 必须是固定值 - 金额单位是**分**:`元 * 100` #### 响应数据 **成功响应**: ```json { "out_batch_no": "BATCH202601291234567890", "batch_id": "1030000071100999991182020050700019480001", "create_time": "2026-01-29T12:30:00+08:00", "batch_status": "PROCESSING" } ``` **字段说明**: | 字段 | 说明 | |------|------| | out_batch_no | 商户批次单号 | | batch_id | 微信批次单号 | | create_time | 批次创建时间 | | batch_status | 批次状态:PROCESSING/SUCCESS/FAIL | **失败响应**: ```json { "code": "PARAM_ERROR", "message": "参数错误" } ``` ### 2. 查询转账单API #### 按商户单号查询 **接口地址**: ``` GET https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} ``` **路径参数**: - `batch_id`:商户批次单号(需URL编码) - `detail_id`:商户明细单号(需URL编码) **示例**: ``` GET /v3/transfer/batches/batch-id/BATCH202601291234567890/details/detail-id/TX202601291234567890 ``` **响应示例**: ```json { "mchid": "1318592501", "out_batch_no": "BATCH202601291234567890", "batch_id": "1030000071100999991182020050700019480001", "out_detail_no": "TX202601291234567890", "detail_id": "1040000071100999991182020050700019500100", "detail_status": "SUCCESS", "transfer_amount": 5000, "transfer_remark": "提现", "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", "initiate_time": "2026-01-29T12:30:00+08:00", "update_time": "2026-01-29T12:30:15+08:00" } ``` **状态说明**: | detail_status | 说明 | |--------------|------| | PROCESSING | 转账中 | | SUCCESS | 转账成功 | | FAIL | 转账失败 | ### 3. 转账结果通知(回调) #### 回调触发 当转账状态变更时,微信支付会主动向配置的 `notify_url` 发送POST请求。 #### 回调请求头 ``` Wechatpay-Signature: 签名值 Wechatpay-Timestamp: 1769653396 Wechatpay-Nonce: R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L Wechatpay-Serial: 642B2B33557205BA79A1CFF08EA2A2478D67BD63 Wechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048 Content-Type: application/json ``` #### 回调请求体(加密) ```json { "id": "cb29e425-ca17-59fb-8045-8e5b58917154", "create_time": "2026-01-29T10:23:11+08:00", "resource_type": "encrypt-resource", "event_type": "MCHTRANSFER.BILL.FINISHED", "summary": "商家转账单据终态通知", "resource": { "original_type": "mch_payment", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "加密的数据...", "associated_data": "mch_payment", "nonce": "随机字符串" } } ``` #### 解密后的数据 ```json { "mch_id": "1318592501", "out_bill_no": "TX202601291234567890", "transfer_bill_no": "1330000114850082601290057112302122", "transfer_amount": 5000, "state": "SUCCESS", "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", "create_time": "2026-01-29T12:30:00+08:00", "update_time": "2026-01-29T12:30:15+08:00" } ``` **state状态说明**: | state | 说明 | |-------|------| | PROCESSING | 转账中 | | SUCCESS | 转账成功 | | FAIL | 转账失败 | | WAIT_USER_CONFIRM | 待用户确认 | | TRANSFERING | 正在转账 | #### 回调响应 处理完成后,返回给微信: ```json { "code": "SUCCESS" } ``` --- ## 签名算法 ### 1. 签名生成(请求签名) #### 签名串格式 ``` 请求方法\n 请求URL路径\n 请求时间戳\n 随机字符串\n 请求报文主体\n ``` **示例**: ``` POST /v3/transfer/batches 1234567890 RandomString123456 {"appid":"wx6489c26045912fe1"} ``` **重要**:每部分末尾都有 `\n` 换行符。 #### 签名步骤 1. 构建签名串 2. 使用商户私钥进行SHA256withRSA签名 3. 对签名结果进行Base64编码 #### PHP实现 ```php function buildSignature($method, $url, $timestamp, $nonce, $body, $privateKeyPath) { // 1. 构建签名串 $signStr = $method . "\n" . $url . "\n" . $timestamp . "\n" . $nonce . "\n" . $body . "\n"; // 2. 加载私钥 $privateKeyContent = file_get_contents($privateKeyPath); $privateKeyResource = openssl_pkey_get_private($privateKeyContent); // 3. 使用私钥签名 openssl_sign($signStr, $signature, $privateKeyResource, 'sha256WithRSAEncryption'); // 4. Base64编码 return base64_encode($signature); } ``` #### 构建Authorization头 ```php function buildAuthorization($mchId, $timestamp, $nonce, $signature, $serialNo) { return sprintf( 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', $mchId, $nonce, $signature, $timestamp, $serialNo ); } ``` ### 2. 签名验证(回调验签) #### 验签串格式 ``` 时间戳\n 随机字符串\n 请求报文主体\n ``` **示例**: ``` 1769653396 R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L {"id":"cb29e425-ca17-59fb-8045-8e5b58917154",...} ``` #### PHP实现 ```php function verifySignature($timestamp, $nonce, $body, $signature, $publicKeyPath) { // 1. 构建验签串 $verifyStr = $timestamp . "\n" . $nonce . "\n" . $body . "\n"; // 2. Base64解码签名 $signatureDecode = base64_decode($signature); // 3. 加载平台公钥 $publicKeyContent = file_get_contents($publicKeyPath); $publicKeyResource = openssl_pkey_get_public($publicKeyContent); // 4. 验证签名 $result = openssl_verify( $verifyStr, $signatureDecode, $publicKeyResource, 'sha256WithRSAEncryption' ); return $result === 1; // 1表示验证成功 } ``` **重要**:验签使用的是**微信支付平台公钥**,不是商户私钥! --- ## 加密解密 ### 回调数据解密 #### 算法信息 - **算法**:AEAD_AES_256_GCM - **密钥**:APIv3密钥(32字节) - **密文格式**:实际密文 + 认证标签(16字节) #### 解密步骤 1. 提取加密数据(ciphertext、nonce、associated_data) 2. Base64解码密文 3. 分离密文和认证标签(最后16字节) 4. 使用AES-256-GCM解密 5. 解析JSON数据 #### PHP实现 ```php function decryptCallbackData($ciphertext, $nonce, $associatedData, $apiV3Key) { // 1. 检查APIv3密钥长度(必须32字节) if (strlen($apiV3Key) !== 32) { throw new Exception('APIv3密钥长度必须为32字节'); } // 2. Base64解码密文 $ciphertextDecoded = base64_decode($ciphertext); // 3. 分离密文和认证标签 $authTag = substr($ciphertextDecoded, -16); $ctext = substr($ciphertextDecoded, 0, -16); // 4. 使用AES-256-GCM解密 $decrypted = openssl_decrypt( $ctext, // 密文 'aes-256-gcm', // 算法 $apiV3Key, // 密钥 OPENSSL_RAW_DATA, // 选项 $nonce, // 随机串 $authTag, // 认证标签 $associatedData // 附加数据 ); if ($decrypted === false) { throw new Exception('解密失败'); } // 5. 解析JSON return json_decode($decrypted, true); } ``` **使用示例**: ```php $resource = $callbackData['resource']; $decrypted = decryptCallbackData( $resource['ciphertext'], $resource['nonce'], $resource['associated_data'], 'wx3e31b068be59ddc131b068be59ddc2' // APIv3密钥 ); ``` --- ## 代码实现 ### 完整的微信支付转账类 ```php mchId = $config['mch_id']; $this->appId = $config['app_id']; $this->apiV3Key = $config['api_v3_key']; $this->certSerialNo = $config['cert_serial_no']; // 加载私钥 $privateKeyContent = file_get_contents($config['private_key']); $this->privateKey = openssl_pkey_get_private($privateKeyContent); } /** * 发起转账 */ public function createTransfer($params) { $url = '/v3/transfer/batches'; $method = 'POST'; // 构建请求数据 $data = [ 'appid' => $this->appId, 'out_batch_no' => 'BATCH' . date('YmdHis') . mt_rand(1000, 9999), 'batch_name' => $params['batch_name'] ?? '提现', 'batch_remark' => $params['batch_remark'] ?? '用户提现', 'total_amount' => $params['transfer_amount'], 'total_num' => 1, 'transfer_detail_list' => [ [ 'out_detail_no' => $params['out_detail_no'], 'transfer_amount' => $params['transfer_amount'], 'transfer_remark' => $params['transfer_remark'], 'openid' => $params['openid'], ] ], 'transfer_scene_id' => $params['transfer_scene_id'] ?? '1005', ]; // 添加场景报备信息 if (!empty($params['transfer_scene_report_infos'])) { $data['transfer_scene_report_infos'] = $params['transfer_scene_report_infos']; } $body = json_encode($data, JSON_UNESCAPED_UNICODE); // 生成签名 $timestamp = time(); $nonce = $this->generateNonce(); $signature = $this->buildSignature($method, $url, $timestamp, $nonce, $body); // 构建Authorization $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); // 发送请求 return $this->request($method, $url, $body, $authorization); } /** * 查询转账单 */ public function queryTransfer($batchNo, $detailNo) { $url = "/v3/transfer/batches/batch-id/" . urlencode($batchNo) . "/details/detail-id/" . urlencode($detailNo); $method = 'GET'; $timestamp = time(); $nonce = $this->generateNonce(); $signature = $this->buildSignature($method, $url, $timestamp, $nonce, ''); $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); return $this->request($method, $url, '', $authorization); } /** * 验证回调签名 */ public function verifyCallback($headers, $body, $publicKey) { $timestamp = $headers['wechatpay-timestamp']; $nonce = $headers['wechatpay-nonce']; $signature = $headers['wechatpay-signature']; $verifyStr = $timestamp . "\n" . $nonce . "\n" . $body . "\n"; $signatureDecode = base64_decode($signature); $publicKeyContent = file_get_contents($publicKey); $publicKeyResource = openssl_pkey_get_public($publicKeyContent); $result = openssl_verify($verifyStr, $signatureDecode, $publicKeyResource, 'sha256WithRSAEncryption'); return $result === 1; } /** * 解密回调数据 */ public function decryptCallbackResource($resource) { $ciphertext = $resource['ciphertext']; $nonce = $resource['nonce']; $associatedData = $resource['associated_data']; if (strlen($this->apiV3Key) !== 32) { throw new \Exception('APIv3密钥长度必须为32字节'); } $ciphertextDecoded = base64_decode($ciphertext); $authTag = substr($ciphertextDecoded, -16); $ctext = substr($ciphertextDecoded, 0, -16); $decrypted = openssl_decrypt( $ctext, 'aes-256-gcm', $this->apiV3Key, OPENSSL_RAW_DATA, $nonce, $authTag, $associatedData ); if ($decrypted === false) { throw new \Exception('解密失败'); } return json_decode($decrypted, true); } /** * 生成签名 */ private function buildSignature($method, $url, $timestamp, $nonce, $body) { $signStr = $method . "\n" . $url . "\n" . $timestamp . "\n" . $nonce . "\n" . $body . "\n"; openssl_sign($signStr, $signature, $this->privateKey, 'sha256WithRSAEncryption'); return base64_encode($signature); } /** * 构建Authorization头 */ private function buildAuthorization($timestamp, $nonce, $signature) { return sprintf( 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', $this->mchId, $nonce, $signature, $timestamp, $this->certSerialNo ); } /** * 生成随机字符串 */ private function generateNonce($length = 32) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $nonce = ''; for ($i = 0; $i < $length; $i++) { $nonce .= $chars[mt_rand(0, strlen($chars) - 1)]; } return $nonce; } /** * 发送HTTP请求 */ private function request($method, $url, $body, $authorization) { $fullUrl = 'https://api.mch.weixin.qq.com' . $url; $headers = [ 'Authorization: ' . $authorization, 'Content-Type: application/json', 'Accept: application/json', 'User-Agent: YourApp/1.0' ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $fullUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); if ($method === 'POST') { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $result = json_decode($response, true); if ($httpCode >= 200 && $httpCode < 300) { return ['success' => true, 'data' => $result]; } else { return [ 'success' => false, 'error_code' => $result['code'] ?? 'UNKNOWN', 'error_msg' => $result['message'] ?? '未知错误' ]; } } } ``` ### 使用示例 #### 1. 发起转账 ```php // 初始化配置 $config = [ 'mch_id' => '1318592501', 'app_id' => 'wx6489c26045912fe1', 'api_v3_key' => 'wx3e31b068be59ddc131b068be59ddc2', 'private_key' => '/path/to/apiclient_key.pem', 'cert_serial_no' => '4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5', ]; $wechatPay = new WechatPayTransfer($config); // 发起转账 $result = $wechatPay->createTransfer([ 'out_detail_no' => 'TX' . date('YmdHis') . mt_rand(1000, 9999), 'transfer_amount' => 5000, // 50元 = 5000分 'transfer_remark' => '提现', 'openid' => 'odq3g5IOG-Z1WLpbeG_amUme8EZk', 'transfer_scene_id' => '1005', 'transfer_scene_report_infos' => [ ['info_type' => '岗位类型', 'info_content' => '兼职人员'], ['info_type' => '报酬说明', 'info_content' => '当日兼职费'], ], ]); if ($result['success']) { echo "转账成功: " . json_encode($result['data']); } else { echo "转账失败: " . $result['error_msg']; } ``` #### 2. 查询转账单 ```php $result = $wechatPay->queryTransfer('BATCH202601291234567890', 'TX202601291234567890'); if ($result['success']) { echo "状态: " . $result['data']['detail_status']; } else { echo "查询失败: " . $result['error_msg']; } ``` #### 3. 处理回调 ```php // 接收回调 $headers = [ 'wechatpay-signature' => $_SERVER['HTTP_WECHATPAY_SIGNATURE'], 'wechatpay-timestamp' => $_SERVER['HTTP_WECHATPAY_TIMESTAMP'], 'wechatpay-nonce' => $_SERVER['HTTP_WECHATPAY_NONCE'], 'wechatpay-serial' => $_SERVER['HTTP_WECHATPAY_SERIAL'], ]; $body = file_get_contents('php://input'); $callbackData = json_decode($body, true); // 验证签名 $verified = $wechatPay->verifyCallback($headers, $body, '/path/to/wechat_pay_pub_key.pem'); if ($verified) { // 解密数据 $decrypted = $wechatPay->decryptCallbackResource($callbackData['resource']); // 处理转账结果 if ($decrypted['state'] === 'SUCCESS') { echo "转账成功: " . $decrypted['out_bill_no']; } // 返回成功 echo json_encode(['code' => 'SUCCESS']); } else { echo json_encode(['code' => 'FAIL', 'message' => '签名验证失败']); } ``` --- ## 测试验证 ### 1. 签名生成测试 ```php $method = 'POST'; $url = '/v3/transfer/batches'; $timestamp = time(); $nonce = 'RandomString123456'; $body = '{"appid":"wx6489c26045912fe1"}'; $signature = buildSignature($method, $url, $timestamp, $nonce, $body, 'apiclient_key.pem'); echo "签名: " . $signature . "\n"; ``` ### 2. 小额转账测试 ```php // 测试金额:0.01元 = 1分 $result = $wechatPay->createTransfer([ 'out_detail_no' => 'TEST' . time(), 'transfer_amount' => 1, // 1分 'transfer_remark' => '测试', 'openid' => 'test_openid', 'transfer_scene_id' => '1005', 'transfer_scene_report_infos' => [ ['info_type' => '岗位类型', 'info_content' => '测试'], ['info_type' => '报酬说明', 'info_content' => '测试'], ], ]); ``` ### 3. 解密测试 ```php $resource = [ 'ciphertext' => 'xxx', 'nonce' => 'xxx', 'associated_data' => 'mch_payment', ]; try { $decrypted = decryptCallbackData( $resource['ciphertext'], $resource['nonce'], $resource['associated_data'], 'wx3e31b068be59ddc131b068be59ddc2' ); print_r($decrypted); } catch (Exception $e) { echo "解密失败: " . $e->getMessage(); } ``` ### 4. 常见问题 | 问题 | 原因 | 解决方法 | |------|------|---------| | 签名验证失败 | 证书序列号错误 | 重新提取证书序列号 | | IP白名单错误 | 服务器IP未配置 | 添加到微信商户平台 | | 解密失败 | APIv3密钥错误 | 检查密钥长度(32字节) | | 场景报备错误 | info_type不正确 | 使用固定值 | | 余额不足 | 商户号余额不足 | 充值商户号 | --- ## 附录 ### A. 错误码对照表 https://pay.weixin.qq.com/doc/v3/merchant/4012070193 | 错误码 | 说明 | 处理建议 | |-------|------|---------| | PARAM_ERROR | 参数错误 | 检查请求参数格式 | | NOTENOUGH | 商户余额不足 | 充值商户号 | | INVALID_REQUEST | 不符合业务规则 | 检查业务逻辑 | | SYSTEM_ERROR | 系统错误 | 稍后重试 | | FREQUENCY_LIMITED | 频率限制 | 降低请求频率 | | APPID_MCHID_NOT_MATCH | appid和mch_id不匹配 | 检查配置 | ### B. 转账状态说明 | 状态 | 说明 | 处理方式 | |------|------|---------| | PROCESSING | 转账中 | 等待回调或主动查询 | | SUCCESS | 转账成功 | 完成流程 | | FAIL | 转账失败 | 检查失败原因 | | WAIT_USER_CONFIRM | 待用户确认 | 等待用户操作 | | TRANSFERING | 正在转账 | 等待处理完成 | ### C. 开发工具 - **Postman**:API测试工具 - **OpenSSL**:证书和密钥管理 - **微信支付调试工具**:https://pay.weixin.qq.com/ --- **文档版本**:v3.0(纯微信支付API版) **更新时间**:2026-01-29 **适用场景**:微信支付商家转账到零钱功能集成 --- ## 总结 本文档提供了微信支付转账功能的完整集成方案: ✅ **3个核心API** - 发起转账:`POST /v3/transfer/batches` - 查询转账:`GET /v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}` - 接收回调:异步通知 ✅ **3个核心算法** - 签名生成:SHA256withRSA + Base64 - 签名验证:使用平台公钥 - 数据解密:AEAD_AES_256_GCM ✅ **完整代码实现** - WechatPayTransfer类(可直接使用) - 包含发起转账、查询、验签、解密全部功能 根据本文档可以快速集成微信支付转账功能。