php实现微信公众平台发红包功能


Posted in PHP onJune 14, 2018

本文实例为大家分享了php微信公众平台给用户发红包的具体代码,供大家参考,具体内容如下

直接上代码:

代码

<?php
/**
 * 微信红包的类 
 * @Author snmoney#gmail.com 
 * @copyright 2015 
 * @version 2.0

 * *微信红包还有部分可选的参数,如分享预设值等将在后续版本补充上相关功能。
 * 对应官方接口更新,追加了分裂红包的玩法,详情参考官方文档。
 */

CLASS WXHongBao {

  private $mch_id = "********";               //商户ID写死
  private $wxappid = "********";          //微信公众号,写死
  private $client_ip = ""; //"127.0.0.1"; //调用红包接口的主机的IP,服务端IP,写死,即脚本文件所在的IP
  private $apikey = "";    //pay的秘钥值
  private $total_num = 1;                   //发放人数。固定值1,不可修改
  private $nick_name = "微信公众号红包";           //红包商户名称
  private $send_name = "微信公众号红包";          //红包派发者名称
  private $wishing = "欢迎再次参与";      //
  private $act_name = "";     //活动名称
  private $remark = "";
  private $nonce_str = "";
  private $mch_billno = "";
  private $re_openid = "";    //接收方的openID
  private $total_amount = 1 ;   //红包金额,单位 分
  private $min_value = 1;   //最小金额
  private $max_value = 1;   //根据接口要求,上述3值必须一致
  private $sign = "";     //签名在send时生成
  private $amt_type;     //分裂红包参数,在sendgroup中进行定义,是常量 ALL_RAND

  //证书,在构造函数中定义,注意!
  private $apiclient_cert; //= getcwd()."/apiclient_cert.pem";
  private $apiclient_key;// = getcwd()."/apiclient_key.pem";
  private $apiclient_ca;// = getcwd()."/apiclient_key.pem";

  //分享参数
  private $isShare = false; //有用?似乎是无用参数,全部都不是必选和互相依赖的参数
  private $share_content = ""; 
  private $share_url ="";
  private $share_imgurl = "";

  private $wxhb_inited;

  private $api_hb_group = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack";//裂变红包
  private $api_hb_single = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

  private $error = "ok"; //init

  /**
   * WXHongBao::__construct()
   * 步骤
   * new(openid,amount)
   * setnickname
   * setsend_name
   * setwishing
   * setact_name
   * setremark
   * send()
   * @return void
   */
  function __construct(){
    //好像没有什么需要构造函数做的 引入需要的文件
    $this->wxhb_inited = false; 
    $this->apiclient_cert = getcwd() . "/zzz1/apiclient_cert.pem";
    $this->apiclient_key = getcwd() . "/zzz1/apiclient_key.pem";
    $this->apiclient_ca = getcwd() . "/zzz1/rootca.pem";
  }

  public function err(){
    return $this->error;
  }

  public function error(){
    return $this->err();
  }
  /**
   * WXHongBao::newhb()
   * 构造新红包 
   * @param mixed $toOpenId
   * @param mixed $amount 金额分
   * @return void
   */
  public function newhb($toOpenId,$amount){

    if(!is_numeric($amount)){
      $this->error = "金额参数错误";
      return;
    }elseif($amount<100){
      $this->error = "金额太小";
      return;
    }elseif($amount>20000){
      $this->error = "金额太大";
      return;
    }

    $this->gen_nonce_str();//构造随机字串
    $this->gen_mch_billno();//构造订单号
    $this->setOpenId($toOpenId);
    $this->setAmount($amount);
    $this->wxhb_inited = true; //标记微信红包已经初始化完毕可以发送

    //每次new 都要将分享的内容给清空掉,否则会出现残余被引用
    $this->share_content= "";
    $this->share_imgurl = "";
    $this->share_url = "";
  }

  /**
   * WXHongBao::sendGroup()
   * 发送裂变红包,参数为裂变数量
   * @param integer $num 3-20
   * @return
   */
  public function sendGroup($num=3){
    $this->amt_type = "ALL_RAND";//$amt; 固定值。发送裂变红包组文档指定参数,随机
    return $this->send($this->api_hb_group,$num);
  }

  public function getApiSingle(){
    return $this->api_hb_single;
  }

  public function getApiGroup(){
    return $this->api_hb_group;
  }

  public function setNickName($nick){
    $this->nick_name = $nick;
  }

  public function setSendName($name){
    $this->send_name = $name;
  }

  public function setWishing($wishing){
    $this->wishing = $wishing;
  }

  public function setActName($act){
    $this->act_name = $act;
  }

  public function setRemark($remark){
    $this->remark = $remark;
  }

  public function setOpenId($openid){
    $this->re_openid = $openid;
  }

  /**
   * WXHongBao::setAmount()
   * 设置红包金额
   * 文档有两处冲突描述
   * 一处指金额 >=1 (分钱)
   * 另一处指金额 >=100 < 20000 [1-200元]
   * 有待测试验证!
   * @param mixed $price 单位 分
   * @return void
   */
  public function setAmount($price){
    $this->total_amount = (int)$price;
    $this->min_value = (int)$price;
    $this->max_value = (int)$price;
  }

  //以下方法,为设置分裂红包时使用
  public function setHBminmax($min,$max){
    $this->min_value = $min;
    $this->max_value = $max;
  }

  public function setShare($img="",$url="",$content=""){
    //https://mmbiz.qlogo.cn/mmbiz/MS1jaDO92Ep4qNo9eV0rnItptyBrzUhJqT8oxSsCofdxibnNWMJiabaqgLPkDaEJmia6fqTXAXulKBa9NLfxYMwYA/0?wx_fmt=png
    //http://mp.weixin.qq.com/s?__biz=MzA5Njg4NTk3MA==&mid=206257621&idx=1&sn=56241da30e384e40771065051e4aa6a8#rd
    $this->share_content = $content;
    $this->share_imgurl = $img;
    $this->share_url = $url;
  }


  /**
   * WXHongBao::send()
   * 发出红包
   * 构造签名
   * 注意第二参数,单发时不要改动!
   * @return boolean $success
   */
  public function send(){

    $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
    $total_num = 1;

    if(!$this->wxhb_inited) {
      $this->error .= "(红包未准备好)";
      return false; //未初始化完成
    }

    $this->total_num = $total_num;

    $this->gen_Sign(); //生成签名

    //构造提交的数据    
    $xml = $this->genXMLParam();

    //echo $xml;

    //debug
    file_put_contents("hbxml.debug",$xml);

    //提交xml,curl
    //$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
    $ch = curl_init();   
    curl_setopt($ch,CURLOPT_TIMEOUT,10);
    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,$this->apiclient_cert);    
    //curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
    curl_setopt($ch,CURLOPT_SSLKEY,$this->apiclient_key);

    curl_setopt($ch,CURLOPT_CAINFO,$this->appclient_ca);

    /* 
    if( count($aHeader) >= 1 ){
      curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
    }
    */    
    curl_setopt($ch,CURLOPT_POST, 1);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
    $data = curl_exec($ch);
     //die(print_r($data));
    if($data){
      curl_close($ch);
      $rsxml = simplexml_load_string($data);
      if($rsxml->return_code == 'SUCCESS' ){
        return true;
      }else{
        $this->error = json_encode($rsxml->return_msg);
        return false;  
      }
    }else{ 
      $this->error = curl_errno($ch);

      curl_close($ch);
      return false;
    }

  }

  private function gen_nonce_str(){
    $this->nonce_str = strtoupper(md5(mt_rand().time())); //确保不重复而已
  }

  private function gen_Sign(){
    unset($param); 
    //其实应该用key重排一次 right?
    $param["act_name"]=$this->act_name;//

    if($this->total_num==1){ //这些是裂变红包用不上的参数,会导致签名错误
      $param["client_ip"]=$this->client_ip;
       $param["max_value"]=$this->max_value;
       $param["min_value"]=$this->min_value;
      $param["nick_name"]=$this->nick_name;
    }

    $param["mch_billno"] = $this->mch_billno;  //   
    $param["mch_id"]=$this->mch_id;//    
    $param["nonce_str"]=$this->nonce_str;  //  
    $param["re_openid"]=$this->re_openid;//
    $param["remark"]=$this->remark;    //
    $param["send_name"]=$this->send_name;//
    $param["total_amount"]=$this->total_amount;//
    $param["total_num"]=$this->total_num;    //
    $param["wishing"]=$this->wishing;//
    $param["wxappid"]=$this->wxappid;//

    //裂变红包 用不到就注释掉
     if($this->share_content) $param["share_content"] = $this->share_content;
     if($this->share_imgurl) $param["share_imgurl"] = $this->share_imgurl;
     if($this->share_url) $param["share_url"] = $this->share_url;
    if($this->amt_type) $param["amt_type"] = $this->amt_type; //

    ksort($param); //按照键名排序...艹,上面排了我好久

    //$sign_raw = http_build_query($param)."&key=".$this->apikey;
    $sign_raw = "";
    foreach($param as $k => $v){
      $sign_raw .= $k."=".$v."&";
    }
    $sign_raw .= "key=".$this->apikey;
    //可以用下面方法查看
    // file_put_contents("11sign.txt",$sign_raw);//debug
    $this->sign = strtoupper(md5($sign_raw));

  }

  /**
   * WXHongBao::genXMLParam()
   * 生成post的参数xml数据包
   * 注意生成之前各项值要生成,尤其是Sign
   * @return $xml
   */
  public function genXMLParam(){
    // $xml = "<xml>


    //   <sign>".$this->sign."</sign> 
    //   <mch_billno>".$this->mch_billno."</mch_billno> 
    //   <mch_id>".$this->mch_id."</mch_id> 
    //   <wxappid>".$this->wxappid."</wxappid> 
    //   <nick_name><![CDATA[".$this->nick_name."]]></nick_name> 
    //   <send_name><![CDATA[".$this->send_name."]]></send_name> 
    //   <re_openid>".$this->re_openid."</re_openid> 
    //   <total_amount>".$this->total_amount."</total_amount> 
    //   <min_value>".$this->min_value."</min_value> 
    //   <max_value>".$this->max_value."</max_value> 
    //   <total_num>".$this->total_num."</total_num> 
    //   <wishing><![CDATA[".$this->wishing."]]></wishing> 
    //   <client_ip><![CDATA[".$this->client_ip."]]></client_ip> 
    //   <act_name><![CDATA[".$this->act_name."]]></act_name> 
    //   <remark><![CDATA[".$this->remark."]]></remark>       
    //   <nonce_str>".$this->nonce_str."</nonce_str>";
   $xml = "<xml>
         <act_name><![CDATA[".$this->act_name."]]></act_name> 
         <client_ip><![CDATA[".$this->client_ip."]]></client_ip> 
         <max_value>".$this->max_value."</max_value> 
          <mch_billno>".$this->mch_billno."</mch_billno> 
          <mch_id>".$this->mch_id."</mch_id>
          <min_value>".$this->min_value."</min_value> 
          <nick_name><![CDATA[".$this->nick_name."]]></nick_name> 
          <nonce_str>".$this->nonce_str."</nonce_str>
          <re_openid>".$this->re_openid."</re_openid> 
          <remark><![CDATA[".$this->remark."]]></remark>
           <send_name><![CDATA[".$this->send_name."]]></send_name>
           <total_amount>".$this->total_amount."</total_amount> 
           <total_num>".$this->total_num."</total_num>
           <wishing><![CDATA[".$this->wishing."]]></wishing>
           <wxappid>".$this->wxappid."</wxappid>
           <sign>".$this->sign."</sign> 
        </xml>
           ";

      // <nick_name><![CDATA[".$this->nick_name."]]></nick_name> 



      // <min_value>".$this->min_value."</min_value> 
      // <max_value>".$this->max_value."</max_value> 

    // $xml .="</xml>";

    return $xml;
  }

  /**
   * WXHongBao::gen_mch_billno()
   * 商户订单号(每个订单号必须唯一) 
    组成: mch_id+yyyymmdd+10位一天内不能重复的数字。 
    接口根据商户订单号支持重入, 如出现超时可再调用。 
   * @return void
   */
  private function gen_mch_billno(){
    //生成一个长度10,的阿拉伯数字随机字符串
    $rnd_num = array('0','1','2','3','4','5','6','7','8','9');
    $rndstr = "";
    while(strlen($rndstr)<10){
      $rndstr .= $rnd_num[array_rand($rnd_num)];  
    }

    $this->mch_billno = $this->mch_id.date("Ymd").$rndstr;
  }
}
/**
*1.上边是红包类,需要用的时候直接引入红包类。
*2.//实例化红包类
*  $wxhongbao=new \WXHongBao();
*3. //需要发放的openid 金额 openid 根据微信提供的接口获取,金额根据自己需求
* $wxhongbao->newhb($user_openid, $pay_money*100);
*$wxhongbao->setActName("根据自己需求设置");
* $wxhongbao->setWishing("根据自己需求设置");
*$wxhongbao->setRemark("根据自己需求设置");
*参数设置之后发放红包
*$wxhongbao->send();
**/
?>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
初学者入门:细述PHP4的核心Zend
Sep 05 PHP
简单的页面缓冲技术
Oct 09 PHP
php中使用接口实现工厂设计模式的代码
Jun 17 PHP
关于zend studio 出现乱码问题的总结
Jun 23 PHP
php与java通过socket通信的实现代码
Oct 21 PHP
php中hashtable实现示例分享
Feb 13 PHP
php向js函数传参的几种方法
Aug 10 PHP
Laravel框架中扩展函数、扩展自定义类的方法
Sep 04 PHP
PHP+JavaScript实现无刷新上传图片
Feb 21 PHP
详解php框架Yaf路由重写
Jun 20 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
Aug 21 PHP
PHP使用Http Post请求发送Json对象数据代码解析
Jul 16 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
Jun 14 #PHP
thinkPHP框架实现多表查询的方法
Jun 14 #PHP
php微信开发之关注事件
Jun 14 #PHP
thinkPHP框架动态配置用法实例分析
Jun 14 #PHP
php微信开发之谷歌测距
Jun 14 #PHP
php微信开发之图片回复功能
Jun 14 #PHP
php微信开发之音乐回复功能
Jun 14 #PHP
You might like
iis下php mail函数的sendmail配置方法(官方推荐)
2012/04/25 PHP
Laravel框架文件上传功能实现方法示例
2019/04/16 PHP
javascript编程起步(第六课)
2007/01/10 Javascript
jQuery常用数据处理方法小结
2015/02/20 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
2015/07/10 Javascript
js随机生成26个大小写字母
2016/02/12 Javascript
package.json文件配置详解
2017/06/15 Javascript
详解js正则表达式验证时间格式xxxx-xx-xx形式
2018/02/09 Javascript
Vue+axios+WebApi+NPOI导出Excel文件实例方法
2019/06/05 Javascript
jQuery 查找元素操作实例小结
2019/10/02 jQuery
JS实现无限轮播无倒退效果
2020/09/21 Javascript
JavaScript实现切换多张图片
2021/01/27 Javascript
pygame播放音乐的方法
2015/05/19 Python
CentOS 6.X系统下升级Python2.6到Python2.7 的方法
2016/10/12 Python
Python计算两个日期相差天数的方法示例
2017/05/23 Python
python3爬取各类天气信息
2018/02/24 Python
Python根据指定日期计算后n天,前n天是哪一天的方法
2018/05/29 Python
Python统计python文件中代码,注释及空白对应的行数示例【测试可用】
2018/07/25 Python
python导包的几种方法(自定义包的生成以及导入详解)
2019/07/15 Python
详解基于python-django框架的支付宝支付案例
2019/09/23 Python
完美解决Django2.0中models下的ForeignKey()问题
2020/05/19 Python
使用已经得到的keras模型识别自己手写的数字方式
2020/06/29 Python
anaconda升级sklearn版本的实现方法
2021/02/22 Python
Html5页面获取微信公众号的openid的方法
2020/05/12 HTML / CSS
日本民宿预约平台:STAY JAPAN
2017/07/01 全球购物
Bally巴利英国官网:经典瑞士鞋履、手袋及配饰奢侈品牌
2018/05/07 全球购物
JPA面试常见问题
2016/11/14 面试题
局域网标准
2016/09/10 面试题
linux下进程间通信的方式
2014/12/23 面试题
Ajax实现页面无刷新留言效果
2021/03/24 Javascript
高中军训广播稿
2014/01/14 职场文书
管理失职检讨书
2014/02/12 职场文书
2014年民警工作总结
2014/11/25 职场文书
工作时间调整通知
2015/04/24 职场文书
职场中的你,辞职信写对了吗?
2019/06/26 职场文书
netty 实现tomcat的示例代码
2022/06/05 Servers