• 微信小程序发送红包功能。填坑记录


    微信官方文档

    1.开通条件

    (1)商户号已入驻90

    (2)商户号有连续30天正常交易

    (3)只有企业资质的商户才有资格申请

    2.注意事项

    (1)目前小程序红包仅支持用户微信扫码打开小程序

    (2)小程序开通了‘社交红包类目’或者处于违规状态时,将无法开发小程序红包

    (3)单日最高发放金额一百万元(可在商户平台设置)

    (4)单日每个用户可领取红包个数1-10(可在商户平台设置)

    (5)单日同一用户领取本商户红包金额 最高一千元(可在商户平台设置)

    (6)防刷等级:防刷是指微信风控针对微信小号、僵尸号、机器号等的拦截,你可以通过更改防刷等级控制防刷的强度(0级为关闭,13逐级递增安全等级);

    (7)要选择好红包发放场景,

    3.需要提供的信息

    (1)需提供商户证书(详情见4.4

    (2)微信支付分配的商户号

    (3)公众账号appid

    (4)商户名称(发送红包时,发送者名称)

    4.商户后台操作

    4.1 开通小程序红包权限

    在使用小程序红包之前,请前往开通小程序红包功能。操作路径:【登录微信支付商户平台——>产品中心——>小程序红包——>开通】

     

     

     

    4.2 首次开通时需要选择一个具体的小程序进行权限申请,如下图所示:

    其他需要开通权限的小程序,可在页面自行设置。操作路径如下:【登录商户平台——>产品中心——>小程序红包——>产品设置】。(注:“产品设置”操作按钮仅当你开通小程序红包功能之后才会出现)

    4.3 设置红包具体参数【登录商户平台——>产品中心——>小程序红包——>产品设置】(注:“产品设置”操作按钮仅当你开通小程序红包功能之后才会出现)。

     

    4.4 下载API证书

     

    4.5 商户平台商户号获取

     

     


     

    代码踩坑记录。

    1:POST请求时需要商户号证书的哦

    2.每个号测试的时候一天一个openID只能生成10个红包,怕测试失败  就把生成红包接口返回的$return['package']保存起来 生成红包全靠他了

    3.timeStamp' => time()."",  这个timeStamp必须是字符串,如果直接time(),用数字的话前端会报错请求不成功,而且wx.sendBizRedPacket()小程序的这个接口小程序开发文档里没有该接口文档,测试了下 FAIL回调方法里   不管什么错误   只会给你返回一个请求不成功,我就是没细心看文档被这个数字的时间戳搞死了  最后才发现是传的数字....

    4.urlencode($return['package'])  这个是生成签名的时候就 urlencode 然后传给小程序端

    5.签名的时候看好参数,和其他的接口不一样不要按老经验来,这里是用appId,timeStamp,nonceStr,package这4个参数生成签名,没有signType 这个参数,返回前端您的时候确实不需要APPID,需要SIGNTYPE.

    6.这里返回前端领取红包的签名最后不要转为大写

    7.wx.getLaunchOptionsSync()//获取场景代码   必须要用这个判断一下页面场景值,就是你通过什么方式进入的小程序,每个进入方法都有一个值,叫场景值.如果没有判断,那就是所有场景都生成红包,,哈哈这下你会发现 红包是生成了 可是领不了.除非你把每个package都保存起来,或者不是和我一样直接生成待领取..要不你冲的那点钱根本不够用...好像没有撤回红包方法,乖乖等24小时后退回把

    8.这个是最坑的一点,为什么写到最后,因为我也想让您们体验一下我的绝望.........这个红包只在1011,1025,1047,1124这四个场景值中触发,不用查资料弄这4个场景值是啥意思了    现在我就可以负责人的告诉你,   只能手机用摄像头扫   不要和我一样妄想着把图片放朋友圈  别人长按识别就能领取了.........你想到的方法我都试过了  一维码   二维码    小程序码   甚至一物一码   都只支持用摄像头扫,    长按和微信扫一扫在相册里扫都不行 都不触发...

    借鉴:https://developers.weixin.qq.com/community/develop/article/doc/000c6009a5cbd805d8790d4ab56013感谢这位大哥。

    /**发送红包接口*/
      public function createredpacket(){
            $url ='https://api.mch.weixin.qq.com/mmpaymkttransfers/sendminiprogramhb';//请求生成红包的网址
            $parameters =array(
                'nonce_str' => $this->createNoncestr(),//随机字符串,不长于32位 这个方法就是随机获得32位随机字符
                'mch_billno' => '23345807342710814',//商户订单号
                'mch_id' =>  $this->mch_id,//商户ID
                'wxappid' => $this->appid ,//小程序appid,这里不用文档的公众号APPID,直接填你的小程序APPID就行
                'send_name' => '我是土豪',//红包发送者名称
                're_openid'=>'oTPLE5J3****gEMJJ-UwLCwb4',//用户OpenId
                'total_amount'=>100,//付款金额,单位分
                'total_num'=>1,//红包发放总人数
                'wishing' =>'祝您万事大吉',//红包祝福语String(128)
                'act_name' =>'测试活动',//活动名称String(32)
                'remark'=>'恭喜你',//备注String(256)
                'notify_way' =>'MINI_PROGRAM_JSAPI',//通过JSAPI方式领取红包,小程序红包固定传MINI_PROGRAM_JSAPI
                // 'scene_id'=>'PRODUCT_1',
            );
            //统一下单签名
            $parameters['sign'] = $this->getSign($parameters);
    
            $xmlData = $this->arrayToXml($parameters);
            /* $res = $this->postXmlCurl($xmlData, $url, 60);*/
            $return = $this->xmlToArray($this->postXmlSSLCurl($xmlData, $url, 60));
            var_dump($return);
        }
    /**收到红包生成验签(这里应该是和发送红包连着用,为了记录,单独拿出来 写的验签)*/ 
    public function shou(){
            $parameters = array(
                'appId' => $this->appid, //小程序 ID
                'timeStamp' =>  time()."", //时间戳
                'nonceStr' => $this->createNoncestr(), //随机串
                'package' => urlencode('package'), //数据包--package是发送红包成功后返回的,
            );
            //生成签名
            $parameters['paySign'] = $this->getSign($parameters); //*****这里验签不需要转换大写
            return $parameters;
        }
    /**查看红包发送记录*/
      public function get_hb(){
            $url ='https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo';//请求生成红包的网址
            $parameters =array(
                'nonce_str' => $this->createNoncestr(),//随机字符串,不长于32位 这个方法就是随机获得32位随机字符
                'mch_billno' => '2334580734271081',//商户订单号
                'mch_id' =>  $this->mch_id,//商户ID
                'appid' => $this->appid ,//小程序appid,这里不用文档的公众号APPID,直接填你的小程序APPID就行
                'bill_type' =>'MCHT'//通过JSAPI方式领取红包,小程序红包固定传MINI_PROGRAM_JSAPI
    
            );
            //统一下单签名
            $parameters['sign'] = $this->getSign($parameters);
    
            $xmlData = $this->arrayToXml($parameters);
            /* $res = $this->postXmlCurl($xmlData, $url, 60);*/
            $return = $this->xmlToArray($this->postXmlSSLCurl($xmlData, $url, 60));
            var_dump($return);
        }
      //作用:生成签名
        private function getSign($Obj) {
            foreach ($Obj as $k => $v) {
                $Parameters[$k] = $v;
            }
            //签名步骤一:按字典序排序参数
            ksort($Parameters);
    
            $String = $this->formatBizQueryParaMap($Parameters, false);
            //签名步骤二:在 string 后加入 KEY
            $String = $String . "&key=" . $this->key;
    
            //签名步骤三:MD5 加密
            $String = md5($String);
            //签名步骤四:所有字符转为大写--根据接口需要打开限制
            $result_ = $String;
            // $result_ = strtoupper($String);
            return $result_;
        }
     //作用:产生随机字符串,不长于 32 位
        private function createNoncestr($length = 32) {
            $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
            $str = "";
            for ($i = 0; $i < $length; $i++) {
                $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
            } return $str;
        }
       /**
         * 作用:格式化参数,签名过程需要使用
         * @param $paraMap
         * @param $urlencode
         * @return string
         */
        private function formatBizQueryParaMap($paraMap, $urlencode) {
            $buff = "";
            ksort($paraMap);
            foreach ($paraMap as $k => $v) {
                if ($urlencode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
            $reqPar = "";
            if (strlen($buff) > 0) {
                $reqPar = substr($buff, 0, strlen($buff) - 1);
            }
            return $reqPar;
        }
      /**
         * 
         * 需要使用证书的请求
         * @param $xml
         * @param $url
         * @param int $second
         * @return bool|mixed
         */
        function postXmlSSLCurl($xml,$url,$second=30)
        {
            $ch = curl_init();
            //超时时间
            curl_setopt($ch,CURLOPT_TIMEOUT,$second);
            //这里设置代理,如果有的话
            //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
            //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
            curl_setopt($ch,CURLOPT_URL, $url);
            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);
            //设置证书
            //使用证书:cert 与 key 分别属于两个.pem文件
            //默认格式为PEM,可以注释
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, ROOT_PATH .'/cert/apiclient_cert.pem');
            //默认格式为PEM,可以注释
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, ROOT_PATH .'/cert/apiclient_key.pem');
            //post提交方式
            curl_setopt($ch,CURLOPT_POST, true);
            curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
            $data = curl_exec($ch);
            //返回结果
            if($data){
                curl_close($ch);
                return $data;
            }else {
                $error = curl_errno($ch);
                echo "curl出错,错误码:$error"."<br>";
                curl_close($ch);
                return false;
            }
        }
      /**
         * 数组转换成 xml
         * @param $arr
         * @return string
         */
        private function arrayToXml($arr) {
            $xml = "<xml>";
            foreach ($arr as $key => $val) {
                if (is_array($val)) {
                    $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
                } else {
                    $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
                }
            }
            $xml .= "</xml>";
            return $xml;
        }
    
    
        /**
         * xml 转换成数组
         * @param $xml
         * @return mixed
         */
        private function xmlToArray($xml) {
            //禁止引用外部 xml 实体
            libxml_disable_entity_loader(true);
            $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
            $val = json_decode(json_encode($xmlstring), true);
            return $val;
        }

    注:一定要看清楚代码踩坑记录里面的东西,代码是PHP的,如有错误请留言指正。觉得有帮助也可以支持一下。

     

     

     

  • 相关阅读:
    在页面中控制媒体流的起播点和播放长度
    缓冲区数据转换为字符串输出
    编程中注意的一个问题
    一个整合SQL语句的类
    注意服务器系统日期对防病毒软件的影响
    网络病毒源的排查(2005年3月22日维护记录)
    升级到 Microsoft .NET >Visual Basic 6.0 控件和 .NET 控件的区别
    修改您的站点设计以改善下载体验
    下一版本Windows&reg; CE 开发工具Smart Device Extensions for Microsoft Visual Studio&reg; .NET
    WINDOWS (服务器) 和 DOS(客户端) 网络互连 基于TCP/IP的编程实现
  • 原文地址:https://www.cnblogs.com/langgezuishuai/p/11980916.html
Copyright © 2020-2023  润新知