PHP实现微信提现功能(微信商城)

吾爱主题 阅读:120 2021-09-17 12:13:00 评论:0

提现必须得用双向证书、所以大家一定要在微信的商户平台找到相应的地方去设置、因为做这个提现已经有一段时间了、所以设置微信商户平台的那几个地方没有图的情况、也说不清楚、下次再做提现的时候、给大家分享如何设置商户平台那几个地方、不是很难、下面贴代码

注意事项:商户打款时是从商户可用余额中减钱,所以确保商户可用余额充足,同时注意官方文档中的付款规则;

封装提现的方法

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 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()

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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;    } }

关于具体签名算法,可参考微信官方文档;

简单示范签名算法:

?
1 2 3 4 5 6 7 8 9 10 //将要发送的数据整理为$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格式(简单方法):

?
1 2 3 4 5 6 7 8 9 //遍历数组方法 function arraytoxml( $data ){   $str = '<xml>' ;   foreach ( $data as $k => $v ) {    $str .= '<' . $k . '>' . $v . '</' . $k . '>' ;   }   $str .= '</xml>' ;   return $str ; }

将xml格式转换为数组:

?
1 2 3 4 5 6 7 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 ; }

下面来看看ThinkPHP5封装的提现类。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 <?php namespace Home\Controller; use Think\Controller; class TixianController extends Controller{   //高级功能-》开发者模式-》获取   private $app_id1 = '' //appid   private $app_secret1 = '' ; //secreat   private $apikey1 = '' ; //支付秘钥   private $mchid1 = 's' //商户号    private $app_id =null;    private $app_secret =null;    private $apikey =null;    private $mchid =null;   public $error =0;   public $state = '' ;   //金额,需在实例化时传入   public $amount = '0' ;   //用户订单号,需在实例化时传入   public $order_sn = '' ;   //用户openid,需在实例化时传入   public $openid = '' ;   //微信提现操作接口-------》   public function actionAct_tixian()   {    $this ->state=md5(uniqid(rand(), TRUE));    $this ->amount=I( 'amount' ); //设置POST过来钱数    $this ->order_sn=rand(100,999). date ( 'YmdHis' ); //随机数可以作为单号    $this ->openid= I( 'openid' ); //设置获取POST过来用户的OPENID    $user_id = I( 'user_id' );    $this ->app_id= $this ->app_id1;    $this ->app_secret= $this ->app_secret1;    $this ->apikey= $this ->apikey1;    $this ->mchid= $this ->mchid1;    $xml = $this ->tiXianAction();    $result =simplexml_load_string( $xml );    if ( $result ->return_code== 'SUCCESS' && $result ->result_code== 'SUCCESS' ) {      $cash = D( 'cash' );      $data [ 'user_id' ] = $user_id ;      $data [ 'amount' ] = $this ->amount;      $res = $cash ->where( 'user_id="' . $user_id . '"' )->find();      if ( $res ){       $res2 = $cash ->where( 'user_id="' . $user_id . '"' )->setInc( 'amount' , $this ->amount);       $res4 = D( 'member' )->where( 'user_id="' . $user_id . '"' )->setDec( 'user_balance' , $this ->amount);      } else {       $res3 = $cash ->add( $data );      }     $output = array ( 'code' => 1, 'data' => $result ->result_code, 'info' => '提现成功' );     exit (json_encode( $output ));    } else {     $output = array ( 'code' => 2, 'data' => $xml , 'info' => '提现失败' );     exit (json_encode( $output ));    }   }   /**   * 提现接口操作,控制器调用   * @param $openid 用户openid 唯一标示   * @return   */   //提现接口操作   public function tiXianAction(){    //获取xml数据    $data = $this ->getdataXml( $this ->openid);    $ch = curl_init ();    //接口地址    $MENU_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers" ;    curl_setopt ( $ch , CURLOPT_URL, $MENU_URL );    curl_setopt ( $ch , CURLOPT_CUSTOMREQUEST, "POST" );    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, 'C:\web\www\Home\wx_pay\apiclient_cert.pem' ); //证书这块大家把文件放到哪都行、    curl_setopt( $ch ,CURLOPT_SSLKEYTYPE, 'PEM' );    curl_setopt( $ch ,CURLOPT_SSLKEY, 'C:\web\www\Home\wx_pay\apiclient_key.pem' ); //注意证书名字千万别写错、    //$zs1=dirname(dirname(__FILE__)).'\wx_pay\apiclient_cert.pem';    //$zs2=dirname(dirname(__FILE__)).'\wx_pay\apiclient_key.pem';    //show_bug($zs1);    //curl_setopt($ch,CURLOPT_SSLCERT,$zs1);    //curl_setopt($ch,CURLOPT_SSLKEY,$zs2);    // curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01;    // Windows NT 5.0)');    //curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );    curl_setopt ( $ch , CURLOPT_AUTOREFERER, 1 );    curl_setopt ( $ch , CURLOPT_POSTFIELDS, $data );    curl_setopt ( $ch , CURLOPT_RETURNTRANSFER, true );    $info = curl_exec ( $ch );    //返回结果    if ( $info ){     curl_close( $ch );     return $info ;    } else {     $error = curl_errno( $ch );     curl_close( $ch );     return "curl出错,错误码:$error" ;    }   }   /**   * 获取数据封装为数组   * @param $openid 用户openid 唯一标示   * @return xml   */   private function getdataXml( $openid ){    //封装成数据    $dataArr = array (     'amount' => $this ->amount*100, //金额(以分为单位,必须大于100)     'check_name' => 'NO_CHECK' , //校验用户姓名选项,NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账)OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)     'desc' => '提现' , //描述     'mch_appid' => $this ->app_id,     'mchid' => $this ->mchid, //商户号     'nonce_str' =>rand(100000, 999999), //不长于32位的随机数     'openid' => $openid , //用户唯一标识     'partner_trade_no' => $this ->order_sn, //商户订单号     're_user_name' => '' , //用户姓名,check_name为NO_CHECK时为可选项     'spbill_create_ip' => $_SERVER [ "REMOTE_ADDR" ], //服务器ip    );    //获取签名    $sign = $this ->getSign( $dataArr );    //xml数据    $data ="<xml>     <mch_appid> ".$dataArr['mch_appid']." </mch_appid>     <mchid> ".$dataArr['mchid']." </mchid>     <nonce_str> ".$dataArr['nonce_str']." </nonce_str>     <partner_trade_no> ".$dataArr['partner_trade_no']." </partner_trade_no>     <openid> ".$dataArr['openid']." </openid>     <check_name> ".$dataArr['check_name']." </check_name>     <re_user_name> ".$dataArr['re_user_name']." </re_user_name>     <amount> ".$dataArr['amount']." </amount>     <desc> ".$dataArr['desc']." </desc>     <spbill_create_ip> ".$dataArr['spbill_create_ip']." </spbill_create_ip>     <sign> ".$sign." </sign>     </xml>";    return $data ;   }   /**   *  作用:格式化参数,签名过程需要使用   */   private function formatBizQueryParaMap( $paraMap , $urlencode )   {    $buff = "" ;    ksort( $paraMap );    foreach ( $paraMap as $k => $v )    {     if ( $v ){     if ( $urlencode )     {      $v = urlencode( $v );     }     $buff .= $k . "=" . $v . "&" ;     }    }    $reqPar =NULL;    if ( strlen ( $buff ) > 0)    {     $reqPar = substr ( $buff , 0, strlen ( $buff )-1);    }    return $reqPar ;   }   /**   *  作用:生成签名   */   private function getSign( $Obj )   {    foreach ( $Obj as $k => $v )    {     $Parameters [ $k ] = $v ;    }    //签名步骤一:按字典序排序参数    ksort( $Parameters );    $String = $this ->formatBizQueryParaMap( $Parameters , false);    //echo '【string1】'.$String.'</br>';    //签名步骤二:在string后加入KEY    $String = $String . "&key=" . $this ->apikey;    //echo "【string2】".$String."</br>";    //签名步骤三:MD5加密    $String = md5( $String );    //echo "【string3】 ".$String."</br>";    //签名步骤四:所有字符转为大写    $result_ = strtoupper ( $String );    //echo "【result】 ".$result_."</br>";    return $result_ ;   }   //-----------   private function http( $url , $method = 'POST' , $postfields = null, $headers = array ())   {    header( "Content-Type:text/html;charset=utf-8" );    $ch = curl_init();    /* Curl settings */    curl_setopt( $ch , CURLOPT_URL, $url );    curl_setopt( $ch , CURLOPT_POSTFIELDS, "" );    curl_setopt( $ch , CURLOPT_RETURNTRANSFER, true);    curl_setopt( $ch , CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts    curl_setopt( $ch , CURLOPT_SSL_VERIFYHOST, FALSE);    curl_setopt( $ch , CURLOPT_TIMEOUT, 30);    switch ( $method ){     case 'POST' :     curl_setopt( $ch ,CURLOPT_POST, true);     break ;    }    curl_setopt( $ch , CURLOPT_HTTPHEADER, $headers );    curl_setopt( $ch , CURLINFO_HEADER_OUT, true);    $response = curl_exec( $ch );    $http_code = curl_getinfo( $ch , CURLINFO_HTTP_CODE); //返回请求状态码    curl_close( $ch );    return array ( $http_code , $response );   } }

总结

以上所述是小编给大家介绍的PHP实现微信提现功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

原文链接:https://www.cnblogs.com/a609251438/p/11900830.html

可以去百度分享获取分享代码输入这里。
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

【腾讯云】云服务器产品特惠热卖中
搜索
标签列表
    关注我们

    了解等多精彩内容