Api看看PHP是如何实现微信提现功能的

Posted PHP自学中心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Api看看PHP是如何实现微信提现功能的相关的知识,希望对你有一定的参考价值。










































【Api】看看PHP是如何实现微信提现功能的

教程分享

【Api】看看PHP是如何实现微信提现功能的

抖音号startphp

用短视频和大家分享PHP学习方法,学习技巧与经验分享

欢迎关注抖音号:startphp


你可能喜欢的文章









【Api】看看PHP是如何实现微信提现功能的

文章正文

之前分享了微信支付接口、现在给大家分享一下APP提现的接口。

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


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

封装提现的方法

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(1000090000) . rand(1000090000);//商户订单号
    $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, 30array(), 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 ";
      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;
}



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

<?php
namespace HomeController;
use ThinkController;
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:webwwwHomewx_payapiclient_cert.pem'); //证书这块大家把文件放到哪都行、
    curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
    curl_setopt($ch,CURLOPT_SSLKEY, 'C:webwwwHomewx_payapiclient_key.pem');//注意证书名字千万别写错、

   //$zs1=dirname(dirname(__FILE__)).'wx_payapiclient_cert.pem';
   //$zs2=dirname(dirname(__FILE__)).'wx_payapiclient_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(100000999999),//不长于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的,小编也可以拉你进微信技术群,交流与学习!


领取以下视频教程

长按二维码加好友,备注码农,记得截图


【前端教程】 web前端视频教程(基础+进阶+高级)

【php基础】 PHP基础到开发中小型网站教程

【php高级】 PHP高级语法与功能实战

【php特级】 手把手教你玩转Linux课程

【php框架】 ThinkPHP5商城实战教程

微信教程】 微信小程序开发合集   


学习  |  交流  |  分享  |  文章 


以上是关于Api看看PHP是如何实现微信提现功能的的主要内容,如果未能解决你的问题,请参考以下文章

Api看看PHP是如何实现微信企业付款到个人零钱的

Api看看PHP是如何实现微信H5支付的?

求php通过已知的经纬度,操作百度地图api获取周边服务信息的实例,回答满意我再加分.

pringboot整合微信支付sdk

PHP实现微信商户支付企业付款到零钱功能代码实例

php微信开发实现自定义菜单功能