PHP实现微信开发中提现功能(企业付款到用户零钱)
一.实现该功能目的
这几天在小程序里要实现用户从系统中提现到零钱的功能,查了一下文档可以使用 企业付款到用户零钱 来实现;
官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1;
注意事项:商户打款时是从商户可用余额中减钱,所以确保商户可用余额充足,同时注意官方文档中的付款规则;
二.PHP实现
//封装提现方法
function tixian($money){
$appid = "################";//商户账号appid
$secret = "##########";//api密码
$mch_id = "#######";//商户号
$mch_no = "#######";
$openid="123456789";//授权用户openid $arr = array();
$arr['mch_appid'] = $appid;
$arr['mchid'] = $mch_id;
$arr['nonce_str'] = ugv::randomid(20);//随机字符串,不长于32位
$arr['partner_trade_no'] = '1298016501' . date("Ymd") . rand(10000, 90000) . rand(10000, 90000);//商户订单号
$arr['openid'] = $openid;
$arr['check_name'] = 'NO_CHECK';//是否验证用户真实姓名,这里不验证
$arr['amount'] = $money;//付款金额,单位为分
$desc = "###提现";
$arr['desc'] = $desc;//描述信息
$arr['spbill_create_ip'] = '192.168.0.1';//获取服务器的ip
//封装的关于签名的算法
$notify = new Notify_pub();
$notify->weixin_app_config = array();
$notify->weixin_app_config['KEY'] = $mch_no; $arr['sign'] = $notify->getSign($arr);//签名 $var = $notify->arrayToXml($arr);
$xml = $this->curl_post_ssl('https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers', $var, 30, array(), 1);
$rdata = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$return_code = (string)$rdata->return_code;
$result_code = (string)$rdata->result_code;
$return_code = trim(strtoupper($return_code));
$result_code = trim(strtoupper($result_code)); if ($return_code == 'SUCCESS' && $result_code == 'SUCCESS') {
$isrr = array(
'con'=>'ok',
'error' => 0,
);
} else {
$returnmsg = (string)$rdata->return_msg;
$isrr = array(
'error' => 1,
'errmsg' => $returnmsg,
); }
return json_encode($isrr);
}
//上个方法中用到的curl_post_ssl()
function curl_post_ssl($url, $vars, $second = 30, $aHeader = array())
{
$isdir = "/cert/";//证书位置 $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_SSLCERTTYPE, 'PEM');//证书类型
curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.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;
}
}
三.补充
关于具体签名算法,可参考微信官方文档;
简单示范签名算法:
//将要发送的数据整理为$data ksort($data);//排序
//使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串
$str='';
foreach($data as $k=>$v) {
$str.=$k.'='.$v.'&';
}
//拼接API密钥
$str.='key='.$secrect;
$data['sign']=md5($str);//加密
将数组转换成xml格式(简单方法):
//遍历数组方法
function arraytoxml($data){
$str='<xml>';
foreach($data as $k=>$v) {
$str.='<'.$k.'>'.$v.'</'.$k.'>';
}
$str.='</xml>';
return $str;
}
将xml格式转换为数组:
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;
}
PHP微信商户支付企业付款到零钱功能
这几天在给客户做一个微信现金红包功能,需要用到微信支付的企业付款到零钱功能。
微信支付企业付款到零钱功能应用广泛,比如微信红包奖励,业务结算等。通过企业向个人付款,付款资金将直接进入用户微信零钱。
一 开通条件
付款资金
企业付款到零钱资金使用商户号余额资金。
根据商户号的账户开通情况,实际出款账户有做区别:
◆ 默认情况下,企业付款到零钱使用商户号基本户(或余额账户)余额。如商户号已开通运营账户,则企业付款到零钱使用运营账户内的资金。
◆ 基本户(或上述其他出款账户)的资金来源,可能是交易结算款项(仅基本户),或给账户充值的资金。当出款账户余额不足时,付款将因余额不足而付款失败。
付款规则
付款方式
◆ 支持API接口或网页操作,付款至目标用户。
收款用户身份指定
◆ 通过APPID+OPENID指定收款用户。
◆ APPID需要为申请商户号时的APPID,或者与商户号有绑定关系。
◆ OPENID的获取方式,可参照:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
付款额度
◆ 不支持给非实名用户打款
◆ 给同一个实名用户付款,单笔单日限额2W/2W
◆ 一个商户同一日付款总额限额100W
注意:以上规则中的限额2w、100w由于计算规则与风控策略的关系,不是完全精确值,金额仅做参考,请不要依赖此金额做系统处理,应以接口实际返回和查询结果为准,请知晓。
收款用户身份校验
◆ 针对付款的目标用户,提供可校验真实姓名的功能
查询付款情况
◆ 已付款的记录,企业可通过企业付款查询查看相应数据,或者查询商户号资金流水。
付款频次
◆ 默认每天最多可向同一个用户付款10次,可以在商户平台--API安全进行设置
其他注意事项
◆ 付款金额必须小于或等于商户当前可用余额的金额;
二 接口地址
接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
请求参数:
具体参看官方企业付款开发文档说明
PHP代码示例调用
<?php
//企业付款到微信零钱,PHP接口调用方法
define("APPID", "wxde3234454354"); // 商户账号appid
define("MCHID", "1900000109"); // 商户号
define("SECRECT_KEY", "145535866885"); //支付密钥签名
define("IP", "120.178.12.52"); //IP
function createNoncestr($length =32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
function unicode() {
$str = uniqid(mt_rand(),1);
$str=sha1($str);
return md5($str);
}
function arraytoxml($data){
$str='<xml>';
foreach($data as $k=>$v) {
$str.='<'.$k.'>'.$v.'</'.$k.'>';
}
$str.='</xml>';
return $str;
}
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;
}
function curl($param="",$url) {
$postUrl = $url;
$curlPost = $param;
$ch = curl_init(); //初始化curl
curl_setopt($ch, CURLOPT_URL,$postUrl); //抓取指定网页
curl_setopt($ch, CURLOPT_HEADER, 0); //设置header
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_POST, 1); //post提交方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost); // 增加 HTTP Header(头)里的字段
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // 终止从服务端进行验证
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch,CURLOPT_SSLCERT,ROOT_PATH .'/wxpay/cacert/apiclient_cert.pem'); //这个是证书的位置绝对路径
curl_setopt($ch,CURLOPT_SSLKEY,ROOT_PATH .'/wxpay/cacert/apiclient_key.pem'); //这个也是证书的位置绝对路径
$data = curl_exec($ch); //运行curl
curl_close($ch);
return $data;
}
/*
$amount 发送的金额(分)目前发送金额不能少于1元
$re_openid, 发送人的 openid
$desc // 企业付款描述信息 (必填)
$check_name 收款用户姓名 (选填)
*/
function sendMoney($amount,$re_openid,$desc='测试',$check_name=''){
$total_amount = (100) * $amount;
$data=array(
'mch_appid'=>APPID,//商户账号appid
'mchid'=> MCHID,//商户号
'nonce_str'=>createNoncestr(),//随机字符串
'partner_trade_no'=> date('YmdHis').rand(1000, 9999),//商户订单号
'openid'=> $re_openid,//用户openid
'check_name'=>'NO_CHECK',//校验用户姓名选项,
're_user_name'=> $check_name,//收款用户姓名
'amount'=>$total_amount,//金额
'desc'=> $desc,//企业付款描述信息
'spbill_create_ip'=> IP,//Ip地址
);
$secrect_key=SECRECT_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=arraytoxml($data);
$url='https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //调用接口
$res=curl($xml,$url);
$return=xmltoarray($res);
print_r($return);
//返回来的结果
// [return_code] => SUCCESS [return_msg] => Array ( ) [mch_appid] => wxd44b890e61f72c63 [mchid] => 1493475512 [nonce_str] => 616615516 [result_code] => SUCCESS [partner_trade_no] => 20186505080216815
// [payment_no] => 1000018361251805057502564679 [payment_time] => 2018-05-15 15:29:50
$responseObj = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
echo $res= $responseObj->return_code; //SUCCESS 如果返回来SUCCESS,则发生成功,处理自己的逻辑
return $res;
}
?>
三 调用方法 :
sendMoney(1,'ewrwexe32423423423423423','xxxx测试');
注释 :调用的话,稍微在修改下,加上自己的业务逻辑就行了。
调用效果:
注释 :调用的话,稍微在修改下,加上自己的业务逻辑就行了。
---------------------
作者:Json2008
来源:CSDN
原文:https://blog.csdn.net/fengqingtao2008/article/details/80244182
版权声明:本文为博主原创文章,转载请附上博文链接!
浅析微信支付:(余额提现)企业付款到微信用户零钱或银行卡账户
浅析微信支付系列已经更新十二篇了哟~,没有看过的朋友们可以看一下哦。
如果你是做电商或者某些有福利返利的系统,基本上会遇到诸如 余额提现
这类需求,主要就是平台向用户返利现金,积累到某一个门槛,可以领取到自己的余额账号、银行卡;或者是使用为用户发送现金红包的方式。
接下来的两篇文章,会为大家描述在微信支付中,像用户付款的以上三种方式。
以下为三种付款方式的必要条件:
- 商户号(或同主体其他非服务商商户号)已入驻90日
- 商户号(或同主体其他非服务商商户号)有30天连续正常交易
- 登录微信支付商户平台-产品中心,开通企业付款。
企业付款到微信用户零钱
企业付款提供由商户直接付钱至用户微信零钱的能力,支持平台操作及接口调用两种方式,资金到账速度快,使用及查询方便。主要用来解决合理的商户对用户付款需求,比如:保险理赔、彩票兑换等等。
如何开通?
- 入驻成为商户:在线提交营业执照、身份证、银行账户等基本信息,快速提交申请;
- 超级管理员开通:前往商户平台-产品中心-企业付款到零钱-申请开通;
- 特殊要求:交易资金是即时入账到商户号基本户的商户,需要满足以下要求:需入驻满90天,连续交易30天。
所需资料:开通企业付款到零钱功能无需提供额外的材料。
费用:试用期间免费使用。
应用场景
企业付款为企业提供付款至用户零钱的能力,支持通过API接口付款,或通过微信支付商户平台(pay.weixin.qq.com)网页操作付款。
以下为官方的解释:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
抓重点,首先需要知道的是,开通了运营账户
的商户,付款时会从运营账户余额中扣除,这个一定要注意,以免金额不足时付款失败(可以使用主账户为运营账户充值,参考[交易中心]-[充值/转入])。
以下为特别需要注意的地方,为大家标记出来,设计系统时一定要参考一下,以免入坑。
接口链接
https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
是否需要证书
请求需要双向证书。
调用接口
注意事项:
◆ 当返回错误码为“SYSTEMERROR”时,请不要更换商户订单号,一定要使用原商户订单号重试,否则可能造成重复支付等资金风险。
◆ XML具有可扩展性,因此返回参数可能会有新增,而且顺序可能不完全遵循此文档规范,如果在解析回包的时候发生错误,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新回包字段,会更新到此API文档中。
◆ 因为错误代码字段err_code的值后续可能会增加,所以商户如果遇到回包返回新的错误码,请商户务必不要换单重试,请商户联系客服确认付款情况。如果有新的错误码,会更新到此API文档中。
◆ 错误代码描述字段err_code_des只供人工定位问题时做参考,系统实现时请不要依赖这个字段来做自动化处理。
PS:目前支持向指定微信用户的openid付款。
官方文档如下:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
具体的传入参数,这里就不一一列举了,请大家参考一下官方文档,下面贴上具体的实现源码:
/**
* [微信支付提现接口] - 保存调用的相关记录
* @param payment 支付对象
* @param wxPayConfig 微信支付单例对象
* @return map
*
* @author yclimb
* @date 2018/7/30
*/
public Map<String, String> saveWxPayTransfers(Payment payment, WXPayConfig wxPayConfig) throws Exception {
// 支付前验证
// 微信支付对象
// WXPay wxPay = new WXPay(WXPayConfigImpl.getInstance());
WXPay wxPay = new WXPay(wxPayConfig);
// 微信退款接口
Map<String, String> resultMap = wxPay.transfers(...);
logger.info("saveWxPayTransfers:resultMap:" + resultMap.toString());
// 下单失败,进行处理
if (WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RETURN_CODE)) || WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RESULT_CODE))) {
// 处理结果返回,无需继续执行
// 余额不足提醒
if (WXPayCodeEnum.ERR_CODE_NOTENOUGH.getCode().equals(resultMap.get(WXPayConstants.ERR_CODE))) {
// 发送余额不足的消息提醒
}
}
// 付款记录修改 & 记录付款日志
return resultMap;
}
以上为调用的应用方法,下面为大家贴出微信接口调用代码 imall.weixin.sdk.WXPay
:
/**
* 作用:企业向微信用户个人付款<br>
* 场景:企业付款为企业提供付款至用户零钱的能力,支持通过API接口付款,或通过微信支付商户平台(pay.weixin.qq.com)网页操作付款。
* 接口文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
*
* @param partner_trade_no 商户订单号
* @param openid 用户openid
* @param amount 企业付款金额
* @param desc 企业付款描述信息
* @param spbill_create_ip 该IP可传用户端或者服务端的IP
* @return API返回数据
* @throws Exception e
*/
public Map<String, String> transfers(String partner_trade_no, String openid, String amount, String desc, String spbill_create_ip) throws Exception {
/** 构造请求参数数据 **/
Map<String, String> data = new HashMap<>();
// 商户订单号 partner_trade_no 是 10000098201411111234567890 String 商户订单号,需保持唯一性(只能是字母或者数字,不能包含有符号)
data.put("partner_trade_no", partner_trade_no);
// 用户openid openid 是 oxTWIuGaIt6gTKsQRLau2M0yL16E String 商户appid下,某用户的openid
data.put("openid", openid);
// 校验用户姓名选项 check_name 是 FORCE_CHECK String NO_CHECK:不校验真实姓名,FORCE_CHECK:强校验真实姓名
data.put("check_name", "NO_CHECK");
// 金额 amount 是 10099 int 企业付款金额,单位为分
data.put("amount", String.valueOf(new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue()));
// 企业付款描述信息 desc 是 理赔 String 企业付款操作说明信息。必填。
data.put("desc", desc);
// Ip地址 spbill_create_ip 是 192.168.0.1 String(32) 该IP同在商户平台设置的IP白名单中的IP没有关联,该IP可传用户端或者服务端的IP。
data.put("spbill_create_ip", spbill_create_ip);
/** 以下参数为非必填参数 **/
/*// 设备号 device_info 否 013467007045764 String(32) 微信支付分配的终端设备号
data.put("device_info", "xxx");
// 收款用户姓名 re_user_name 可选 王小王 String 收款用户真实姓名。(如果check_name设置为FORCE_CHECK,则必填用户真实姓名)
data.put("re_user_name", "xxx");*/
// 微信调用接口
Map<String, String> resultMap = this.transfers(data);
WXPayUtil.getLogger().info("wxPay.transfers:" + resultMap);
return resultMap;
}
PS:推荐数据库中对于金额存储为数值单位,以分为单位来存储,1.1元可以储存为101,这样和微信对应,会方便很多。
对于企业付款查询的接口,这里就不详细描述了,以下为具体的官方文档链接:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
需要的朋友,根据文档进行接口查询即可,非高频接口。
企业付款到银行卡
企业付款到银行卡提供由商户直接付钱至指定银行卡账户的能力,支持平台操作及接口调用两种方式,资金到账速度快,使用及查询方便。主要用来解决合理的商户对用户付款需求,比如:保险理赔、彩票兑换等等。
开通流程:
- 入驻成为商户:在线提交营业执照、身份证、银行账户等基本信息,快速提交申请;
- 超级管理员开通:前往商户平台-产品中心-企业付款到银行卡-申请开通;
- 特殊要求:交易资金是即时入账到商户号基本户的商户,需要满足以下要求:需入驻满90天,连续交易30天。
所需资料:开通企业付款到银行卡功能无需提供额外的材料。
费用:此功能需收取手续费,按照单笔金额收取,每笔收取0.1%,最低1元,最高25元。
应用场景
微信支付已上线企业付款至银行卡功能。商户可以将商户号余额付款至指定的收款银行账户。通过指定收款银行账户户名、卡号,以及收款银行信息即可实现付款。
官方文档地址:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_1&index=1
功能说明:
- 企业付款至银行卡只支持新资金流类型账户
- 目前企业付款到银行卡支持17家银行,更多银行逐步开放中
- 付款到账实效为1-3日,最快次日到账
- 每笔按付款金额收取手续费,按金额0.1%收取,最低1元,最高25元,如果商户开通了运营账户,手续费和付款的金额都从运营账户出。如果没有开通,则都从基本户出。
- 每个商户号每天可以出款100万,单商户给同一银行卡付款每天限额5万
- 发票:在账户中心-发票信息页面申请开票的商户会按月收到发票(已申请的无需重复申请)。
企业付款到银行卡发票与交易手续费发票为拆分单独开具。
需要注意的是,微信支持的银行有限,具体的支持银行见如下链接:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_4&index=5
所以肯定会出现不支持的银行,小伙伴们在开发的时候,可以在前后端控制用户选择提现银行来解决。
平台上手动付款流程:
- 在产品中心,开通企业付款到个人银行卡功能
- 进入交易中心-企业付款到银行卡页面进行付款
- 指定收款银行账号、户名、收款方开户行,及付款金额信息,即可实现付款
接口链接
https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
是否需要证书
请求需要双向证书。
调用接口
接口介绍:
用于企业向微信用户银行卡付款
目前支持接口API的方式向指定微信用户的银行卡付款。
接口调用规则:
◆ 单商户日限额——单日100w
◆ 单次限额——单次5w
◆ 单商户给同一银行卡单日限额——单日5w
注意:重点来了,首先,收款方银行卡号enc_bank_no
、收款方用户名enc_true_name
这两个入参是需要 采用标准RSA算法,公钥由微信侧提供
得到的,所以还需要先拿到这个密钥,下面是官方文档地址:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
以上文档详细介绍了如何得到具体的密钥方式,如果有看不明白的小伙伴,可以直接百度 获取RSA加密公钥API
,可以得到很多示例,这里我就不讲了。
除入参和企业付款到微信用户零钱
有所不一致之外,其他方面都差不多,小伙伴们可以参考上面付款到零钱的接口来实现付款到银行卡接口。
结语
以上为微信余额提现
相关的解释和源码,小伙伴们一定要注意看看官方文档哦,具体的源码可以看作者的github,里面对每个方法有详细的注释。
如果小伙伴有遇到解决不了的问题,可以关注作者微信公众号,加入讨论群中发出疑问,和小伙伴们一起解决哦~
预告:下一篇文章会讲发放奖励的另一种方式 商户平台-现金红包
,敬请期待!!!
如果想要提前一览源码的小伙伴,可以先看看我的 github,地址如下:
https://github.com/YClimb/wxpay-sdk/blob/master/README.md