1. 程式人生 > 實用技巧 >公眾號給使用者發紅包

公眾號給使用者發紅包

場景:公眾號裡面,通過指定openid給使用者傳送紅包,比如使用者在公眾號中提現,發福利紅包都可以使用。

直接上程式碼:

class wxHongbao
{
    // 商戶id
    private $mch_id = '********';

    // 訂單號
    private $mch_billno = '';

    // 公眾號id
    private $wxappid = '';

    // 呼叫介面機器ip
    private $client_ip = '';

    // 商戶平臺金鑰
    private $apikey = '';

    // 紅包發放人數
    private $total_num = 1;

    // 紅包傳送者名稱
    private $send_name = '正義的程式猿';

    // 祝福語
    private $wishing = '歡迎再次參與';

    // 活動名稱
    private $act_name = '';

    // 備註
    private $remark = '';

    // 隨機字串
    private $nonce_str = '';

    // 接收使用者的openid
    private $re_openid = '';

    //紅包金額,單位 分
    private $total_amount = 1;

    // 簽名
    private $sign;

    /**
     * 活動資訊
     * @var array
     */
    private $risk_info;

    // 發放紅包使用場景,紅包金額大於200或者小於1元時必傳
    // PRODUCT_1:商品促銷
    // PRODUCT_2:抽獎
    // PRODUCT_3:虛擬物品兌獎
    // PRODUCT_4:企業內部福利
    // PRODUCT_5:渠道分潤
    // PRODUCT_6:保險回饋
    // PRODUCT_7:彩票派獎
    // PRODUCT_8:稅務刮獎
    private $scene_id;

    // 證書
    private $apiclient_cert;
    private $apiclient_key;
    private $apiclient_ca;

    private $api_hb_single = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

    /**
     * wxHongbao constructor.
     */
    public function __construct()
    {
        // todo 初始化證書目錄
        $this->apiclient_cert = '';
        $this->apiclient_key  = '';
        $this->apiclient_ca   = '';
    }

    /**
     * @return string
     */
    public function getSendName()
    {
        return $this->send_name;
    }

    /**
     * @param string $send_name
     * @return $this
     */
    public function setSendName($send_name)
    {
        $this->send_name = $send_name;
        return $this;
    }

    /**
     * @return string
     */
    public function getWishing()
    {
        return $this->wishing;
    }

    /**
     * @param string $wishing
     * @return $this
     */
    public function setWishing($wishing)
    {
        $this->wishing = $wishing;
        return $this;
    }

    /**
     * @return string
     */
    public function getActName()
    {
        return $this->act_name;
    }

    /**
     * @param string $act_name
     * @return $this
     */
    public function setActName($act_name)
    {
        $this->act_name = $act_name;
        return $this;
    }

    /**
     * @return string
     */
    public function getRemark()
    {
        return $this->remark;
    }

    /**
     * @param string $remark
     * @return  $this
     */
    public function setRemark($remark)
    {
        $this->remark = $remark;
        return $this;
    }

    /**
     * @return string
     */
    public function getReOpenid()
    {
        return $this->re_openid;
    }

    /**
     * @param string $re_openid
     * @return $this
     */
    public function setReOpenid($re_openid)
    {
        $this->re_openid = $re_openid;
        return $this;
    }

    /**
     * @return int
     */
    public function getTotalAmount()
    {
        return $this->total_amount;
    }

    /**
     * 紅包金額,單位 分
     * @param int $total_amount
     * @return $this
     */
    public function setTotalAmount($total_amount)
    {
        $this->total_amount = (int)$total_amount;
        return $this;
    }

    /**
     * 建立紅包
     * @param $openid string
     * @param $amount int 紅包金額,單位分
     * @return $this
     */
    public function createHongbao($openid, $amount)
    {
        if (! $openid) {
            throw new \InvalidArgumentException('openid error');
        }

        if ($amount <= 0) {
            throw new \InvalidArgumentException('amount error');
        }

        $this->generate_nonce_str();
        $this->generate_mch_billno();
        $this->setReOpenid($openid);
        $this->setTotalAmount($amount);

        return $this;
    }

    /**
     * 傳送紅包
     * @return bool
     */
    public function send()
    {
        $this->generate_sign();

        $data = $this->generate_xml_params();

        $data_obj = $this->https_request($this->api_hb_single, $data);

        if ($data_obj->return_code === 'SUCCESS' && $data_obj->result_code === 'SUCCESS') {
            $log = json_encode((array)$data_obj);
            error_log(sprintf("[%s]\twx hongbao send success.\tmch_billno:%s\tret:%s", date("Y-m-d H:i:s"), $this->mch_billno, $log));

            return true;
        }

        $log = json_encode((array)$data_obj);
        error_log(sprintf("[%s]\twx hongbao send failed.\tmch_billno:%s\tret:%s", date("Y-m-d H:i:s"), $this->mch_billno, $log));

        return false;
    }

    private function generate_xml_params()
    {
        $xml = "<xml>
                <sign><![CDATA[{$this->sign}]]></sign>
                <mch_billno><![CDATA[{$this->mch_billno}]]></mch_billno>
                <mch_id><![CDATA[{$this->mch_id}]]></mch_id>
                <wxappid><![CDATA[{$this->wxappid}]]></wxappid>
                <send_name><![CDATA[{$this->send_name}]]></send_name>
                <re_openid><![CDATA[{$this->re_openid}]]></re_openid>
                <total_amount><![CDATA[{$this->total_amount}]]></total_amount>
                <total_num><![CDATA[{$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><![CDATA[{$this->nonce_str}]]></nonce_str>";

        if ($this->scene_id) {
            $xml .= "<scene_id><![CDATA[{$this->scene_id}]]></scene_id>";
        }

        if ($this->risk_info) {
            $rsk = http_build_query($this->risk_info);
            $rsk = urlencode($rsk);
            $xml .= "<risk_info>{$rsk}</risk_info>";
        }

        $xml .= "</xml>";

        return $xml;
    }

    // 生成簽名
    private function generate_sign()
    {
        $params = array(
            'nonce_str' => $this->nonce_str,
            'mch_billno'=> $this->mch_billno,
            'mch_id'    => $this->mch_id,
            'wxappid'   => $this->wxappid,
            'send_name' => $this->send_name,
            're_openid' => $this->re_openid,
            'total_amount' => $this->total_amount,
            'total_num' => $this->total_num,
            'wishing'   => $this->wishing,
            'client_ip' => $this->client_ip,
            'act_name'  => $this->act_name,
            'remark'    => $this->remark
        );

        if ($this->scene_id) {
            $params['scene_id'] = $this->scene_id;
        }

        if ($this->risk_info) {
            $rsk = http_build_query($this->risk_info);
            $params['risk_info'] = urlencode($rsk);
        }

        ksort($params);

        $params['key'] = $this->apikey;

        $s = http_build_query($params);

        $this->sign = strtoupper(md5($s));
    }


    // 隨機字串
    private function generate_nonce_str($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $chars_len = strlen($chars);
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= $chars[mt_rand(0, $chars_len - 1)];
        }

        $this->nonce_str = $str;
    }

    // 訂單號
    private function generate_mch_billno()
    {
        $s = substr($this->getReOpenid(), -4);

        $this->mch_billno = date('YmdHis') . $s;
    }

    private function https_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//        curl_setopt($curl, CURLOPT_TIMEOUT, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_SSLCERT, $this->apiclient_cert);
        curl_setopt($curl, CURLOPT_SSLKEY, $this->apiclient_key);
        curl_setopt($curl, CURLOPT_CAINFO, $this->apiclient_ca);

        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        $data = curl_exec($curl);
        curl_close($curl);

        return simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
    }
}

程式碼中引入這個類,需要配置一下商戶id$mch_id,關聯的公眾號$wxappid,伺服器的公網ip$client_ip,還有$apikey,然後在建構函式中配置下證書,就能直接用了:

$hongbao = new wxHongbao();
$hongbao->createHongbao('xxxx', 100)->send();

Happy Coding~