微信红包封装类

php

浏览数:364

2019-1-7

片段 1片段 2片段 3


模拟普通红包发送 TestController.php

public function actionRedpack(){
        $inputObj = new WxRedPack();
        $inputObj->SetMch_billno("REDPACK".date("ymd").time());
        $inputObj->SetRe_openid('on9r51P0GuwCfizNdERZFsd725wo');
        $inputObj->SetSend_name('高兴舅好');
        $inputObj->SetTotal_amount(100);
        $inputObj->SetWishing('恭喜尼,祝福尼,舅服尼!');
        $inputObj->SetAct_name("舅爱活动");
        $inputObj->SetRemark('赞点红包去划船,淘气的诗和远方');
        $rst = WxRedPackApi::sendredpack($inputObj);
        echo '<pre>';
        print_r($rst);

    }


WxRedPack.php

<?php

namespace app\common\wxpayapi\lib;

use app\common\wxpayapi\lib\WxPayConfig;
use app\common\wxpayapi\lib\WxPayException;
use app\common\wxpayapi\lib\WxPayDataBase;

/**
 *
 *微信红包 封装类
 * @link https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
 * @author leo.yzw@foxmail.com
 *
 */
class WxRedPack extends WxPayDataBase
{    /**
     * 设置随机字符串,不长于32位。推荐随机数生成算法
     * @param string $value
     **/
    public function SetNonce_str($value) {
        $this->values['nonce_str'] = $value;
    }

    /**
     * 获取随机字符串,不长于32位。推荐随机数生成算法的值
     * @return 值
     **/
    public function GetNonce_str() {
        return $this->values['nonce_str'];
    }

    /**
     * 判断随机字符串,不长于32位。推荐随机数生成算法是否存在
     * @return true 或 false
     **/
    public function IsNonce_strSet() {
        return array_key_exists('nonce_str', $this->values);
    }

    /**
     * 设置微信分配的公众账号ID
     * @param string $value
     **/
    public function SetWxappid($value) {
        $this->values['wxappid'] = $value;
    }

    /**
     * 获取微信分配的公众账号ID的值
     * @return 值
     **/
    public function GetWxappid() {
        return $this->values['wxappid'];
    }

    /**
     * 判断微信分配的公众账号ID是否存在
     * @return true 或 false
     **/
    public function IsWxappidSet() {
        return array_key_exists('wxappid', $this->values);
    }    /**
     * 设置微信支付分配的商户号
     * @param string $value
     **/
    public function SetMch_id($value) {
        $this->values['mch_id'] = $value;
    }

    /**
     * 获取微信支付分配的商户号的值
     * @return 值
     **/
    public function GetMch_id() {
        return $this->values['mch_id'];
    }

    /**
     * 判断微信支付分配的商户号是否存在
     * @return true 或 false
     **/
    public function IsMch_idSet() {
        return array_key_exists('mch_id', $this->values);
    }    public function SetMch_billno($value) {
        $this->values['mch_billno'] = $value;
    }

    public function GetMch_billno() {
        return $this->values['mch_billno'];
    }

    public function IsMch_billnoSet() {
        return array_key_exists('mch_billno', $this->values);
    }

    public function SetSend_name($value) {
        $this->values['send_name'] = $value;
    }

    public function GetSend_name() {
        return $this->values['send_name'];
    }

    public function IsSend_nameSet() {
        return array_key_exists('send_name', $this->values);
    }

    public function SetRe_openid($value) {
        $this->values['re_openid'] = $value;
    }

    public function GetRe_openid() {
        return $this->values['re_openid'];
    }

    public function IsRe_openidSet() {
        return array_key_exists('re_openid', $this->values);
    }

    /**
     * 设置订单总金额,只能为整数,详见支付金额
     * @param string $value
     **/
    public function SetTotal_amount($value) {
        $this->values['total_amount'] = $value;
    }

    /**
     * 获取订单总金额,只能为整数,详见支付金额的值
     * @return 值
     **/
    public function GetTotal_amount() {
        return $this->values['total_amount'];
    }

    /**
     * 判断订单总金额,只能为整数,详见支付金额是否存在
     * @return true 或 false
     **/
    public function IsTotal_amountSet() {
        return array_key_exists('total_amount', $this->values);
    }

    public function SetTotal_num($value) {
        $this->values['total_num'] = $value;
    }

    public function GetTotal_num() {
        return $this->values['total_num'];
    }

    public function IsTotal_numSet() {
        return array_key_exists('total_num', $this->values);
    }

    public function SetWishing($value) {
        $this->values['wishing'] = $value;
    }

    public function GetWishing() {
        return $this->values['wishing'];
    }

    public function IsWishingSet() {
        return array_key_exists('wishing', $this->values);
    }

    public function SetClient_ip($value) {
        $this->values['client_ip'] = $value;
    }

    public function GetClient_ip() {
        return $this->values['client_ip'];
    }

    public function IsClient_ipSet() {
        return array_key_exists('client_ip', $this->values);
    }

    public function SetAct_name($value) {
        $this->values['act_name'] = $value;
    }

    public function GetAct_name() {
        return $this->values['act_name'];
    }

    public function IsAct_nameSet() {
        return array_key_exists('act_name', $this->values);
    }

    public function SetRemark($value) {
        $this->values['remark'] = $value;
    }

    public function GetRemark() {
        return $this->values['remark'];
    }

    public function IsRemarkSet() {
        return array_key_exists('remark', $this->values);
    }

    /**
     * 发放红包使用场景,红包金额大于200时必传
     * PRODUCT_1:商品促销
     * PRODUCT_2:抽奖
     * PRODUCT_3:虚拟物品兑奖
     * PRODUCT_4:企业内部福利
     * PRODUCT_5:渠道分润
     * PRODUCT_6:保险回馈
     * PRODUCT_7:彩票派奖
     * PRODUCT_8:税务刮奖
     */
    public function SetScene_id($value) {
        $this->values['scene_id'] = $value;
    }

    public function GetScene_id() {
        return $this->values['scene_id'];
    }

    public function IsScene_idSet() {
        return array_key_exists('scene_id', $this->values);
    }

    public function SetRisk_info($value) {
        $this->values['risk_info'] = $value;
    }

    public function GetRisk_info() {
        return $this->values['risk_info'];
    }

    public function IsRisk_infoSet() {
        return array_key_exists('risk_info', $this->values);
    }

    public function SetConsume_mch_id($value) {
        $this->values['consume_mch_id'] = $value;
    }

    public function GetConsume_mch_id() {
        return $this->values['consume_mch_id'];
    }

    public function IsConsume_mch_idSet() {
        return array_key_exists('consume_mch_id', $this->values);
    }

    public function SetAmt_type($value) {
        $this->values['amt_type'] = $value;
    }

    public function GetAmt_type() {
        return $this->values['amt_type'];
    }

    public function IsAmt_typeSet() {
        return array_key_exists('amt_type', $this->values);
    }

    public function SetBill_type($value) {
        $this->values['bill_type'] = $value;
    }

    public function GetBill_type() {
        return $this->values['bill_type'];
    }

    public function IsBill_typeSet() {
        return array_key_exists('bill_type', $this->values);
    }

    /**
     * 设置微信分配的公众账号ID
     * @param string $value
     **/
    public function SetAppid($value) {
        $this->values['appid'] = $value;
    }

    /**
     * 获取微信分配的公众账号ID的值
     * @return 值
     **/
    public function GetAppid() {
        return $this->values['appid'];
    }

    /**
     * 判断微信分配的公众账号ID是否存在
     * @return true 或 false
     **/
    public function IsAppidSet() {
        return array_key_exists('appid', $this->values);
    }

}


WxRedPackApi.php

<?php

namespace app\common\wxpayapi\lib;
use app\common\BasePayment;

/**
 *
 * 接口访问类,包含所有微信红包API列表的封装,类中方法为static方法,
 * @author leo.yzw@foxmail.com
 *
 * 发放规则
 * 1.发送频率限制------默认1800/min
 * 2.发送个数上限------按照默认1800/min算
 * 3.金额上限------根据传入场景id不同默认上限不同,可以在商户平台产品设置进行设置和申请,最大不大于4999元/个
 * 4.其他的“量”上的限制还有哪些?------用户当天的领取上限次数,默认是10
 * 5.如果量上满足不了我们的需求,如何提高各个上限?------金额上限和用户当天领取次数上限可以在商户平台进行设置
 * 注意1-红包金额大于200时,请求参数scene_id必传,参数说明见下文。
 * 注意2-新申请商户号使用企业付款需要满足两个条件:1、入驻时间超过90天 2、连续正常交易30天。
 */
class WxRedPackApi extends BasePayment
{

    /**
     *
     * 普通红包发送
     * wxappid、mch_id、client_ip、nonce_str,total_num不需要填入
     * mch_billno,send_name,re_openid,total_amount,wishing,act_name,remark
     * @param WxRedPack $inputObj
     * @throws WxPayException
     * @return 成功时返回,其他抛异常
     */
    public static function sendredpack(WxRedPack $inputObj, $timeOut = 6) {
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
        //检测必填参数
        if (!$inputObj->IsMch_billnoSet()) {
            throw new WxPayException("缺少必填参数mch_billno!");
        } else if (!$inputObj->IsSend_nameSet()) {
            throw new WxPayException("缺少必填参数send_name!");
        } else if (!$inputObj->IsRe_openidSet()) {
            throw new WxPayException("缺少必填参数re_opendid!");
        } else if (!$inputObj->IsTotal_amountSet()) {
            throw new WxPayException("缺少必填参数total_amount!");
        } else if (!$inputObj->IsWishingSet()) {
            throw new WxPayException("缺少必填参数wishing!");
        } else if (!$inputObj->IsAct_nameSet()) {
            throw new WxPayException("缺少必填参数act_name!");
        } else if (!$inputObj->IsRemarkSet()) {
            throw new WxPayException("缺少必填参数remark!");
        }
        //关联参数
        if ($inputObj->GetTotal_amount() > 20000 && !$inputObj->IsScene_idSet()) {
            throw new WxPayException("缺少必填参数scene_id!红包金额大于200时必传!");
        }
        $inputObj->SetWxappid(WxPayConfig::APPID);//公众账号ID
        $inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
        $inputObj->SetClient_ip($_SERVER['REMOTE_ADDR']);
        $inputObj->SetNonce_str(self::getNonceStr());//随机字符串
        $inputObj->SetTotal_num(1);

        //签名
        $inputObj->SetSign();
        $xml = $inputObj->ToXml();

        $response = self::postXmlCurl($xml, $url, true, $timeOut);
        $result = WxPayResults::Init($response);

        return $result;

    }

    /**
     *
     * 裂变红包发送
     * wxappid、mch_id、nonce_str,amt_type不需要填入
     * mch_billno,send_name,re_openid,total_amount,total_num,wishing,act_name,remark
     * @param WxRedPack $inputObj
     * @throws WxPayException
     * @return 成功时返回,其他抛异常
     */
    public static function sendgroupredpack(WxRedPack $inputObj, $timeOut = 6) {
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack';
        //检测必填参数
        if (!$inputObj->IsMch_billnoSet()) {
            throw new WxPayException("缺少必填参数mch_billno!");
        } else if (!$inputObj->IsSend_nameSet()) {
            throw new WxPayException("缺少必填参数send_name!");
        } else if (!$inputObj->IsRe_openidSet()) {
            throw new WxPayException("缺少必填参数re_opendid!");
        } else if (!$inputObj->IsTotal_amountSet()) {
            throw new WxPayException("缺少必填参数total_amount!");
        } else if (!$inputObj->IsTotal_numSet()) {
            throw new WxPayException("缺少必填参数total_num!");
        } else if (!$inputObj->IsWishingSet()) {
            throw new WxPayException("缺少必填参数wishing!");
        } else if (!$inputObj->IsAct_nameSet()) {
            throw new WxPayException("缺少必填参数act_name!");
        } else if (!$inputObj->IsRemarkSet()) {
            throw new WxPayException("缺少必填参数remark!");
        }

        $inputObj->SetWxappid(WxPayConfig::APPID);//公众账号ID
        $inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
        $inputObj->SetNonce_str(self::getNonceStr());//随机字符串
        $inputObj->SetAct_name("ALL_RAND");

        //签名
        $inputObj->SetSign();
        $xml = $inputObj->ToXml();

        $response = self::postXmlCurl($xml, $url, true, $timeOut);
        $result = WxPayResults::Init($response);

        return $result;
    }

    /**
     *
     * 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包,
     * WxRedPack中mch_billno 必填
     * appid、mch_id 、nonce_str,bill_type不需要填入
     * @param WxRedPack $inputObj
     * @param int $timeOut
     * @throws WxPayException
     * @return 成功时返回,其他抛异常
     */
    public static function redpackQuery(WxRedPack $inputObj, $timeOut = 6) {
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo";
        //检测必填参数
        if (!$inputObj->IsMch_billnoSet()) {
            throw new WxPayException("红包查询 mch_billno必填!");
        }
        $inputObj->SetAppid(WxPayConfig::APPID);//公众账号ID
        $inputObj->SetMch_id(WxPayConfig::MCHID);//商户号
        $inputObj->SetNonce_str(self::getNonceStr());//随机字符串
        $inputObj->SetBill_type('MCHT');

        $inputObj->SetSign();//签名
        $xml = $inputObj->ToXml();

        $response = self::postXmlCurl($xml, $url, true, $timeOut);
        $result = WxPayResults::Init($response);
        return $result;
    }

    /**
     *
     * 产生随机字符串,不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public static function getNonceStr($length = 32) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 以post方式提交xml到对应的接口url
     *
     * @param string $xml 需要post的xml数据
     * @param string $url url
     * @param bool $useCert 是否需要证书,默认不需要
     * @param int $second url执行超时时间,默认30s
     * @throws WxPayException
     */
    private static function postXmlCurl($xml, $url, $useCert = false, $second = 30) {
        self::logPay($xml, "WXRedPack_XML");
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        //如果有配置代理这里就设置代理
        if (WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"
            && WxPayConfig::CURL_PROXY_PORT != 0
        ) {
            curl_setopt($ch, CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
            curl_setopt($ch, CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
        }
        curl_setopt($ch, CURLOPT_URL, $url);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
        //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);//严格校验
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if ($useCert == true) {
            $path = \Yii::getAlias('@webroot');
            $certPath = $path.'/../common/wxpayapi/cert/';
            //设置证书
            //使用证书:cert 与 key 分别属于两个.pem文件
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLCERT, $certPath.WxPayConfig::SSLCERT_PATH);
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($ch, CURLOPT_SSLKEY, $certPath.WxPayConfig::SSLKEY_PATH);
            //curl_setopt($ch,CURLOPT_CAPATH,$certPath);
            curl_setopt($ch,CURLOPT_CAINFO,$certPath.WxPayConfig::SSLCA_PATH);
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            self::logPay($data, "WXRedPack_XML_Response");
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            throw new WxPayException("curl出错,错误码:$error");
        }
    }
}