微信现金红包实例

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

require_once(APP_PATH.'vendor/autoload.php');
use GuzzleHttp\Client;
use DOMDocument;

class wxapiv2_model
{
    protected $merchantId = '';
    protected $apiv2Key = '';
    protected $privateKeyPath = APP_PATH . 'weixinzhifu/apiclient_key.pem';
    protected $certificatePath = APP_PATH . 'weixinzhifu/apiclient_cert.pem';

    public function sendRedpack()
    {
        // 1. 构造请求数据
        $data = [
            'nonce_str'         => $this->generateNonceStr(),
            'mch_billno'        => $this->generateBillNo(),
            'mch_id'            => $this->merchantId,
            'wxappid'           => '',
            'send_name'         => '',
            're_openid'         => '',
            'total_amount'      => 100,
            'total_num'         => 1,
            'wishing'           => '恭喜发财',
            'act_name'          => '新人送好礼活动',
            'remark'            => '邀请好友关注闰土吃瓜,还有更多惊喜等着你',
            //'scene_id'          => 'PRODUCT_1',
        ];

        // 2. 签名
        $data['sign'] = $this->makeSign($data);

        // 3. 构造 XML
        $xml = $this->arrayToXml($data);

        // 4. 发起请求
        $client = new Client([
            'base_uri' => 'https://api.mch.weixin.qq.com',
            'verify' => true,
            'timeout' => 10,
            'cert' => $this->certificatePath,
            'ssl_key' => $this->privateKeyPath,
            'headers' => [
                'Content-Type' => 'application/xml',
                'Accept' => 'application/xml',
            ]
        ]);

        $response = $client->post('/mmpaymkttransfers/sendredpack', [
            'body' => $xml,
        ]);

        // 5. 解析响应
        return $this->xmlToArray($response->getBody()->getContents());
    }

    // 生成随机字符串
    protected function generateNonceStr($length = 32)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    // 生成订单号(建议用时间 + 随机)
    protected function generateBillNo()
    {
        return $this->merchantId . date('YmdHis') . rand(1000, 9999);
    }

    // 签名
    protected function makeSign($data)
    {
        ksort($data);
        $string = urldecode(http_build_query($data) . '&key=' . $this->apiv2Key);
        return strtoupper(md5($string));
    }

    // 数组转 XML
    protected function arrayToXml($data)
    {
        $xml = new DOMDocument();
        $root = $xml->createElement('xml');
        foreach ($data as $key => $value) {
            if (is_numeric($value)) {
                $node = $xml->createElement($key, $value);
            } else {
                $node = $xml->createElement($key, htmlspecialchars($value));
            }
            $root->appendChild($node);
        }
        $xml->appendChild($root);
        return $xml->saveXML();
    }

    // XML 转数组
    protected function xmlToArray($xml)
    {
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }
}