微信公众号开发之现金红包

作者: Javen205 | 来源:发表于2016-10-22 22:14 被阅读10820次

    欢迎留言、转发

    微信极速开发系列文章:点击这里

    前几篇文章介绍了微信支付。 公众号支付微信扫码支付刷卡支付微信买单

    此文来聊聊微信商户中的支付工具----现金红包

    现金红包.png

    准备工作

    【官方文档】

    一、开通现金红包权限

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

    二、下载API证书

    商户调用微信红包接口时,服务器会进行证书验证,请在商户平台下载证书

    现金红包-下载证书.png 现金红包-下载之后的文件.png

    有人要问这么多证书到底使用那个呢?跟开发语言有关系吗?

    什么语言使用什么证书,以及如何使用可以参考截图中的证书说明.txt

    内容如下:

    欢迎使用微信支付!
    微信支付API共四份(证书pkcs12格式、证书pem格式、证书密钥pem格式、CA证书),为接口中强制要求时需携带的证书文件。
    证书属于敏感信息,请妥善保管不要泄露和被他人复制。
    不同开发语言下的证书格式不同,以下为说明指引:
        证书pkcs12格式(apiclient_cert.p12)
            包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
            部分安全性要求较高的API需要使用该证书来确认您的调用身份
            windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID(如:10010000)
        证书pem格式(apiclient_cert.pem)
            从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
            部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
            您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
        证书密钥pem格式(apiclient_key.pem)
            从apiclient_cert.p12中导出密钥部分的文件,为pem格式
            部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
            您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
        CA证书(rootca.pem)
            微信支付api服务器上也部署了证明微信支付身份的服务器证书,您在使用api进行调用时也需要验证所调用服务器及域名的真实性
            该文件为签署微信支付证书的权威机构的根证书,可以用来验证微信支付服务器证书的真实性
            某些环境和工具已经内置了若干权威机构的根证书,无需引用该证书也可以正常进行验证,这里提供给您在未内置所必须根证书的环境中载入使用
    
    

    三、充值

    在发放现金红包之前,请确保你的资金充足。如若不足,请充值。操作路径:【登录商户平台——>账户中心——>资金管理——>充值】

    每个红包的平均金额必须在1.00元到200.00元之间

    现金红包-充值.png

    四、获取openid

    目前支持向指定微信用户的openid发放指定金额红包。(获取openid参见之前写的文章:极速开发微信公众号之授权获取用户信息

    五、相关参数设置

    和红包相关的参数【主要是安全方面:绑定IP、防止用户盗刷】,你可以在页面上自主设置和更改。
    操作路径如下:【登录商户平台——>产品中心——>现金红包——>产品设置】(注:“产品设置”操作按钮仅当你开通现金红包功能之后才会出现)。
    你可以设置和更改以下参数:

    现金红包-设置参数.png

    说明:
    1、 调用IP地址:设置之后,仅有已设置的IP地址可以调用,其余的IP调用会报错;
    2、用户领取上限:限制同一openid同一日领取的个数
    3、防刷等级:防刷是指微信风控针对微信小号、僵尸号、机器号等的拦截,你可以通过更改防刷等级控制防刷的强度。
    4、 同时,你也可以申请更改红包额度。但是需要经过微信支付的审核,审核通过之后才会生效。

    现金红包类别

    现金红包分为两类:
    1、普通红包 【官方文档】
    2、裂变红包 【官方文档】

    两者部分参数不同

    发送现金红包

    1、发送普通红包接口 com.javen.weixin.api.RedPackApi.java

    private static String sendRedPackUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
        
        /**
         * 发送红包
         * @param params 请求参数
         * @param certPath 证书文件目录
         * @param partner 证书密码
         * @return {String}
         */
        public static String sendRedPack(Map<String, String> params, String certPath, String partner) {
            return HttpUtils.postSSL(sendRedPackUrl, PaymentKit.toXml(params), certPath, partner);
        }
    

    2、发送裂变红包接口 com.javen.weixin.api.RedPackApi.java

    private static String sendGroupRedPackUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack";
        
        /**
         * 发送裂变红包
         * @param params 请求参数
         * @param certPath 证书文件目录
         * @param partner 证书密码
         * @return {String}
         */
        public static String sendGroupRedPack(Map<String, String> params, String certPath, String partner) {
            return HttpUtils.postSSL(sendGroupRedPackUrl, PaymentKit.toXml(params), certPath, partner);
        }
    

    具体实现封装 com.javen.utils.ReadPackUtils.java
    1、普通红包

    /**
         * 发送普通红包
         * @param request 获取IP
         * @param total_amount  付款现金(单位分)
         * @param total_num 红包发放总人数
         * @param wishing 红包祝福语
         * @param act_name 活动名称
         * @param remark 备注
         * @param reOpenid 用户openid
         * @param partner 商户号
         * @param wxappid 公众账号appid
         * @param sendName 商户名称
         * @param paternerKey 商户签名key
         * @param certPath 证书路径
         * @return
         */
        public static boolean sendredpack(HttpServletRequest request,String total_amount,String total_num,String wishing,String act_name,String remark,String reOpenid,String partner,String wxappid,String sendName,String paternerKey,String certPath) {
            // 商户订单号
            String mchBillno = System.currentTimeMillis() + "";
            String ip = IpKit.getRealIp(request);
    
            Map<String, String> params = new HashMap<String, String>();
            // 随机字符串
            params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
            // 商户订单号
            params.put("mch_billno", mchBillno);
            // 商户号
            params.put("mch_id", partner);
            // 公众账号ID
            params.put("wxappid", wxappid);
            // 商户名称
            params.put("send_name", sendName);
            // 用户OPENID
            params.put("re_openid", reOpenid);
            // 付款现金(单位分)
            params.put("total_amount", total_amount);
            // 红包发放总人数
            params.put("total_num", total_num);
            // 红包祝福语
            params.put("wishing", wishing);
            // 终端IP
            params.put("client_ip", ip);
            // 活动名称
            params.put("act_name", act_name );
            // 备注
            params.put("remark", remark);
            //创建签名
            String sign = PaymentKit.createSign(params, paternerKey);
            params.put("sign", sign);
    
            String xmlResult = RedPackApi.sendRedPack(params, certPath, partner);
            Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
            log.warn(JsonKit.toJson(result));
            //此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
            String return_code = result.get("return_code");
            //业务结果
            String result_code = result.get("result_code");
            
            if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
                return false;
            }
            if (StrKit.notBlank(result_code) && "SUCCESS".equals(result_code)) {
                
                return true;
            }
            return false;
        }
        
    

    2、裂变红包

    /**
         * 发送裂变红包
         * @param partner
         * @param wxappid
         * @param sendName
         * @param reOpenid
         * @param total_amount
         * @param total_num
         * @param wishing
         * @param act_name
         * @param remark
         * @param paternerKey
         * @param certPath
         * @return
         */
        public static boolean sendGroupRedPack(String partner, String wxappid, String sendName, String reOpenid, String total_amount, String total_num, String wishing, String act_name, String remark, String paternerKey, String certPath){
            // 商户订单号
            String mchBillno = System.currentTimeMillis() + "";
            
            Map<String, String> params = new HashMap<String, String>();
            // 随机字符串
            params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
            // 商户订单号
            params.put("mch_billno", mchBillno);
            // 商户号
            params.put("mch_id", partner);
            // 公众账号ID
            params.put("wxappid", wxappid);
            // 商户名称
            params.put("send_name", sendName);
            // 用户OPENID
            params.put("re_openid", reOpenid);
            // 付款现金(单位分)
            params.put("total_amount", total_amount);
            // 红包发放总人数
            params.put("total_num", total_num);
            //红包金额设置方式
            params.put("amt_type", "ALL_RAND");
            // 红包祝福语
            params.put("wishing", wishing);
            // 活动名称
            params.put("act_name", act_name );
            // 备注
            params.put("remark", remark);
            
            //创建签名
            String sign = PaymentKit.createSign(params, paternerKey);
            params.put("sign", sign);
            
            String xmlResult = RedPackApi.sendGroupRedPack(params, certPath, partner);
            Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
            log.warn(JsonKit.toJson(result));
            //此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
            String return_code = result.get("return_code");
            //业务结果
            String result_code = result.get("result_code");
            
            if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
                return false;
            }
            if (StrKit.notBlank(result_code) && "SUCCESS".equals(result_code)) {
                
                return true;
            }
            return false;
            
        }
    

    发送红包Demo

    /**
     * 微信红包demo
     * @author Javen
     * 2016年5月28日
     */
    public class RedPackApiController extends Controller {
        private static String sendName = "Javen205";
        //微信证书路径
        private static String certPath = "/Users/Javen/Downloads/cert/apiclient_cert.p12";
        //商户相关资料
        String wxappid = PropKit.get("appId");
        // 微信支付分配的商户号
        String partner = PropKit.get("mch_id");
        //API密钥
        String paternerKey = PropKit.get("paternerKey");
    
        /**
         * 发送普通红包
         */
        public void sendredpack() {
            
            boolean isSend = ReadPackUtils.sendredpack(getRequest(), "100", "1", "感谢您参加猜灯谜活动,祝您元宵节快乐!",
                    "猜灯谜抢红包活动", "猜越多得越多,快来抢!", "o_pncsidC-pRRfCP4zj98h6slREw",
                    partner, wxappid, sendName, paternerKey, certPath);
            
            renderJson(isSend);
        }
        /**
         * 发送裂变红包
         */
        public void sendGroupRedPack() {
            
            boolean isSend = ReadPackUtils.sendGroupRedPack(partner, wxappid, "天虹百货", "o_pncsidC-pRRfCP4zj98h6slREw", 
                    "100", "10", "感谢您参加猜灯谜活动,祝您元宵节快乐!", "猜灯谜抢红包活动",
                    "猜越多得越多,快来抢", paternerKey, certPath);
            
            
            renderJson(isSend);
        }
        
    
        public void query() {
            String query = ReadPackUtils.query("10000098201411111234567890", partner, wxappid, paternerKey, certPath);
            renderJson(query);
        }
    
    }
    

    查询红包记录

    【查询红包记录官方文档】

    接口封装com.javen.weixin.api.RedPackApi.java

    private static String getHBInfo = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo ";
        
        /**
         * 根据商户订单号查询信息
         * @param params 请求参数
         * @param certPath 证书文件目录
         * @param partner 证书密码
         * @return {String}
         */
        public static String getHbInfo(Map<String, String> params, String certPath, String partner) {
            return HttpUtils.postSSL(getHBInfo, PaymentKit.toXml(params), certPath, partner);
        }
    

    具体实现封装 com.javen.utils.ReadPackUtils.java

    /**
         * 根据商户订单号查询红包
         * @param mch_billno 商户订单号
         * @param partner 商户号
         * @param wxappid 公众账号ID
         * @param paternerKey 商户签名Key
         * @param certPath 证书路径
         * @return
         */
        public static String  query(String mch_billno,String partner,String wxappid,String paternerKey,String certPath) {
            Map<String, String> params = new HashMap<String, String>();
            // 随机字符串
            params.put("nonce_str", System.currentTimeMillis() / 1000 + "");
            // 商户订单号
            params.put("mch_billno", mch_billno);
            // 商户号
            params.put("mch_id", partner);
            // 公众账号ID
            params.put("appid", wxappid);
            params.put("bill_type", "MCHT");
            //创建签名
            String sign = PaymentKit.createSign(params, paternerKey);
            params.put("sign", sign);
    
            String xmlResult = RedPackApi.getHbInfo(params, certPath, partner);
            Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
            System.out.println(result);
            return JsonKit.toJson(result);
        }
    

    码字完毕,以上就是微信发送现金红包的详细介绍。

    欢迎留言、转发
    微信极速开发系列文章:http://www.jianshu.com/p/a172a1b69fdd
    此文章项目开源地址:极速开发微信公众号-Start支持项目发展

    相关文章

      网友评论

      • 司马轻雄:你好,请问一下,微信现金红包审核是区域审核还是总部审核?
        Javen205:@司马轻雄 管理审核,具体什么区域根据公司规来决定
      • 971214b00a73:你好,请教一下,公众服务号微信认证是未认证有没有办法实现现金红包呀
        Javen205:@昵称好难好难 没有认证是没有办法申请到微信支付的,也就没有红包接口可用。
      • 567e5d47508d:服务商怎么帮助商户开发微信现金红包功能?
        Javen205:@Clover_bcb7 商户模式与服务商模式发红包只是部分参数不一样 可以参考IJPay这个开源项目
      • bc20f6bb730d:您好,请假您一下。公司同时开通了两个公众号,A号是满足正常30天交易流水的,已经开通了现金红包的功能。B号没有交易,无法开通此功能。
        我们现在想用B号给一些关注了B号的用户发红包,可以用B号调用A号的API证书,然后给B号的用户发红包吗?
        bc20f6bb730d:@JJ_cdaf 这种情况的话,还有好的建议么?不胜感激!
        bc20f6bb730d:@Javen205 可是A号和B号两边拿到的用户open ID是不相通的,没办法直接用A号发。。。。
        Javen205:@JJ_cdaf 你可以直接使用A号发红包 测试试试 B号调用A号的证书发肯定是不行的
      • 04e8526a52dc:可以发一下红包的算法吗
        Javen205:@单线程_38fd 签名错误请检查你api key以及商户号是不是对应的
        efea430ba27b:你好,我在做微信公众号发现金红包,调用微信接口的时候返回的报文提示签名错误。请教一下这是什么原因呢?
        Javen205:@星空物语_c51b 红包算法这里没有涉及到
      • 葉者:转:smile:
      • 澄澈的蓝天呦:正好要做这个功能。果断看看。
      • b18779b910a9:不知有没其它方便快捷的支付方法实现app提现功能? :joy:
        b18779b910a9:@Javen205 如果申请提现人数较多的话,财务人工打款太慢。我就是想实现程序自动打款功能,现在红包接口用不了,那么自动打款就实现不了。
        Javen205:@billLee02 可以关联账号 达到一定数额申请提现 财务打款到绑定的账号或者程序实现 现在大部分app都是这样做的
      • b18779b910a9:你好,请问一下。为什么我登陆了商户平台,进入产品中心页面,没看到有“现金红包”可以申请开通的?“代金券”什么的都有,就现金红包没有。谢谢~
        b18779b910a9:@Javen205 刚才问了腾讯客服,说要有30天连续交易记录才能开通公众号红包接口 :sob: 。欲哭无泪,申请的过程中一直没提示有要求。我的app都开发好了,就差集成公众号红包接口一步。不知还有没其它方便快捷的支付方法
        Javen205:@billLee02 检查下你登陆的账号不是管理员账号?
      • b18779b910a9:就是相当于app有个提现功能,点击申请提现就通过微信公众号发现金红包给指定用户
        Javen205:@只有NO1 需要将微信公众号绑定到开发平台,在用户绑定微信时(授权获取用户个人信息时)会生成unionid,此unionid与App授权获取到的unionid是一样的。这样就可以关联到公众号的openid进行发红包提现了。

        近期在线交流活动如果感兴趣的话可以参与:http://gitbook.cn/gitchat/activity/59fa83751f102c456e9f8c59
        只有NO1:@Javen205 请问 如何根据UnionID来获取openId呢 没有找到对应的接口啊
        Javen205:@billLee02 提现到公众号是可以的,前提是需要你开放平台绑定微信公众号,使用UnionID机制来获取openId
      • b18779b910a9:您好,请教一下。怎么通过app(android)端控制公众号发送现金红包给指定用户?还有怎么获取、识别app端的特定用户openId?非常感谢~
        Javen205:@billLee02 微信开放平台是没有提供红包接口的 只有分享到朋友圈、发送给好友、微信支付、微信登录、卡券、智能接口 。所以只能通过公众号了。
        b18779b910a9:@Javen205 很感谢您的答复,大概懂了实现的流程。这些天一直在查找这方面的资料,知道实现公众号发现金红包功能,需要申请公众服务号,才能使用公众号红包接口。查过的资料都是在后台服务器调用红包接口的,可不可以直接在app端调用红包接口发送红包?谢谢~
        Javen205:@billLee02 第一、App可以在开放平台申请授权接口来获取用户的openid 第二、通过账号绑定微信公众号授权获取openid、App再根据账号从数据库查。再通过公众号的红包接口发送红包

      本文标题:微信公众号开发之现金红包

      本文链接:https://www.haomeiwen.com/subject/ncuhuttx.html