[PHP+JS]微信卡券(潦草笔记,全代码,亲测通过)

群发卡券可以通过客服消息推送

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140547

 

后端代码:

define('APPID', 'xxxxxxxxxxxxxxxx');
define('SECRET', 'xxxxxxxxxxxxxxxx');
$publicToken = null;

if($do == 'test') {
    set_time_limit(0);
    $openId = 'xxxxxxxxxxxxxxxx';

    //$account = account_fetch($_W['acid']);
    //$account['key'], $account['secret']

    echo '<pre>';
    $publicToken = WxPublic_AccessToken(APPID, SECRET);
    echo 'AccessToken' . PHP_EOL;
    print_r($publicToken);

    if($publicToken != null && $publicToken['expires_datetime'] >= time()) {
        // 创建前获取公众号的全部卡券
        $result = WxPublic_Card_BatchGet($publicToken['access_token']);
        echo 'BatchGet' . PHP_EOL;
        print_r($result);
        if($result['errcode'] == '0') {
            $cardIdList = $result['card_id_list'];

            $codes = array();
            for($i = 1; $i <= 5; $i++) {
                $codes[] = strval(10000 + $i);
            }
            foreach($cardIdList as $cardId) {
                $result = WxPublic_Card_Get($publicToken['access_token'], $cardId);
                echo 'Get' . PHP_EOL;
                print_r($result);

                $result = WxPublic_Card_CheckCode($publicToken['access_token'], $cardId, $codes);
                echo 'CheckCode' . PHP_EOL;
                print_r($result);
            }

            $result = WxPublic_Card_CardInfo($publicToken['access_token'], date('Y-m-d', strtotime('-62 day')), date('Y-m-d', strtotime('-1 day')), 0);
            echo 'CardInfo-0' . PHP_EOL;
            print_r($result);

            $result = WxPublic_Card_CardInfo($publicToken['access_token'], date('Y-m-d', strtotime('-62 day')), date('Y-m-d', strtotime('-1 day')), 1);
            echo 'CardInfo-1' . PHP_EOL;
            print_r($result);
        }

    /*
        // ========================================

        $aPath = realpath(dirname(__FILE__) . './test.jpg');
        $cardImage = WxPublic_Card_Uploadimg($publicToken['access_token'], $aPath);
        //if($cardImage !== null && isset($cardImage['url'])) {
            echo 'Uploadimg' . PHP_EOL;
            print_r($cardImage);
        //}

        // ========================================


        // 使用GET_CUSTOM_CODE_MODE_DEPOSIT模式创建卡券
        // 用法参考:https://blog.csdn.net/u011738153/article/details/50457167
        // 1.quantity初始值设置为0,设置use_custom_code=true,get_custom_code_mode='GET_CUSTOM_CODE_MODE_DEPOSIT'
        // 2.审核后添加code
        // 3.修改库存,<= code数量
        $card = WxPublic_Card_Create_Groupon(
            $publicToken['access_token'],
            'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
            '微信餐厅',
            '132元双人火锅套餐',
            '020-88888888',
            '不可与其他优惠同享\r\n如需团购券发票,请在消费时向商户提出\r\n店内均可使用,仅限堂食',
            date('Y-m-d', strtotime('-1 day')),
            date('Y-m-d', strtotime('+1 year')),
            '以下锅底2选1(有菌王锅、麻辣锅、大骨锅、番茄锅、清补 凉锅、酸菜鱼锅可选):\n大锅1份 12元\n小锅2份 16元',
            2
        );
        // $card = WxPublic_Card_Create_Cash(
        //     $publicToken['access_token'],
        //     'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
        //     '微信餐厅',
        //     '020-88888888',
        //     '不可与其他优惠同享\r\n如需团购券发票,请在消费时向商户提出\r\n店内均可使用,仅限堂食',
        //     date('Y-m-d', strtotime('-1 day')),
        //     date('Y-m-d', strtotime('+1 year')),
        //     1000,
        //     10000,
        //     2
        // );
        // $card = WxPublic_Card_Create_Discount(
        //     $publicToken['access_token'],
        //     'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
        //     '微信餐厅',
        //     '132元双人火锅套餐',
        //     '020-88888888',
        //     '不可与其他优惠同享\r\n如需团购券发票,请在消费时向商户提出\r\n店内均可使用,仅限堂食',
        //     date('Y-m-d', strtotime('-1 day')),
        //     date('Y-m-d', strtotime('+1 year')),
        //     30,
        //     2
        // );
        // $card = WxPublic_Card_Create_Gift(
        //     $publicToken['access_token'],
        //     'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
        //     '微信餐厅',
        //     '132元双人火锅套餐',
        //     '020-88888888',
        //     '不可与其他优惠同享\r\n如需团购券发票,请在消费时向商户提出\r\n店内均可使用,仅限堂食',
        //     date('Y-m-d', strtotime('-1 day')),
        //     date('Y-m-d', strtotime('+1 year')),
        //     '可兑换音乐木盒一个',
        //     2
        // );
        // $card = WxPublic_Card_Create_GeneralCoupon(
        //     $publicToken['access_token'],
        //     'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0',
        //     '微信餐厅',
        //     '132元双人火锅套餐',
        //     '020-88888888',
        //     '不可与其他优惠同享\r\n如需团购券发票,请在消费时向商户提出\r\n店内均可使用,仅限堂食',
        //     date('Y-m-d', strtotime('-1 day')),
        //     date('Y-m-d', strtotime('+1 year')),
        //     '优惠券专用,填写优惠详情',
        //     2
        // );

        echo 'Create' . PHP_EOL;
        print_r($card);
        if($card['errcode'] == '0' && isset($card['card_id'])) {

            $codes = array();
            for($i = 1; $i <= 5; $i++) {
                $codes[] = strval(10000 + $i);
            }

            if(count($codes) > 0) {
                $codeResult = WxPublic_Card_AddCode($publicToken['access_token'], $card['card_id'], $codes);
                if($codeResult['errcode'] == '0') {
                    $countResult = WxPublic_Card_CodeCount($publicToken['access_token'], $card['card_id']);
                    if($countResult['errcode'] == '0' && intval($countResult['count']) > 0)
                        WxPublic_Card_ModifyStock($publicToken['access_token'], $card['card_id'], intval($countResult['count']));
                    else
                        throw new Exception('卡券修改库存失败:' . json_encode($countResult));
                } else {
                    throw new Exception('卡券添加code失败:' . json_encode($codeResult));
                }
            }

            // 失败
            // $result = WxPublic_Card_CodeUpdate($publicToken['access_token'], $codes[count($codes) - 1], '99999', $cardIdList[count($cardIdList) - 1]);
            // echo 'CodeUpdate' . PHP_EOL;
            // print_r($result);

            $result = WxPublic_Card_CheckCode($publicToken['access_token'], $cardIdList[count($cardIdList) - 1], $codes);
            echo 'CheckCode' . PHP_EOL;
            print_r($result);

            $result = WxPublic_Card_Get($publicToken['access_token'], $card['card_id']);
            echo 'Get' . PHP_EOL;
            print_r($result);

            $result = WxPublic_Card_QrcodeCreate($publicToken['access_token'], $card['card_id']);
            echo 'QrcodeCreate' . PHP_EOL;
            print_r($result);
        } else {
            throw new Exception('创建卡券失败:' . json_encode($card));
        }

        // ========================================

        // 需要客户领取后才能有数据
        $result = WxPublic_Card_UserCardList($publicToken['access_token'], $openId, $cardIdList[count($cardIdList) - 1]);
        echo 'UserCardList' . PHP_EOL;
        print_r($result);

        // 需要客户领取后才能查询
        $result = WxPublic_Card_CodeGet($publicToken['access_token'], $cardIdList[count($cardIdList) - 1], $codes[0]);
        echo 'CodeGet' . PHP_EOL;
        print_r($result);
        if($result['errcode'] == '0' && $result['can_consume'] == true) {
            // 需要客户领取后才能核销
            $result = WxPublic_Card_CodeConsume($publicToken['access_token'], $cardIdList[count($cardIdList) - 1], $codes[0]);
            echo 'CodeConsume' . PHP_EOL;
            print_r($result);
        }

        // ========================================

        for($i = 0; $i < count($cardIdList);++$i) {
            for($j = 0; $j < count($codes);++$j) {
                // 需要客户领取后才能失效,已使用的不能失效
                $result = WxPublic_Card_CodeUnavailable($publicToken['access_token'], $cardIdList[$i], $codes[$j], '用户发生退款');
                echo 'Unavailable:' . $cardIdList[$i] . '-' . $codes[$j] . PHP_EOL;
                print_r($result);
            }

            $result = WxPublic_Card_Delete($publicToken['access_token'], $cardIdList[$i]);
            echo 'Delete:' . $cardIdList[$i] . PHP_EOL;
            print_r($result);
        }

        $result = WxPublic_Card_BizuinInfo($publicToken['access_token'], date('Y-m-d', strtotime('-62 day')), date('Y-m-d', strtotime('-1 day')), 0);
        echo 'BizuinInfo-0' . PHP_EOL;
        print_r($result);

        $result = WxPublic_Card_BizuinInfo($publicToken['access_token'], date('Y-m-d', strtotime('-62 day')), date('Y-m-d', strtotime('-1 day')), 1);
        echo 'BizuinInfo-1' . PHP_EOL;
        print_r($result);
    */
    }
    echo '</pre>';

    template('pad/test');
    exit();
} elseif($do == 'wx_authority_signature') {
    $publicToken = WxPublic_AccessToken(APPID, SECRET);
    if($publicToken != null && $publicToken['expires_datetime'] >= time()) {
        exit(json_encode(Wx_AuthoritySignature($publicToken, $_GPC['url'])));
    }
    exit();
} elseif($do == 'wx_getcard') {
    // https://mp.weixin.qq.com/s/WhYpWmfuhUBw2wseTXdt2A
    // http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=cardsign
    $publicToken = WxPublic_AccessToken(APPID, SECRET);
    if($publicToken != null && $publicToken['expires_datetime'] >= time()) {
        $result = WxPublic_Card_BatchGet($publicToken['access_token']);
        if($result['errcode'] == '0') {
            $codes = array();
            for($i = 1; $i <= 5; ++$i) {
                $codes[] = strval(10000 + $i);
            }

            $data = array();
            foreach ($result['card_id_list'] as $cardId) {
                for($i = 0; $i < count($codes); ++$i) {
                    $signature = Wx_CardSignature($publicToken['access_token'], $cardId);
                    $data[] = array(
                      'api_ticket' => $signature['api_ticket'],
                        'card_id' => $signature['card_id'],
                        'card_ext' => array(  // 全部字段传出去,别管有没有值
                          'code' => empty($signature['code']) ? null : $signature['code'],
                          'openid' => empty($signature['openid']) ? null : $signature['openid'],
                            'timestamp' => $signature['timestamp'],
                            'nonce_str' => $signature['nonce_str'],
                            'signature' => $signature['signature'],
                            'plaintext' => $signature['plaintext'],
                        )
                    );
                }
            }
            exit(json_encode(array_slice($data, 0, 5)));  // 官方:只能一次领5张,超出报错
        }
        exit(json_encode($result));  // 输出错误
    }
    exit(json_encode('获取Token失败'));
}

function curl_get($url) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);    // 跳过验证证书
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);    // 跳过验证主机
    curl_setopt($curl, CURLOPT_HEADER, false);
    //curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json;charset=\'utf-8\''));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($curl);
    curl_close($curl);

    return ($data === FALSE) ? null : json_decode($data, true);
}
function curl_jsonPost($url, $data) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);    // 跳过验证证书
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);    // 跳过验证主机
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
    $data = curl_exec($curl);
    curl_close($curl);

    return ($data === FALSE) ? null : json_decode($data, true);
}
function WxPublic_AccessToken($appid, $secret) {
    static $cache = array();
    $name = strtoupper('__ACCESSTOKEN_' . sha1($appid . $secret) . '__');
    $data = isset($cache[$name]) ? $cache[$name] : null;

    if($data == null || $data['expires_datetime'] <= time()) {
        $data = curl_get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret);
        $data['expires_datetime'] = time() + intval($data['expires_in'] * 0.9); // 提前过期
        $cache[$name] = $data;
    }

    return $data;

    /*
    $name = strtoupper('__ACCESSTOKEN_' . sha1($appid . $secret) . '__');
    $data = isset($_COOKIE[$name]) ? json_decode($_COOKIE[$name], true) : null;

    if($data == null || $data['expires_datetime'] <= time()) {
        $data = curl_get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret);
        $data['expires_datetime'] = time() + intval($data['expires_in'] * 0.9); // 提前过期
        setcookie($name, json_encode($data), $data['expires_datetime'], '/', $_SERVER['HTTP_HOST']);
    }

    return $data;
    */

    /*
    static $cache = array();

    $key = sha1($appid . $secret);
    if(!isset($cache[$key]) || $cache[$key]['expires_datetime'] <= time()) {
        $cache[$key] = curl_get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret);
        $cache[$key]['expires_datetime'] = time() + intval($cache[$key]['expires_in'] * 0.9); // 提前过期
    }

    return $cache[$key];
    */
}

function WxPublic_Card_Uploadimg($publicToken, $file_path) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=' . $publicToken);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);    // 跳过验证证书
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);    // 跳过验证主机
    curl_setopt($curl, CURLOPT_HEADER, false);
    // curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json;charset=\'utf-8\''));    // 注意http头,发送失败也是一个原因,这个是个失败案例
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $aPath = realpath($file_path);
    if (class_exists('\CURLFile')) {
        curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true);
        $data = array('buffer' => new \CURLFile($aPath));    // >= 5.5
    } else {
        if (defined('CURLOPT_SAFE_UPLOAD'))
            curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false);
        $data = array('buffer' => '@' . $aPath);    // <= 5.5
    }

    if(!empty($data)) {
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }

    $data = curl_exec($curl);
    curl_close($curl);

    return ($data === FALSE) ? null : json_decode($data, true);
}

function WxPublic_Card_Create_Groupon($publicToken, $logoUrl, $brandName, $title, $servicePhone, $description, $beginDatetime, $endDatetime, $dealDetail = '', $getLimit = 1, $useLimit = 50, $canShare = true, $canGiveFriend = true) {
    $url = 'https://api.weixin.qq.com/card/create?access_token=' . $publicToken;
    $data = array(
        'card' => array(
            'card_type' => 'GROUPON',
            'groupon' => array(
                'base_info' => array(
                    'logo_url' => $logoUrl,  // 300*300
                    'brand_name' => $brandName,
                    'code_type' => 'CODE_TYPE_QRCODE',
                    'title' => $title,
                    'color' => 'Color010',
                    'notice' => '使用时向服务员出示此券',
                    'service_phone' => $servicePhone,
                    'description' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $description),
                    'date_info' => array(
                        'type' => 'DATE_TYPE_FIX_TIME_RANGE',
                        'begin_timestamp' => strtotime($beginDatetime),
                        'end_timestamp' => strtotime($endDatetime)
                    ),
                    'sku' => array(
                        'quantity' => 0
                    ),
                    'get_limit' => $getLimit,
                    'use_limit' => $useLimit,
                    'bind_openid' => false,
                    'can_share' => !!$canShare,
                    'can_give_friend' => !!$canGiveFriend,

                    // GET_CUSTOM_CODE_MODE_DEPOSIT用法,参考:https://blog.csdn.net/u011738153/article/details/50457167
                    'use_custom_code' => true,
                    'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT',
                ),
                'deal_detail' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $dealDetail)
            )
        )
    );
    return curl_jsonPost($url, $data);
    /*
    if($card['errcode'] == '0' && isset($card['card_id'])) {
        if(count($codes) > 0) {
            $codeResult = WxPublic_Card_AddCode($publicToken, $card['card_id'], $codes);
            if($codeResult['errcode'] == '0') {
                $countResult = WxPublic_Card_CodeCount($publicToken, $card['card_id']);
                if($countResult['errcode'] == '0' && intval($countResult['count']) > 0)
                    WxPublic_Card_ModifyStock($publicToken, $card['card_id'], intval($countResult['count']));
                else
                    throw new Exception('卡券修改库存失败:' . json_encode($countResult));
            } else {
                throw new Exception('卡券添加code失败:' . json_encode($codeResult));
            }
        }
        return $card['card_id'];
    }
    throw new Exception('创建卡券失败:' . json_encode($card));
    */
}
function WxPublic_Card_Create_Cash($publicToken, $logoUrl, $brandName, $servicePhone, $description, $beginDatetime, $endDatetime, $reduceCost, $leastCost = 0, $getLimit = 1, $useLimit = 50, $canShare = true, $canGiveFriend = true) {
    $url = 'https://api.weixin.qq.com/card/create?access_token=' . $publicToken;
    $data = array(
        'card' => array(
            'card_type' => 'CASH',
            'cash' => array(
                'base_info' => array(
                    'logo_url' => $logoUrl,
                    'brand_name' => $brandName,
                    'code_type' => 'CODE_TYPE_QRCODE',
                    'color' => 'Color070',
                    'notice' => '使用时向服务员出示此券',
                    'service_phone' => $servicePhone,
                    'description' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $description),
                    'date_info' => array(
                        'type' => 'DATE_TYPE_FIX_TIME_RANGE',
                        'begin_timestamp' => strtotime($beginDatetime),
                        'end_timestamp' => strtotime($endDatetime)
                    ),
                    'sku' => array(
                        'quantity' => 0
                    ),
                    'get_limit' => $getLimit,
                    'use_limit' => $useLimit,
                    'bind_openid' => false,
                    'can_share' => !!$canShare,
                    'can_give_friend' => !!$canGiveFriend,

                    // GET_CUSTOM_CODE_MODE_DEPOSIT用法,参考:https://blog.csdn.net/u011738153/article/details/50457167
                    'use_custom_code' => true,
                    'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT',
                ),
                'least_cost' => $leastCost,
                'reduce_cost' => $reduceCost,
            )
        )
    );
    return curl_jsonPost($url, $data);
}
function WxPublic_Card_Create_Discount($publicToken, $logoUrl, $brandName, $title, $servicePhone, $description, $beginDatetime, $endDatetime, $discount, $getLimit = 1, $useLimit = 50, $canShare = true, $canGiveFriend = true) {
    $url = 'https://api.weixin.qq.com/card/create?access_token=' . $publicToken;
    $data = array(
        'card' => array(
            'card_type' => 'DISCOUNT',
            'discount' => array(
                'base_info' => array(
                    'logo_url' => $logoUrl,
                    'brand_name' => $brandName,
                    'code_type' => 'CODE_TYPE_QRCODE',
                    'title' => $title,
                    'color' => 'Color030',
                    'notice' => '使用时向服务员出示此券',
                    'service_phone' => $servicePhone,
                    'description' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $description),
                    'date_info' => array(
                        'type' => 'DATE_TYPE_FIX_TIME_RANGE',
                        'begin_timestamp' => strtotime($beginDatetime),
                        'end_timestamp' => strtotime($endDatetime)
                    ),
                    'sku' => array(
                        'quantity' => 0
                    ),
                    'get_limit' => $getLimit,
                    'use_limit' => $useLimit,
                    'use_custom_code' => false,
                    'bind_openid' => false,
                    'can_share' => !!$canShare,
                    'can_give_friend' => !!$canGiveFriend,

                    // GET_CUSTOM_CODE_MODE_DEPOSIT用法,参考:https://blog.csdn.net/u011738153/article/details/50457167
                    'use_custom_code' => true,
                    'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT',
                ),
                'discount' => $discount
            )
        )
    );
    return curl_jsonPost($url, $data);
}
function WxPublic_Card_Create_Gift($publicToken, $logoUrl, $brandName, $title, $servicePhone, $description, $beginDatetime, $endDatetime, $gift = '', $getLimit = 1, $useLimit = 50, $canShare = true, $canGiveFriend = true) {
    $url = 'https://api.weixin.qq.com/card/create?access_token=' . $publicToken;
    $data = array(
        'card' => array(
            'card_type' => 'GIFT',
            'gift' => array(
                'base_info' => array(
                    'logo_url' => $logoUrl,
                    'brand_name' => $brandName,
                    'code_type' => 'CODE_TYPE_QRCODE',
                    'title' => $title,
                    'color' => 'Color050',
                    'notice' => '使用时向服务员出示此券',
                    'service_phone' => $servicePhone,
                    'description' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $description),
                    'date_info' => array(
                        'type' => 'DATE_TYPE_FIX_TIME_RANGE',
                        'begin_timestamp' => strtotime($beginDatetime),
                        'end_timestamp' => strtotime($endDatetime)
                    ),
                    'sku' => array(
                        'quantity' => 0
                    ),
                    'get_limit' => $getLimit,
                    'use_limit' => $useLimit,
                    'bind_openid' => false,
                    'can_share' => !!$canShare,
                    'can_give_friend' => !!$canGiveFriend,

                    // GET_CUSTOM_CODE_MODE_DEPOSIT用法,参考:https://blog.csdn.net/u011738153/article/details/50457167
                    'use_custom_code' => true,
                    'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT',
                ),
                'gift' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $gift)
            )
        )
    );
    return curl_jsonPost($url, $data);
}
function WxPublic_Card_Create_GeneralCoupon($publicToken, $logoUrl, $brandName, $title, $servicePhone, $description, $beginDatetime, $endDatetime, $defaultDetail = '', $getLimit = 1, $useLimit = 50, $canShare = true, $canGiveFriend = true) {
    $url = 'https://api.weixin.qq.com/card/create?access_token=' . $publicToken;
    $data = array(
        'card' => array(
            'card_type' => 'GENERAL_COUPON',
            'general_coupon' => array(
                'base_info' => array(
                    'logo_url' => $logoUrl,
                    'brand_name' => $brandName,
                    'code_type' => 'CODE_TYPE_QRCODE',
                    'title' => $title,
                    'color' => 'Color090',
                    'notice' => '使用时向服务员出示此券',
                    'service_phone' => $servicePhone,
                    'description' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $description),
                    'date_info' => array(
                        'type' => 'DATE_TYPE_FIX_TIME_RANGE',
                        'begin_timestamp' => strtotime($beginDatetime),
                        'end_timestamp' => strtotime($endDatetime)
                    ),
                    'sku' => array(
                        'quantity' => 0
                    ),
                    'get_limit' => $getLimit,
                    'use_limit' => $useLimit,
                    'bind_openid' => false,
                    'can_share' => !!$canShare,
                    'can_give_friend' => !!$canGiveFriend,

                    // GET_CUSTOM_CODE_MODE_DEPOSIT用法,参考:https://blog.csdn.net/u011738153/article/details/50457167
                    'use_custom_code' => true,
                    'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT',
                ),
                'default_detail' => str_replace(array('\r\n', '\r', '\n'), chr(13) . chr(10), $defaultDetail)
            )
        )
    );
    return curl_jsonPost($url, $data);
}

function WxPublic_Card_AddCode($publicToken, $cardId, $codes) {
    $url = 'http://api.weixin.qq.com/card/code/deposit?access_token=' . $publicToken;
    $data = array(
   'card_id' => $cardId,
   'code' => $codes
    );

    return curl_jsonPost($url, $data);
}
function WxPublic_Card_CodeCount($publicToken, $cardId) {
    $url = 'http://api.weixin.qq.com/card/code/getdepositcount?access_token=' . $publicToken;
    $data = array(
   'card_id' => $cardId
    );

    return curl_jsonPost($url, $data);
}
function WxPublic_Card_ModifyStock($publicToken, $cardId, $increase = 0, $reduce = 0) {
    $url = 'https://api.weixin.qq.com/card/modifystock?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'increase_stock_value' => $increase,
        'reduce_stock_value' => $reduce,
    );

    return curl_jsonPost($url, $data);
}
function WxPublic_Card_CheckCode($publicToken, $cardId, $codes) {
    $url = 'http://api.weixin.qq.com/card/code/checkcode?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'code' => $codes
    );

    return curl_jsonPost($url, $data);
}

function WxPublic_Card_BatchGet($publicToken) {
    $url = 'https://api.weixin.qq.com/card/batchget?access_token=' . $publicToken;
    $data = array(
        'offset' => 0,
        'count' => 50,
        'status_list' => array(
            // 'CARD_STATUS_NOT_VERIFY',  // 待审核
            // 'CARD_STATUS_VERIFY_FAIL',  // 审核失败
            'CARD_STATUS_VERIFY_OK',  // 通过审核
            // 'CARD_STATUS_DELETE',  // 卡券被商户删除
            // 'CARD_STATUS_DISPATCH'  // 在公众平台投放过的卡券
        )
    );

    return curl_jsonPost($url, $data);
}
function WxPublic_Card_Get($publicToken, $cardId) {
    $url = 'https://api.weixin.qq.com/card/get?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId
    );

    return curl_jsonPost($url, $data);
}
function WxPublic_Card_Delete($publicToken, $cardId) {
    $url = 'https://api.weixin.qq.com/card/delete?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId
    );

    return curl_jsonPost($url, $data);
}

// 重点:use_custom_code=true和get_custom_code_mode=GET_CUSTOM_CODE_MODE_DEPOSIT时,不需要传code生成(PS:不带code可以一码多人领取)
function WxPublic_Card_QrcodeCreate($publicToken, $cardId, $code = '', $openId = '', $outerStr = '') {
    $url = 'https://api.weixin.qq.com/card/qrcode/create?access_token=' . $publicToken;
    $data = array(
        'action_name' => 'QR_CARD',
        'expire_seconds' => 0,
        'action_info' => array(
            'card' => array(
                'card_id' => $cardId,
                'code' => $code,
                'openid' => $openId,
                'is_unique_code' => false,
                'outer_str' => $outerStr
            )
        )
    );

    return curl_jsonPost($url, $data);
}

// 需要客户领取后才能有数据
function WxPublic_Card_UserCardList($publicToken, $openId, $cardId = '') {
    $url = 'https://api.weixin.qq.com/card/user/getcardlist?access_token=' . $publicToken;
    $data = array(
        'openid' => $openId,
        'card_id' => $cardId
    );

    return curl_jsonPost($url, $data);
}
// 需要客户领取后才能查询
function WxPublic_Card_CodeGet($publicToken, $cardId, $code) {
    $url = 'https://api.weixin.qq.com/card/code/get?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'code' => $code,
        'check_consume' => true
    );

    return curl_jsonPost($url, $data);
}
// 需要客户领取后才能核销
function WxPublic_Card_CodeConsume($publicToken, $cardId, $code) {
    $url = 'https://api.weixin.qq.com/card/code/consume?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'code' => $code
    );

    return curl_jsonPost($url, $data);
}
// 需要客户领取后才能失效,已使用的不能失效
function WxPublic_Card_CodeUnavailable($publicToken, $cardId, $code, $reason = '') {
    $url = 'https://api.weixin.qq.com/card/code/unavailable?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'code' => $code,
        'reason' => $reason
    );

    return curl_jsonPost($url, $data);
}

/*
// 失败
function WxPublic_Card_CodeUpdate($publicToken, $code, $new_code, $cardId = null) {
    $url = 'https://api.weixin.qq.com/card/code/update?access_token=' . $publicToken;
    $data = array(
        'card_id' => $cardId,
        'code' => $code,
        'new_code' => $new_code,
    );

    return curl_jsonPost($url, $data);
}
*/

// $beginDate必须是<=62,$endDate必须是小于今天
function WxPublic_Card_BizuinInfo($publicToken, $beginDate, $endDate, $condSource) {
    $url = 'https://api.weixin.qq.com/datacube/getcardbizuininfo?access_token=' . $publicToken;
    $data = array(
        'begin_date' => $beginDate,
        'end_date' => $endDate,
        'cond_source' => $condSource
    );

    return curl_jsonPost($url, $data);
}

function WxPublic_Card_CardInfo($publicToken, $beginDate, $endDate, $condSource, $cardId = null) {
    $url = 'https://api.weixin.qq.com/datacube/getcardcardinfo?access_token=' . $publicToken;
    $data = array(
        'begin_date' => $beginDate,
        'end_date' => $endDate,
        'cond_source' => $condSource,
        'card_id' => $cardId
    );

    return curl_jsonPost($url, $data);
}

function WxPublic_Card_CodeDecrypt($publicToken, $encryptCode) {
    $url = 'https://api.weixin.qq.com/card/code/decrypt?access_token=' . $publicToken;
    $data = array(
        'encrypt_code' => $encryptCode
    );

    return curl_jsonPost($url, $data);
}

// ========================================

function WxJsApi_GetTicket($publicToken, $type) {
    static $cache = array();
    $name = strtoupper('__TICKET_' . sha1($publicToken . $type) . '__');
    $data = isset($cache[$name]) ? $cache[$name] : null;

    if($data == null || $data['expires_datetime'] <= time()) {
        // jsapi:jsapi_ticket
        // wx_card:api_ticket
        $data = curl_get('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $publicToken . '&type=' . $type);
        $data['expires_datetime'] = time() + intval($data['expires_in']);
        $cache[$name] = $data;
    }

    return $data;
}

// ========================================
// 权限签名算法
// ========================================
// 签名生成规则如下:
// 参与签名的字段包括有效的
//   jsapi_ticket:获取方式详见微信JSSDK文档
//   noncestr:随机字符串,由开发者随机生成
//   timestamp:由开发者生成的当前时间戳)
//   url:当前网页的URL,不包含#及其后面部分。注意:对于没有只有域名没有path的URL,浏览器会自动加上/作为path
// 对所有待签名参数按照字段名的ASCII码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符
// 接下来对string1作sha1加密,字段名和字段值都采用原始值,不进行URL转义。即signature=sha1(string1)
function Wx_AuthoritySignature($publicToken, $url) {
    $ticket = WxJsApi_GetTicket($publicToken, 'jsapi');
    if($ticket != null && $ticket['expires_datetime'] >= time()) {
        static $cache = array();
        $name = strtoupper('__AUTHORITYSIGNATURE_' . sha1($ticket['ticket'] . $url) . '__');
        $data = isset($cache[$name]) ? $cache[$name] : null;

        if($data == null || $ticket['expires_datetime'] <= time()) {
            $input = array(
                'jsapi_ticket' => $ticket['ticket'],
                'noncestr' => sha1(uniqid(microtime(true), true)),
                'timestamp' => time(),
                'url' => $url
            );

            $data = array(
                'appid' => APPID,
              'noncestr' => $input['noncestr'],
              'timestamp' => $input['timestamp'],
              'signature' => sha1('jsapi_ticket=' . $input['jsapi_ticket'] . '&noncestr=' . $input['noncestr'] . '&timestamp=' . $input['timestamp'] . '&url=' . $input['url']),  // 必须按小写字段名升序排序
              //'plaintext' => 'jsapi_ticket=' . $input['jsapi_ticket'] . '&noncestr=' . $input['noncestr'] . '&timestamp=' . $input['timestamp'] . '&url=' . $input['url'],
            );

            $cache[$name] = $data;
        }

        return $data;
    }
    return null;
}
// ========================================
// 卡券签名算法
// ========================================
// 重点:use_custom_code=true和get_custom_code_mode=GET_CUSTOM_CODE_MODE_DEPOSIT时,不需要传code进行签名
// 重点:code和openid是空字符串时,只能传null或不传给wx.addCard,否则报出参数错误
function Wx_CardSignature($publicToken, $cardId, $code = '', $openId = '') {
    $ticket = WxJsApi_GetTicket($publicToken, 'wx_card');
    if($ticket != null && $ticket['expires_datetime'] >= time()) {
        static $cache = array();
        $name = strtoupper('__CARDSIGNATURE_' . sha1($ticket['ticket'] . $cardId . $code . $openId) . '__');
        $data = isset($cache[$name]) ? $cache[$name] : null;

        if($data == null || $ticket['expires_datetime'] <= time()) {
            $input = array(
                'api_ticket' => $ticket['ticket'],
                'timestamp' => time(),
                'nonce_str' => sha1(uniqid(microtime(true), true)),
                'card_id' => $cardId,
                'code' => strval($code),
                'openid' => $openId,
            );

            asort($input, SORT_STRING);  // 按键值升序排序

            $data = array(
              'api_ticket' => $input['api_ticket'],
              'timestamp' => $input['timestamp'],
              'nonce_str' => $input['nonce_str'],
              'card_id' => $input['card_id'],
              'code' => (!isset($input['code']) || empty($input['code'])) ? null : $input['code'],
              'openid' => (!isset($input['openid']) || empty($input['openid'])) ? null : $input['openid'],
              'signature' => sha1(implode('', $input)),
              //'plaintext' => implode(';', $input),
            );

            $cache[$name] = $data;
        }

        return $data;
    }
    return null;
}

 

前端代码:

<!doctype html>
<html class="w-100 h-100">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0, shrink-to-fit=no" />
<meta name="format-detection" content="telephone=no" />
<title>测试</title>
</head>
<body>

<script type="text/javascript" src="{$_W['siteroot']}app/resource/pad/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<script type="text/javascript">
// https://www.cnblogs.com/ka-bu-qi-nuo/p/8659688.html
$(function() {
    $.ajax({
        url: '{url "pad/store_pad/wx_authority_signature" array("store" => $_GPC["store"])}',
        type: 'GET',
        dataType: 'json',
        data: {
            'url': encodeURIComponent(window.location.href.split('#')[0])  // 获取最新url
        },
        success: function(signData) {
            wx.config({
              debug: true,  // true时,即使正确也会提示签名无效,这是官方bug
              appId: signData.appid,
              timestamp: signData.timestamp,
              nonceStr: signData.noncestr,
              signature: signData.signature,
              jsApiList: [
                    // 'updateAppMessageShareData',
                    // 'updateTimelineShareData',
                    // 'onMenuShareTimeline',  // 即将废弃
                    // 'onMenuShareAppMessage',  // 即将废弃
                    // 'onMenuShareQQ',  // 即将废弃
                    // 'onMenuShareWeibo',
                    // 'onMenuShareQZone',
                    // 'startRecord',
                    // 'stopRecord',
                    // 'onVoiceRecordEnd',
                    // 'playVoice',
                    // 'pauseVoice',
                    // 'stopVoice',
                    // 'onVoicePlayEnd',
                    // 'uploadVoice',
                    // 'downloadVoice',
                    // 'chooseImage',
                    // 'previewImage',
                    // 'uploadImage',
                    // 'downloadImage',
                    // 'translateVoice',
                    // 'getNetworkType',
                    // 'openLocation',
                    // 'getLocation',
                    // 'hideOptionMenu',
                    // 'showOptionMenu',
                    // 'hideMenuItems',
                    // 'showMenuItems',
                    // 'hideAllNonBaseMenuItem',
                    // 'showAllNonBaseMenuItem',
                    // 'closeWindow',
                    // 'scanQRCode',
                    // 'chooseWXPay',
                    // 'openProductSpecificView',
                    'addCard',
                    // 'chooseCard',
                    // 'openCard',
              ]
            });

            wx.ready(function() {
                wx.checkJsApi({
                    jsApiList: ['addCard'],
                    success: function(res1) {
                        //alert(JSON.stringify(res1));
                        if(res1.checkResult.addCard) {
                            $.ajax({
                                url: '{url "pad/store_pad/wx_getcard" array("store" => $_GPC["store"])}',
                                type: 'GET',
                                dataType: 'json',
                                success: function(signData2) {
                                    if(typeof(signData2['errcode']) === 'undefined' || signData2['errcode'] == '0') {
                                        var cardList = [];
                                        for(var i = 0; i < signData2.length; ++i) {
                                            cardList.push({
                                                cardId: signData2[i].card_id,
                                                cardExt: JSON.stringify({  // 全部字段赋上,别管有没有值
                                                    code: signData2[i].card_ext.code,
                                                    openid: signData2[i].card_ext.openid,
                                                    timestamp: signData2[i].card_ext.timestamp,
                                                    nonce_str: signData2[i].card_ext.nonce_str,
                                                    signature: signData2[i].card_ext.signature
                                                })
                                            });
                                        }
                                        if(cardList.length > 0) {
                                            wx.addCard({
                                                cardList: cardList, // 需要添加的卡券列表
                                                success: function (res2) {
                                                    var cardList = res2.cardList; // 添加的卡券列表信息
                                                    alert(JSON.stringify(cardList));
                                                }
                                            });
                                        }
                                    } else {
                                        alert('获取失败\r\nCode:' + signData2['errcode'] + '\r\nMessage:' . signData2['errmsg']);
                                    }
                                }
                            });
                        } else {
                            alert('不支持addCard!');
                        }
                    }
                });

            

                /*
                wx.checkJsApi({
                    jsApiList: ['scanQRCode'],
                    success: function(res) {
                        //alert(JSON.stringify(res));
                        if(res.checkResult.scanQRCode) {
                            alert('支持scanQRCode');
                        } else {
                            alert('不支持scanQRCode!');
                        }
                    }
                });

                wx.checkJsApi({
                    jsApiList: [
                        'updateAppMessageShareData',
                        'updateTimelineShareData',
                    ],
                    success: function(res) {
                        //alert(JSON.stringify(res));
                        if(res.checkResult.updateAppMessageShareData) {
                            alert('支持分享到朋友/QQ');
                            / *
                            wx.updateAppMessageShareData({
                          title: '分享标题',
                          desc: '分享描述',
                          link: signData.url,
                          imgUrl: '{$_W["siteroot"]}favicon.png',
                          success: function () {
                              alert('分享到朋友/QQ成功');
                          }
                        });
                        * /
                        } else {
                            alert('不支持分享到朋友/QQ');
                        }

                        if(res.checkResult.updateAppMessageShareData) {
                            alert('支持分享到朋友圈/QQ空间');
                            / *
                        wx.updateTimelineShareData({ 
                          title: '分享标题',
                          link: signData.url,
                          imgUrl: '{$_W["siteroot"]}favicon.png',
                          success: function () {
                              alert('分享到朋友圈/QQ空间成功');
                          }
                        });
                        * /
                        } else {
                            alert('不支持分享到朋友圈/QQ空间');
                        }
                    }
                });

                wx.checkJsApi({
                    jsApiList: ['openCard'],
                    success: function(res) {
                        //alert(JSON.stringify(res));
                        if(res.checkResult.openCard) {
                            alert('支持openCard!');
                        } else {
                            alert('不支持openCard!');
                        }
                    }
                });
                */
            });
         
            wx.error(function(res) {
                alert('初始化失败!');
            });
        }
    });
});
</script>
<script type="text/javascript">
/**
 * @param {String}  errorMessage   错误信息
 * @param {String}  scriptURI      出错的文件
 * @param {Long}    lineNumber     出错代码的行号
 * @param {Long}    columnNumber   出错代码的列号
 * @param {Object}  errorObj       错误的详细信息,Anything
 */
window.onerror = function(errorMessage, scriptURI, lineNumber, columnNumber, errorObj) {
    var msg = '';
    var CRLF = String.fromCharCode(13) + String.fromCharCode(10);
    msg += '错误信息:' + errorMessage + CRLF;
    msg += '出错文件:' + scriptURI + '(' + lineNumber + ',' + columnNumber + ')' + CRLF;
    msg += '错误详情:' + errorObj;
    alert(msg);
}
</script>
</body>
</html>

 

posted @ 2019-01-25 09:40  炎峰森林影  阅读(2110)  评论(0编辑  收藏  举报