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 相关文章推荐
WHOIS类的修改版
Oct 09 PHP
常用的php ADODB使用方法集锦
Mar 25 PHP
php生成缩略图的类代码
Oct 02 PHP
PHP获取url的函数代码
Aug 02 PHP
php+ajax实现无刷新数据分页的办法
Nov 02 PHP
thinkPHP下ueditor的使用方法详解
Dec 26 PHP
Zend Framework生成验证码并实现验证码验证功能(附demo源码下载)
Mar 22 PHP
laravel学习教程之关联模型
Jul 30 PHP
php fseek函数读取大文件两种方法
Oct 12 PHP
php记录搜索引擎爬行记录的实现代码
Mar 02 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
Oct 15 PHP
Thinkphp框架使用list_to_tree 实现无限级分类列出所有节点示例
Apr 04 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
PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
2011/07/01 PHP
PHP return语句的另一个作用
2014/07/30 PHP
Yii实现文章列表置顶功能示例
2016/10/18 PHP
Symfony查询方法实例小结
2017/06/28 PHP
php工具型代码之印章抠图
2018/07/18 PHP
laravel框架的安装与路由实例分析
2019/10/11 PHP
laravel开发环境homestead搭建过程详解
2020/07/03 PHP
javascript开发技术大全 第4章 直接量与字符集
2011/07/03 Javascript
Jquery同辈元素选中/未选中效果的实例代码
2013/08/01 Javascript
通过Javascript读取本地Excel文件内容的代码示例
2014/04/08 Javascript
js实现简单的可切换选项卡效果
2015/04/10 Javascript
JS扩展方法实例分析
2015/04/15 Javascript
Angularjs实现搜索关键字高亮显示效果
2017/01/17 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
2017/08/29 jQuery
vue中手机号,邮箱正则验证以及60s发送验证码的实例
2018/03/16 Javascript
浅析JS中什么是自定义react数据验证组件
2018/10/19 Javascript
json数据格式常见操作示例
2019/06/13 Javascript
微信小程序列表时间戳转换实现过程解析
2019/10/12 Javascript
Vue解析带html标签的字符串为dom的实例
2019/11/13 Javascript
Element Card 卡片的具体使用
2020/07/26 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
Python实用日期时间处理方法汇总
2015/05/09 Python
图文讲解选择排序算法的原理及在Python中的实现
2016/05/04 Python
selenium+python自动化测试之页面元素定位
2019/01/23 Python
Python爬虫如何应对Cloudflare邮箱加密
2020/06/24 Python
经典的班主任推荐信
2013/10/28 职场文书
语文教育专业求职信
2014/06/28 职场文书
2014年社区居委会主任重阳节讲话稿
2014/09/25 职场文书
我的大学四年规划书范文2014
2014/09/26 职场文书
2014年检察院个人工作总结
2014/12/09 职场文书
2014个人年终工作总结范文
2014/12/15 职场文书
2016年春季趣味运动会开幕词
2016/03/04 职场文书
2016年公共机构节能宣传周活动总结
2016/04/05 职场文书
浅谈react useEffect闭包的坑
2021/06/08 Javascript
浅谈TypeScript 索引签名的理解
2021/10/16 Javascript
《传颂之物 虚伪的假面》BD发售宣传CM公开
2022/04/04 日漫