目录
一、日常填坑:注意事项
1:转账低于5毛会失败
2:转账金额需要自己取整一下,不然运气来了会出现以下问题
{
"code":"PARAM_ERROR",
"detail":{
"location":"body",
"value":7.000000000000001 // 微信金额除不尽出现的问题
},
"message":" 无法将 JSON 输入源“\/body\/
total_amount”映射到目标字段“转账总金额”中,
此字段需要一个合法的 64 位有符号整数"
}
二、代码示例
1.服务层
const SSLCERT_PATH = '证书路径';
const SSLKEY_PATH = '证书key路径';
const MCHID = '商户号';
const APPID = 'app_id';
const KEY = 'key值';
/**
* 付款到微信零钱
* sOpenid:收款方openid
* nMoney:转账金额
*/
public function transfer_batches($sOpenid, $nMoney)
{
// 付款到零钱方法url
$url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
// 订单号
$sOrderId = '测试付款' . time();
// 转账备注 (微信用户会收到该备注)
$tRemark = '测试付款' . $sOrderId;
// 转账金额:微信是分为单位 *100 转换
$transfer_amount = $nMoney * 100;
// 转账接收列表设置
$transfer_detail_list = array(
[
'out_detail_no' => $sOrderId, // 明细单号
'transfer_amount' => intval($transfer_amount), // 转账总金额
'transfer_remark' => $tRemark, // 单条转账备注
'openid' => $sOpenid, // 收款方openid
// 'user_name' => '张三',
// 转账金额 >= 2,000元,收款用户姓名必填
],
);
// 请求参数设置
$params = [ // 请求参数设置
'appid' => self::APPID, // 文档顶部定义
'out_batch_no' => $sOrderId, // 商家批次单号
'batch_name' => 'x年x月转账', // 转账的名称
'batch_remark' => 'x年x月转账', // 转账的备注
'total_amount' => intval($transfer_amount), // 转账总金额
'total_num' => 1, // 转账总笔数
'transfer_detail_list' => $transfer_detail_list, // 转账接收列表
];
// 获取token
$token = $this->getToken($params);
// 发送请求
$res = $this->https_request($url, json_encode($params), $token);
// 反馈数组化
$resArr = json_decode($res, true);
dump($resArr);
// 存储转账成功信息或别的操作
// 成功实例返回值
{
"out_batch_no": "plfk2020042013", // wx唯一识别号
"batch_id": "1030000071100999991182020050700019480001", // 商家批次单号
"create_time": "2015-05-20T13:29:35.120+08:00" // 创建时间
}
}
/**
* 构造请求
*/
function https_request($url, $data = null, $token)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, (string)$url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 添加请求头
$headers = [
'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $token,
'Accept: application/json',
'Content-Type: application/json; charset=utf-8',
'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
];
if (!empty($headers)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
/**
* 获取token
*/
public function getToken($pars)
{
$url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
$http_method = 'POST'; // 请求方法(GET,POST,PUT)
$timestamp = time(); // 请求时间戳
$url_parts = parse_url($url); // 获取请求的绝对URL
$nonce = $timestamp . rand('10000', '99999'); // 请求随机串
$body = json_encode((object)$pars); // 请求报文主体
$stream_opts = [
"ssl" => [
"verify_peer" => false,
"verify_peer_name" => false,
]
];
// 证书路径信息:文档顶部定义
$apiclient_cert_path = self::SSLCERT_PATH;
$apiclient_key_path = self::SSLKEY_PATH;
$apiclient_cert_arr = openssl_x509_parse(file_get_contents($apiclient_cert_path, false, stream_context_create($stream_opts)));
// 证书序列号
$serial_no = $apiclient_cert_arr['serialNumberHex'];
// 密钥
$mch_private_key = file_get_contents($apiclient_key_path, false, stream_context_create($stream_opts));
// 商户id:文档顶部定义
$merchant_id = self::MCHID;
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$message = $http_method . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
// 签名
$sign = base64_encode($raw_sign);
$schema = 'WECHATPAY2-SHA256-RSA2048';
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $merchant_id, $nonce, $timestamp, $serial_no, $sign);
// 微信返回token
return $token;
}
2.控制层
public function onTransferBatches($openid, $nMoney)
{
// 实例化服务层
$serviceTransfer = new serviceTransfer();
// 带参请求:sOpenid(收款方openid) nMoney(转账金额)
$result = $serviceTransfer->transfer_batches($openid, $nMoney);
return $result;
}