技术饭
PHP实现微信支付的现金红包、企业付款到零钱功能
copylian
0 评论
9610 浏览
2020.08.07
企业付款:
提供由商户直接付钱至用户微信零钱的能力,支持平台操作及接口调用两种方式。具有免费、快速到账、灵活、安全等优点。商户可以使用企业付款,用于如:费用报销、员工福利、用户奖励等。
微信红包:
2014年春节一推出即受到广大用户好评,引发全民抢红包热潮。现将微信红包打造成“现金红包”,作为一款定向资金发放的营销工具,供商户使用。用户在客户端领取到红包之后,所得金额进入微信钱包,可用于转账、支付或提取到银行卡。
官方文档:
企业付款到零钱:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
现金红包:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1
开通功能使用条件
商户号(或同主体其他非服务商商户号)已入驻90日商户号(或同主体其他非服务商商户号)有30天连续正常交易登录微信支付商户平台-产品中心,开通企业付款。具体的可以看微信支付开发文档
示例代码:
<?php /** * Author [ CopyLian ] * Date: [ 2018.11.10 ] * Email: [ copylian@aikehou.com ] * Site: [ https://www.copylian.com/ ] * Description: [ 企业付款到零钱、红包发送接口基类 ] */ namespace wechat; class WechatMmpaymk { //公众号APPID private $appid; //支付密钥签名 private $secret; //IP private $ip; //微信接口域名 private $api_url; //商户号 private $mchid; /** * [__construct 构造函数] */ public function __construct($prefix = '') { //前缀 $prefix = !empty($prefix) ? $prefix : ''; //初始化数据 $this->appid = config('wechatpay.' . $prefix . 'pay_account.appid'); $this->secret = config('wechatpay.' . $prefix . 'pay_account.secret'); $this->mchid = config('wechatpay.' . $prefix . 'pay_account.mchid'); $this->ip = config('wechatpay.' . $prefix . 'pay_account.ip'); $this->api_url = config('wechatpay.' . $prefix . 'pay_account.api_url'); } /** * [xmltoarray xml格式转换为数组] * @param [type] $xml [xml] * @return [type] [xml 转化为array] */ 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; } /** * [arraytoxml 将数组转换成xml格式(简单方法):] * @param [type] $data [数组] * @return [type] [array 转 xml] */ public function arraytoxml($data){ $str='<xml>'; foreach($data as $k=>$v) { $str.='<'.$k.'>'.$v.'</'.$k.'>'; } $str.='</xml>'; return $str; } /** * [createNoncestr 生成随机字符串] * @param integer $length [长度] * @return [type] [字母大小写加数字] */ 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; } /** * [curl_post_ssl 发送curl_post数据] * @param [type] $url [发送地址] * @param [type] $xmldata [发送文件格式] * @param [type] $second [设置执行最长秒数] * @param [type] $aHeader [设置头部] * @return [type] [description] */ function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()){ //证书位置 $isdir = __DIR__."/cert/"; //初始化curl $ch = curl_init(); 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; } } /** * [sendMoneyToChange 企业付款到零钱] * @param [type] $snedData [数据] */ public function sendMoneyToChange($snedData = []){ //总金额 if(empty($snedData) || !isset($snedData['order_sn']) || !isset($snedData['openid']) || !isset($snedData['amount']) || !isset($snedData['order_sn'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '参数异常'; return $rdata; } //数据 $data = array( 'mch_appid' => $this->appid,//商户账号appid 'mchid' => $this->mchid,//商户号 'nonce_str' => $this->createNoncestr(),//随机字符串 'partner_trade_no' => $snedData['order_sn'],//商户订单号 'openid' => $snedData['openid'],//用户openid 'check_name' => isset($snedData['check_name']) ? $snedData['check_name'] : 'NO_CHECK',//校验用户姓名选项, 're_user_name' => isset($snedData['re_user_name']) ? $snedData['re_user_name'] : '',//收款用户姓名 'amount' => $snedData['amount'],//金额 'desc' => $snedData['desc'],//企业付款描述信息 'spbill_create_ip' => $this->ip //Ip地址 ); //生成签名算法 $secrect_key = $this->secret;///这个就是个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->api_url . 'mmpaymkttransfers/promotion/transfers'; //调用接口 $res = $this->curl_post_ssl($url,$xml); $return = $this->xmltoarray($res); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '提交成功'; $rdata['data'] = $return; return $rdata; } /** * [queryChange 查询企业付款到零钱] * @param [type] $snedData [数据] */ public function queryChange($snedData = []){ //总金额 if(empty($snedData) || !isset($snedData['order_sn'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '参数异常'; return $rdata; } //数据 $data = array( 'appid' => $this->appid,//商户账号appid 'mch_id' => $this->mchid,//商户号 'nonce_str' => $this->createNoncestr(),//随机字符串 'partner_trade_no' => $snedData['order_sn']//商户订单号 ); //生成签名算法 $secrect_key = $this->secret;///这个就是个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->api_url . 'mmpaymkttransfers/gettransferinfo'; //调用接口 $res = $this->curl_post_ssl($url,$xml); $return = $this->xmltoarray($res); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '提交成功'; $rdata['data'] = $return; return $rdata; } /** * [redPacketPay 现金红包] * @param [type] $snedData [数据] */ public function redPacketPay($snedData = []){ //总金额 if(empty($snedData) || !isset($snedData['order_sn']) || !isset($snedData['openid']) || !isset($snedData['amount']) || !isset($snedData['order_sn'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '参数异常'; return $rdata; } //数据 $data = array( 'wxappid' => $this->appid,//商户账号appid 'mch_id' => $this->mchid,//商户号 'nonce_str' => $this->createNoncestr(),//随机字符串 'mch_billno' => $snedData['order_sn'],//商户订单号 're_openid' => $snedData['openid'],//用户openid 'act_name' => isset($snedData['act_name']) ? $snedData['act_name'] : '红包活动', //活动名称 'send_name' => isset($snedData['send_name']) ? $snedData['send_name'] : '多想互动',//红包发送者名称 'wishing' => isset($snedData['wishing']) ? $snedData['wishing'] : '恭喜发财', //红包祝福语 'remark' => isset($snedData['remark']) ? $snedData['remark'] : '抢到红包了,恭喜发财!', //备注 'total_num' => 1, //红包发放总人数 'total_amount' => $snedData['amount'],//金额 'client_ip' => $this->ip, //Ip地址 'scene_id' => 'PRODUCT_2' //场景id,发放红包使用场景,红包金额大于200或者小于1元时必传 PRODUCT_1:商品促销;PRODUCT_2:抽奖;PRODUCT_3:虚拟物品兑奖 ;PRODUCT_4:企业内部福利;PRODUCT_5:渠道分润;PRODUCT_6:保险回馈;PRODUCT_7:彩票派奖;PRODUCT_8:税务刮奖 ); //生成签名算法 $secrect_key = $this->secret;///这个就是个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->api_url . 'mmpaymkttransfers/sendredpack'; //调用接口 $res = $this->curl_post_ssl($url,$xml); $return = $this->xmltoarray($res); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '提交成功'; $rdata['data'] = $return; return $rdata; } /** * [queryRedPacket 查询现金红包] * @param [type] $snedData [数据] */ public function queryRedPacket($snedData = []){ //总金额 if(empty($snedData) || !isset($snedData['order_sn'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '参数异常'; return $rdata; } //数据 $data = array( 'appid' => $this->appid,//商户账号appid 'mch_id' => $this->mchid,//商户号 'nonce_str' => $this->createNoncestr(),//随机字符串 'mch_billno' => $snedData['order_sn'], //商户订单号 'bill_type' => 'MCHT', //MCHT:通过商户订单号获取红包信息。 ); //生成签名算法 $secrect_key = $this->secret;///这个就是个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->api_url . 'mmpaymkttransfers/gethbinfo'; //调用接口 $res = $this->curl_post_ssl($url,$xml); $return = $this->xmltoarray($res); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '提交成功'; $rdata['data'] = $return; return $rdata; } }
<?php /** * Author: [ CopyLian ] * Date: [ 2017.02.23 ] * Email: [ copylian@aikehou.com ] * Site: [ http://www.copylian.com ] * Description [ 测试接口控制器 ] */ namespace app\wechat\controller; use wechat\Wechat; use wechat\WechatAuth; class Test extends Base{ //授权公众号前缀 //private $prefix_account = 'many_'; //正式机 private $prefix_account = ''; //测试机 /** * [initialize 初始化] */ public function initialize(){ parent::initialize(); } /** * [auth 测试第三方平台授权] */ public function getauth(){ if($this->request->isPost()){ //获取参数 $params = $this->request->param(); //验证地址 if(!isset($params['back_url']) || empty($params['back_url'])){ $rdata['code'] = 0; $rdata['msg'] = lang('l_back_url_error'); return $rdata; } //平台ID $platform_id = 2; //平台ID $state = 'test'; //重定向后会带上 state 参数、平台活动名称 //$scope = 'snsapi_userinfo'; //授权作用域:snsapi_userinfo、snsapi_base $scope = 'snsapi_base'; //授权作用域:snsapi_userinfo、snsapi_base $back_url = $params['back_url']; //重定向URL $code = isset($params['code']) ? $params['code'] : ''; //执行第三方的授权 $Thirdplatform = new \app\wechat\controller\Thirdplatform(); $data = $Thirdplatform->agent_thirdplatform_auth($platform_id, $state, $back_url, $scope, $code); return $data; } } /** * [getSign 测试第三方平台获取微信签名包] */ public function getSign() { //获取参数 $params = $this->request->param(); //跨域 if(isset($params['url'])){ $url = $params['url']; } else{ $url = 'https://h5test.ponyfamily.cn/wechat/index.html'; } //设置分享数据缓存 $cache_name = md5($url); $share_data = cache($cache_name); if(empty($share_data)){ //平台ID $platform_id = 2; //平台ID $code = isset($params['code']) ? $params['code'] : ''; //执行第三方的授权 $Thirdplatform = new \app\wechat\controller\Thirdplatform(); $share_data = $Thirdplatform->getSignPackage($platform_id, $url); //设置缓存 cache($cache_name, $share_data, 7200); } //微信签名包 $data['code'] = 1; $data['msg'] = lang('l_get_data_success'); $data['data'] = $share_data; return json($data); } /** * [changePay 企业付款到零钱] */ public function changePay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'amount' => 60, //单位分 'openid' => 'oHL30wVEuI58Lgp8dkQmSSW4dU4g', 'order_sn' => create_order_sn(1, "qylq"), 'desc' => '企业付款到零钱', 'check_name' => 'NO_CHECK', //NO_CHECK:不校验真实姓名、FORCE_CHECK:强校验真实姓名 're_user_name' => '', //收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名 ]; //返回结果 $res = $WechatMmpaymk->sendMoneyToChange($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [queryChangePay 查询企业付款到零钱] */ public function queryChangePay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'order_sn' => 'qylq00807115204001340' ]; //返回结果 $res = $WechatMmpaymk->queryChange($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '查询成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [redPacketPay 发送红包] */ public function redPacketPay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'amount' => 30, //单位分 'openid' => 'oHL30wVEuI58Lgp8dkQmSSW4dU4g', 'order_sn' => create_order_sn(1, "qylq") ]; //返回结果 $res = $WechatMmpaymk->redPacketPay($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [queryRedPacket 查询现金红包] */ public function queryRedPacket() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'order_sn' => 'qylq00807151840001406' ]; //返回结果 $res = $WechatMmpaymk->queryRedPacket($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '查询成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } }
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!
文明上网理性发言!