由于公司之前开发了打赏及支付功能,因此用户的钱需要提现出来,支持微信和支付宝两个渠道, 今天就针对微信的提现整理下代码。
微信商户平台开通
微信使用的是企业付款接口,第一步当然是用公司账户申请商户账户了,这个简单就不说了,不过有个提醒
-
开通条件: 1、商户号已入驻90日 2、商户号有30天连续正常交易
开通后需要登录微信支付商户平台,通过网页充值功能充值(商户平台-交易中心)。
获取用户的 openid
通过API或网页操作,付款至目标用户(企业可根据APPID+OpenID锁定目标用户)。针对已实名认证的用户,微信支付可提供校验真实姓名一致性的可选功能。
这个APP 端调用开放平台,网页端调用公众号接口来获取,就不细说了。
温馨提示:
◆ 给同一个实名用户付款,单笔单日限额2W/2W
◆ 不支持给非实名用户打款
◆ 一个商户同一日付款总额限额100W
◆ 仅支持商户号已绑定的APPID;
◆ 针对付款的目标用户,已微信支付实名认证的用户可提供校验真实姓名的功能,未实名认证的用户无法校验,企业可根据自身业务的安全级别选择验证类型;
◆ 付款金额必须小于或等于商户当前可用余额的金额;
◆ 已付款的记录,企业可通过企业付款查询查看相应数据。
调用付款接口
// 文档地址 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
// 这里代码是基于微信文档直接写的,如果图方便可以参考别人写好的包,比如 https://helei112g.github.io/2016/08/16/PHP%E6%8E%A5%E5%85%A5%E5%BE%AE%E4%BF%A1%E4%BC%81%E4%B8%9A%E4%BB%98%E6%AC%BE%E5%8A%9F%E8%83%BD/
// type=0 app 端付款 type=1 网页端付款 本代码实例基于 laravel 框架,需要根据自身代码结构更改
function pay($order_id,$openid,$money,$desc,$type=0){
if ($type == 1) {
$appid = config('appwxpay.appid');// 应用 id
$mchid = config('appwxpay.mchid');// 商户 id
$appkey = config('appwxpay.key');//key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
$cert_path = config('transfer.appsslcert_path');//登录商户平台下载 PHP开发环境请使用商户证书文件apiclient_cert.pem和apiclient_key.pem ,rootca.pem是CA证书
$key_path = config('transfer.appsslkey_path');//需要注意证书会过期,可以设置自动更新
} else if ($type == 2) {
$appid = config('wxpay.appid');
$mchid = config('wxpay.mchid');
$appkey = config('wxpay.key');
$cert_path = config('transfer.wapsslcert_path');
$key_path = config('transfer.wapsslkey_path');
}
$arr = [
'mch_appid'=>$appid,
'mchid'=>$mchid,
'nonce_str'=>str_random(32),
'partner_trade_no'=>$order_id,//订单号 根据自己项目生成
'openid'=>$openid,//用户的 openid APP 和网页端 的不一样
'check_name'=>'NO_CHECK',
'amount'=>$money*100,//单位是分
'desc'=>$desc,
'spbill_create_ip'=>\Request::getClientIp(),
'sign'=>'',
];
ksort($arr);
$sign="";
foreach ($arr as $key => $value) {
if($value && $key!="sign" && $key!="key"){
$sign.=$key."=".$value."&";
}
}
$sign.="key=".$appkey;
$arr['sign'] = strtoupper(md5($sign));// 生成签名
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val))
{
$xml.="<".$key.">".$val."</".$key.">";
}
else
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml.="</xml>";
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,6);
curl_setopt($ch,CURLOPT_URL,'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers');
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
//默认格式为PEM
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT,$cert_path);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,$key_path);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
$data = curl_exec($ch);
$data = json_decode(json_encode(simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
curl_close($ch);
return $data;
}
$data = pay(888888,'dsfdsrefdfd', 100, 'pay');
if($data['return_code'] == 'SYSTEMERROR'){
pay(888888,'dsfdsrefdfd', 100, 'pay');//当返回错误码为“SYSTEMERROR”时,一定要使用原单号重试,否则可能造成重复支付等资金风险。
return;
}
if($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
todo();//提现成功 更新用户的订单和扣余额
}
到账
付款成功后直接支付到个人微信的钱包里
查询订单信息
// 文档地址 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
function query(){
// 具体代码就不写了,参考上面的支付接口
}