这次我们老老实实,一行一行的看文档,官方链接: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
场景介绍
整个限制条件主要包含: 对方必须在微信实名认证,每个人每天只能最多只能收款10次,请求30次/s.具体可以前往产品设置了解
付款流程,就不继续贴官方图了,直接上代码
a. 为了方便,还是新建个基类,payToUser.php
<?php
namespace app\api\controller;
use think\Controller;
class payToUser extends Controller{
protected $appid = '你的商户appid'; // 商户账号appid
protected $mch_id = '你的商户号'; // 商户号
protected $key = '你的秘钥'; //支付密钥签名
protected $sendUrl = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //付款地址
protected $searchUrl = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo'; //查询地址
/**
* xml转数组
* @param $xml
* @return mixed
*/
public function xmltoarray($xml) {
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring),true);
return $val;
}
/**
* 数组转xml
* @param $data
* @return string
*/
public function arraytoxml($data){
$str='<xml>';
foreach($data as $k=>$v) {
$str.='<'.$k.'>'.$v.'</'.$k.'>';
}
$str.='</xml>';
return $str;
}
/**
* 生成随机数
* @param int $length
* @return string
*/
public function createNoncestr($length =32){
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for($i=0;$i<$length;$i++){
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
/**
* 发送post请求
* @param $url
* @param $vars
* @param int $second
* @param array $aHeader
* @return bool|string
*/
function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()){
$ch = curl_init();//初始化curl
curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置执行最长秒数
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_URL, $url);//抓取指定网页
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//
//证书的位置
curl_setopt($ch, CURLOPT_SSLCERT, '你的证书地址/apiclient_cert.pem');
//证书key的位置
curl_setopt($ch, CURLOPT_SSLKEY, '你的证书地址/apiclient_key.pem');
if (count($aHeader) >= 1) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部
}
curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);//全部数据使用HTTP协议中的"POST"操作来发送
$data = curl_exec($ch);//执行回话
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
echo "call faild, errorCode:$error\n";
curl_close($ch);
return false;
}
}
/**
* 付款到零钱
* @param $amount
* @param $re_openid
* @param string $desc
* @param $partner_trade_no
* @param string $check_name
* @return mixed
*/
public function sendMoney($amount,$re_openid,$desc='奖励',$partner_trade_no,$check_name=''){
$total_amount = $amount;
$data=array(
'mch_appid'=>$this->appid,//商户账号appid
'mchid'=> $this->mch_id,//商户号
'nonce_str'=>$this->createNoncestr(),//随机字符串
'partner_trade_no'=> $partner_trade_no,//商户订单号
'openid'=> $re_openid,//用户openid
'check_name'=>'NO_CHECK',//校验用户姓名选项,
're_user_name'=> $check_name,//收款用户姓名
'amount'=>$total_amount,//金额,单位为分
'desc'=> $desc,//企业付款描述信息
'spbill_create_ip'=> '',//Ip地址
);
//生成签名算法
$secrect_key=$this->key;///这个就是个API密码。MD5 32位。
$data=array_filter($data);
ksort($data);
$str='';
foreach($data as $k=>$v) {
$str.=$k.'='.$v.'&';
}
$str.='key='.$secrect_key;
$data['sign']=md5($str);
//生成签名算法
$xml=$this->arraytoxml($data);
$url=$this->sendUrl; //调用接口
$res=$this->curl_post_ssl($url,$xml);
$return=$this->xmltoarray($res);
return $return;
}
/**
* 查询付款状态
* @param string $partner_trade_no
* @return mixed
*/
public function searchMoney($partner_trade_no=''){
$data=array(
'appid'=>$this->appid,//商户账号appid
'mch_id'=> $this->mch_id,//商户号
'nonce_str'=>$this->createNoncestr(),//随机字符串
'partner_trade_no'=> $partner_trade_no,//商户订单号
);
//生成签名算法
$secrect_key=$this->key;///这个就是个API密码。MD5 32位。
$data=array_filter($data);
ksort($data);
$str='';
foreach($data as $k=>$v) {
$str.=$k.'='.$v.'&';
}
$str.='key='.$secrect_key;
$data['sign']=md5($str);
//生成签名算法
$xml=$this->arraytoxml($data);
$url=$this->searchUrl; //调用接口
$res=$this->curl_post_ssl($url,$xml);
$return=$this->xmltoarray($res);
return $return;
}
}
b. 在控制器调用,测试
/**
* @param int $amount 转账金额
* @param string $partner_trade_no 订单号
*/
public function test($amount=0,$partner_trade_no=''){
$pay = new PayToUser();
if($partner_trade_no){ //有订单号则为查询
print_r($pay->searchMoney($partner_trade_no));
}else{ //无订单号为付款
print_r($pay->sendMoney($amount,$this->auth->openid,$desc='测试',$check_name=''));
}
}
查询付款结果
基本都是复制粘贴的事情了,重点提示,产品设置一定记得修改,不改也点进去看看,不然有时会错得莫名其妙.比如余额不足,用户领取金额上限,用户领取次数上限.还有疑问,欢迎留言