微信支付 “商家转账到零钱”

这里有个坑

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;
 }

 

作者:家里有猫原文地址:https://www.cnblogs.com/simpe/p/16949847.html

%s 个评论

要回复文章请先登录注册