微信支付商家转账到个人小程序接口实战指南

随着小程序生态的不断发展,很多企业和商家都有一个常见需求:如何从商家账户安全、合规地向用户发放资金?比如发放活动奖励、推广佣金、用户返现、分销结算等。

微信支付官方提供了 商家转账到零钱(小程序场景)接口,能够帮助企业实现这一功能。本文将结合 PHP 代码示例,带大家了解如何调用该接口。


为什么需要小程序转账?

在很多实际业务中,资金发放是必不可少的一环,例如:

  • 用户激励:完成任务后直接发现金红包到用户零钱;

  • 分销/返利:按比例将佣金结算到个人账户;

  • 补贴/退款:活动补贴、订单差价等直接发放;

  • 奖励发放:抽奖、签到活动即时兑现。

相较于传统的人工转账,微信官方 API 更安全、自动化、可追溯,也能减少财务人工操作风险。


接口介绍

接口地址:

POST https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills

核心要点:

  1. 需要商户号(mchid)、小程序 appid、API证书和私钥

  2. 请求必须使用 SHA256 with RSA 加签,保证安全性;

  3. 金额 >= 2000 元时必须填写收款人姓名,并且使用平台公钥加密;

  4. 支持自定义业务单号、转账备注、场景 ID 等。


PHP 示例代码

下面是一段完整的 PHP 实现,包含签名、加密和请求逻辑。

<?php
namespace wechat;
class WxPayMiniTransfer
{
// 配置参数
private $mchid = ''; // 商户号
private $appid = ''; // 小程序APPID
private $certPath = ''; // 商户证书路径
private $keyPath = ''; // 商户私钥路径
private $wechatpaySerial = ''; // 微信支付平台证书序列号
private $mch_serial = ''; // 商户证书序列号
private $apiUrl = 'https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills';

/**
* 发起商家小程序转账
* @param array $transferInfo 转账信息数组
* @return array
* @throws \Exception
*/

public function __construct()
{
$config = config('wechat');
$this->mchid = $config['mch_id'];
$this->appid = $config['app_id'];
$this->certPath = $config['cert_path'];
$this->keyPath = $config['key_path'];
$this->wechatpaySerial = $config['wechatpay_serial'];
$this->mch_serial = $config['mch_serial'];
}
public function createMiniTransfer(array $transferInfo)
{
$data = [
'appid' => $this->appid,
'out_bill_no' => $transferInfo['out_bill_no'],
'transfer_scene_id' => $transferInfo['transfer_scene_id'],
'openid' => $transferInfo['openid'],
'transfer_amount' => $transferInfo['transfer_amount']*100,// 转账金额(分)
'transfer_remark' => $transferInfo['transfer_remark'],
//'notify_url' => $transferInfo['notify_url'],
'user_recv_perception' => $transferInfo['user_recv_perception'],
'transfer_scene_report_infos' => $transferInfo['transfer_scene_report_infos']
];
if($transferInfo['transfer_amount']>=2000){
if(empty($transferInfo['user_name'])){
throw new \Exception( '明细金额大于等于2000,收款人姓名必须填写');
}
$data['user_name']= $this->encryptUserName($transferInfo['user_name']);
}
// 1. 构建请求Body
$body = json_encode($data, JSON_UNESCAPED_UNICODE);

// 2. 生成随机串和时间戳
$nonce = $this->generateNonce();
$timestamp = time();

// 3. 生成签名
$method = 'POST';
$url = '/v3/fund-app/mch-transfer/transfer-bills'; // 请求的绝对路径
$signatureMessage = $method . "\n" .
$url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";

// 使用商户私钥对签名串进行SHA256 with RSA签名
$signature = $this->signMessage($signatureMessage);
$signatureBase64 = base64_encode($signature);

// 4. 构建Authorization请求头
$token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"',
$this->mchid,
$nonce,
$signatureBase64,
$timestamp,
$this->mch_serial
);

//测试检验你的小程序和商户的密钥等设置是否正确
// curl -X POST https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills \
// -H "Content-Type: application/json" \
// -H "Authorization: WECHATPAY2-SHA256-RSA2048 mchid=\"你的商户号\",nonce_str=\"243ea1a0\",signature=\"HzVHaqu1fau2U4MYbL8PR0uFh7vxGhoEHRA9Y/zOFpOO2u8MdMBx7NLCtYxKup9Ey+I2CufR0iDWycCmGt+CPU6EyQ7PiwFDqHHjP/CnYxwoko5POUwMmXkqORQw6QmUEF5RInVXEDnOa8TCNzS/64PiMsNFItvLSVM8HJxeWU9Aywka88yizr67hvKpw0NOaj+Rte44g36k9UvMK4yKH3rxr4A6gPFFVaObrPMQ4U3JxGl+euBJmiWy1gi8Yc2UVQ7dhUxzVVXrXmigEsjfakaFZW6y7dU34Q3GQxddeB1XbDtnG1vcJ+CDOMo4ET2RUXr0JZD+VgIw5tD16ealJQ==\",timestamp=\"1756569416\",serial_no=\"245032232472480232664006076861880199408114685090\"" \
// -H "Wechatpay-Serial: 350853A73D8C3FD184F0152174F4199EB2DF2D22" \
// -d '{"appid":"你的小程序appid","out_bill_no":"202507262216578774","openid":"oXJi25S_ikttPhn3vKy_9rJoNNZs"}'
//openssl x509 -in apiclient_cert.pem -noout -serial 查询商户证书序列号
//openssl x509 -in apiclient_cert.pem -noout -text | grep -o 'CN=[0-9]*' | sed 's/CN=//' 根据证书查询商户号
// 5. 设置HTTP头并发送请求
$headers = [
'Content-Type: application/json',
'Accept: application/json',
'User-Agent: 你的小程序名字',
'Authorization: ' . $token,
'Wechatpay-Serial: ' . $this->wechatpaySerial // 添加微信支付平台证书序列号
];

$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $this->apiUrl,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSLCERT => $this->certPath,
CURLOPT_SSLKEY => $this->keyPath,
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);

if ($error) {
throw new \Exception("cURL Error: " . $error);
}

// 6. 处理响应
$result = json_decode($response, true);
if ($httpCode >= 200 && $httpCode < 300) {
return $result;
}
else {
throw new \Exception(sprintf('Request failed. HTTP Code: %d, Response: %s', $httpCode, $response));
}
}

/**
* 生成随机串
*/
private function generateNonce()
{
return sprintf('%08x', mt_rand(0, 0x7fffffff));
}

/**
* 对消息进行签名
*/
private function signMessage($message)
{
$privateKey = $this->getPrivateKey();
openssl_sign($message, $signature, $privateKey, 'sha256WithRSAEncryption');
return $signature;
}


/**
* 加载商户私钥
*/
private function getPrivateKey()
{
$key = file_get_contents($this->keyPath);
if (!$key) {
throw new \Exception("Failed to load private key: {$this->keyPath}");
}
$privateKey = openssl_get_privatekey($key);
if (!$privateKey) {
throw new \Exception("Failed to parse private key");
}
return $privateKey;
}

/**
* 加密敏感信息(用户名)
* 需要使用微信支付平台证书进行RSA加密
*/
public function encryptUserName($userName)
{
$encrypted = '';
$result = openssl_public_encrypt(
$userName,
$encrypted,
$this->wechatpaySerial,
OPENSSL_PKCS1_OAEP_PADDING
);

if (!$result) {
throw new \Exception("加密失败: " . openssl_error_string());
}

// 4. 返回Base64编码结果
return base64_encode($encrypted);
}

}
$config = config('wechat');

核心步骤包括:

  • 生成签名串(method、url、timestamp、nonce、body);

  • 使用商户私钥进行 SHA256withRSA 签名;

  • 拼接 Authorization 头部;

  • 通过 cURL 发起 HTTPS POST 请求;

  • 解析返回结果,判断是否转账成功。

调用示例:

$transfer = new WxPayMiniTransfer();

$transferData = [
'out_bill_no' => $withdraw['order_no'], // 商户转账单据号
'transfer_scene_id' => '1005', // id=1005 佣金报酬
'openid' => $withdraw['openid'], // 用户openid
//'user_name' => $withdraw['real_name'], // 用户名(需要加密)
'transfer_amount' => $withdraw['amount'],
'transfer_remark' => '佣金奖励', // 转账备注
'user_recv_perception' => '劳务报酬', // 用户领取感知
'transfer_scene_report_infos' => [
[
'info_type' => '岗位类型',
'info_content' => '佣金奖励'
],
[
'info_type' => '报酬说明',
'info_content' => '佣金奖励'
],
]
];

$result = $transfer->createMiniTransfer($transferData);
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
// 更新状态为成功
$withdraw->save([
'status' => 'agree',
'wechat_billno' => $result['payment_billno'] ?? '',
'handle_time' => time(),
'memo' => '提现成功'
]);
//增加金额记录
UserMoneyLog::log($withdraw['user_id'], $withdraw['amount'], '余额提现', 'withdraw');
$this->success('提现成功');
} else {
// 微信返回失败
$withdraw->save([
'status' => 'fail',
'handle_time' => time(),
'memo' => $result['err_code_des'] ?? '微信返回失败: ' . json_encode($result),
]);
$this->error('提现失败:' . $result['return_msg']);
}




注意事项

  1. 证书管理:需要上传商户 API 证书、私钥,并在配置中填入对应序列号;

  2. 敏感信息加密:收款人姓名必须使用 微信支付平台证书公钥加密,而不是直接传输明文;

  3. 错误处理:接口返回非 2xx 状态时,需要记录日志,便于排查;

  4. 幂等性:业务单号 out_bill_no 必须唯一,避免重复转账;

  5. 安全合规:确保资金发放符合业务和监管要求,避免违规用途。


应用场景举例

  • 电商返现:商家活动奖励自动结算到用户零钱;

  • 社交平台:创作者分成收益定期结算;

  • 出行/生活服务:司机、骑手补贴自动到账;

  • 企业内部:员工激励金、奖金发放。


总结

微信小程序转账接口为商家提供了一个 安全、自动化、灵活 的资金发放渠道。通过 API 调用,商家可以将用户激励、返利、补贴等资金高效发放到个人零钱账户,不仅提升了用户体验,也降低了财务操作成本。

如果你正准备在小程序或平台业务中增加 奖励结算、返现 功能,那么微信支付的 商家转账接口 将是一个非常合适的解决方案。




点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部