【微信公众号发红包转账】微信公众号上手机网页接收请求,通过公众号给用户发红包 开发流程

有了微信支付 的开发做铺垫,相关的微信其他业务处理起来逻辑就能清晰很多。

 

准备好这两个架包

 

---------------------------------------------------------------------------------------------------1.微信公众号发红包 开发流程图----------------------------------------------------------------------------------------------

 

-----------------------------------------------------------------------------------------------2.红包实体-----------------------------------------------------------------------------------------------------

package net.shopxx.wx.redPackage;

/**
 * 微信公众号   发红包实体
 * @author SXD
 *
 */
public class RedPack {

        /**
         * 随机字符串
         * 随机字符串,不长于32位
         */
         private String nonce_str;
         /**
          * 签名
          */
        private String sign;
        /**
         * 商户订单号
         * 商户订单号(每个订单号必须唯一。取值范围:0~9,a~z,A~Z)接口根据商户订单号支持重入,如出现超时可再调用。
         */
        private String mch_billno;
        /**
         * 商户号
         * 微信支付分配的商户号
         */
        private String mch_id;
        /**
         * 公众账号
         * 微信分配的公众账号ID(企业号corpid即为此appId)
         */
        private String wxappid;
        /**
         * 商户名称
         * 红包发送者名称
         */
        private String send_name;
        /**
         * 用户openid
         * 接受红包的用户
         * 用户在wxappid下的openid
         */
        private String re_openid;
        /**
         * 付款金额 单位:分
         * 100 == 1元钱 ,也就是说 这里的 1 相当于1分钱
         * 微信发送红包不少于1元钱
         */
        private int total_amount;
        /**
         * 红包发放总人数
         */
        private int total_num;
        /**
         * 红包祝福语
         */
        private String wishing;
        /**
         * Ip地址
         * 调用接口的机器Ip地址
         */
        private String client_ip;
        /**
         * 活动名称
         */
        private String act_name;
        /**
         * 备注
         */
        private String remark;
        public String getNonce_str() {
            return nonce_str;
        }
        public void setNonce_str(String nonce_str) {
            this.nonce_str = nonce_str;
        }
        public String getSign() {
            return sign;
        }
        public void setSign(String sign) {
            this.sign = sign;
        }
        public String getMch_billno() {
            return mch_billno;
        }
        public void setMch_billno(String mch_billno) {
            this.mch_billno = mch_billno;
        }
        public String getMch_id() {
            return mch_id;
        }
        public void setMch_id(String mch_id) {
            this.mch_id = mch_id;
        }
        public String getWxappid() {
            return wxappid;
        }
        public void setWxappid(String wxappid) {
            this.wxappid = wxappid;
        }
        public String getSend_name() {
            return send_name;
        }
        public void setSend_name(String send_name) {
            this.send_name = send_name;
        }
        public String getRe_openid() {
            return re_openid;
        }
        public void setRe_openid(String re_openid) {
            this.re_openid = re_openid;
        }
        public int getTotal_amount() {
            return total_amount;
        }
        public void setTotal_amount(int total_amount) {
            this.total_amount = total_amount;
        }
        public int getTotal_num() {
            return total_num;
        }
        public void setTotal_num(int total_num) {
            this.total_num = total_num;
        }
        public String getWishing() {
            return wishing;
        }
        public void setWishing(String wishing) {
            this.wishing = wishing;
        }
        public String getClient_ip() {
            return client_ip;
        }
        public void setClient_ip(String client_ip) {
            this.client_ip = client_ip;
        }
        public String getAct_name() {
            return act_name;
        }
        public void setAct_name(String act_name) {
            this.act_name = act_name;
        }
        public String getRemark() {
            return remark;
        }
        public void setRemark(String remark) {
            this.remark = remark;
        }

}

View Code

-----------------------------------------------------------------------------------------------3.服务器端处理  逻辑---------------------------------------------------------------------------------------

package net.shopxx.wx.redPackage;

import java.util.Map;
import java.util.UUID;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;

import net.shopxx.wx.pay.HttpConnection;
import net.shopxx.wx.pay.WeXinUtil;
import net.shopxx.wx.pay.XmlUtil;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.internal.platform.Platform;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/wx/SendRedPack")
public class SendRedPackController {

    /**
     * 公众账号ID
     */
    @Value("${member.appid}")
    private String APPID;
    /**
     * 商户号
     */
    private String MCHID;
    /**
     * key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
     */
    private String KEY;
    private XmlUtil xmlUtil = new XmlUtil();

    /**
     * ②接收请求
     * @param request
     * @param open_id
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("/sendRedPack")
    public void sendRedPack(HttpServletRequest request,String open_id) throws Exception{
        RedPack pack = new RedPack();
        pack.setAct_name("活动名称111");
        pack.setClient_ip(WeXinUtil.getIp(request));
        pack.setMch_billno("order_id");
        pack.setMch_id(MCHID);
         String nonce = UUID.randomUUID().toString().replaceAll("-", "");
        pack.setNonce_str(nonce);
        pack.setRe_openid(open_id);
        pack.setRemark("备注信息");
        pack.setSend_name("商户名称:谁发的红包");
        pack.setTotal_amount(1000);
        pack.setTotal_num(1);
        pack.setWishing("红包祝福语");
        pack.setWxappid(APPID);
        String sign = WeXinUtil.createUnifiedOrderSign(pack,KEY);
        pack.setSign(sign);

        /**
         * 转成XML格式 微信可接受的格式
         */
        xmlUtil.getXstreamInclueUnderline().alias("xml", pack.getClass());
        String xml = xmlUtil.getXstreamInclueUnderline().toXML(pack);

        //发起请求前准备
        RequestBody body = RequestBody.create(MediaType.parse("text/xml;charset=UTF-8"), xml);
        Request req = new Request.Builder()
                .url("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack")
                .post(body)
                .build();
        //为http请求设置证书
        SSLSocketFactory socketFactory = WeXinUtil.getSSL().getSocketFactory();
        X509TrustManager x509TrustManager = Platform.get().trustManager(socketFactory);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().sslSocketFactory(socketFactory, x509TrustManager).build();
        //得到输出内容
        /**
         *③ ④ 解析结果,判断是否红包发送成功
         */
        Response response = okHttpClient.newCall(req).execute();
        String content = response.body().string();
        Map<String, String> responseMap = xmlUtil.parseXML(content);
        if("SUCCESS".equals(responseMap.get("return_code"))){
            System.out.println("红包发送成功");
            System.out.println("签名"+responseMap.get("sign")+"业务结果"+responseMap.get("result_code"));
            if("SUCCESS".equals(responseMap.get("result_code"))){
                System.out.println("商户订单号"+responseMap.get("mch_billno")+
                        "商户号"+responseMap.get("mch_id")+
                        "公众账号appid"+responseMap.get("wxappid")+
                        "用户openid"+responseMap.get("re_openid")+
                        "付款金额"+responseMap.get("total_amount")+
                        "微信单号"+responseMap.get("send_listid"));
            }
        }else{
            System.out.println("红包发送失败");
        }

    }

}

View Code

-----------------------------------------------------------------------------------------------4.XML工具类--------------------------------------------------------------------------------------------------

package net.shopxx.wx.pay;

import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 微信支付   微信公众号发红包
 * 封装/解析xml消息的工具类
 * @author SXD
 *
 */
public class XmlUtil {

    public XStream getXstreamInclueUnderline(){
         XStream stream = new XStream(new XppDriver(new NoNameCoder()) {

             @Override
             public PrettyPrintWriter createWriter(Writer out) {
                 return new PrettyPrintWriter(out) {
                     // 对所有xml节点的转换都增加CDATA标记
                     boolean cdata = true;

                     @Override
                     @SuppressWarnings("rawtypes")
                     public void startNode(String name, Class clazz) {
                         super.startNode(name, clazz);
                     }

                     @Override
                     public String encodeNode(String name) {
                         return name;
                     }

                     @Override
                     protected void writeText(QuickWriter writer, String text) {
                         if (cdata) {
                             writer.write("<![CDATA[");
                             writer.write(text);
                             writer.write("]]>");
                         } else {
                             writer.write(text);
                         }
                     }
                 };
             }
         });

         return stream;
    }

    /**
     * 根据字符串 解析XML map集合
     * @param xml
     * @return
     * @throws DocumentException
     */
    public Map<String, String> parseXML(String xml) throws DocumentException{
        Document document = DocumentHelper.parseText(xml);
        Element element =document.getRootElement();
        List<Element> childElements = element.elements();
        Map<String,String> map = new HashMap<String, String>();

        map = getAllElements(childElements,map);

        map.forEach((k,v)->{
            System.out.println(k+">>>>"+v);
        });

        return map;
    }
    /**
     * 获取 子节点的被迭代方法
     * @param childElements
     * @param mapEle
     * @return
     */
    private Map<String, String> getAllElements(List<Element> childElements,Map<String,String> mapEle) {
        for (Element ele : childElements) {
            if(ele.elements().size()>0){
                mapEle = getAllElements(ele.elements(), mapEle);
            }else{
                mapEle.put(ele.getName(), ele.getText());
            }
        }
        return mapEle;
    }

}

View Code

-----------------------------------------------------------------------------------------------5.微信工具类---------------------------------------------------------------------------------------------------

package net.shopxx.wx.pay;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import javax.net.ssl.SSLContext;
import javax.security.cert.CertificateException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.ssl.SSLContexts;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

/**
 * 微信支付  微信公众号发红包
 * 工具类
 * @author SXD
 *
 */
public class WeXinUtil {

    /**
     * 获取用户IP
     * @param request
     * @return
     */
    public static String getIp(HttpServletRequest request){
        String ipAddress = null;
         if (request.getHeader("x-forwarded-for") == null) {
             ipAddress = request.getRemoteAddr();
         }else{
            if(request.getHeader("x-forwarded-for").length()  > 15){
                String [] aStr = request.getHeader("x-forwarded-for").split(",");
                ipAddress = aStr[0];
            } else{
                ipAddress = request.getHeader("x-forwarded-for");
            }
         }
         return ipAddress;
    }

    /**
     * 签名算法,生成统一下单中 必填项签名
     * @param unifiedOrder  1.将统一下单实体中各个字段拼接  2.MD5加密  3.全部转化为大写
     * @return    返回经过签名算法生成的签名 sign
     * 第一步的规则
     *     ◆ 参数名ASCII码从小到大排序(字典序);
     *    ◆ 如果参数的值为空不参与签名;
     *    ◆ 参数名区分大小写;
     *    ◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
     *    ◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
     */

    /* 手动拼接方式
    public String createUnifiedOrderSign(Unifiedorder unifiedOrder){
        StringBuffer sign = new StringBuffer();
        sign.append("appid=").append(unifiedOrder.getAppid());
        sign.append("&body=").append(unifiedOrder.getBody());
        sign.append("&mch_id=").append(unifiedOrder.getMch_id());
        sign.append("&nonce_str=").append(unifiedOrder.getNonce_str());
        sign.append("&notify_url=").append(unifiedOrder.getNotify_url());
        sign.append("&openid=").append(unifiedOrder.getOpenid());
        sign.append("&out_trade_no=").append(unifiedOrder.getOut_trade_no());
        sign.append("&spbill_create_ip=").append(unifiedOrder.getSpbill_create_ip());
        sign.append("&total_fee=").append(unifiedOrder.getTotal_fee());
        sign.append("&trade_type=").append(unifiedOrder.getTrade_type());
        sign.append("&key=").append(KEY);

        return DigestUtils.md5Hex(sign.toString()).toUpperCase();
    }
    */

    /**
     * 拼接生成sign 签名
     * @param unifiedOrder
     * @param KEY
     * @return
     * @throws Exception
     */
     public static String createUnifiedOrderSign(Object object,String KEY) throws Exception{
            StringBuffer sign = new StringBuffer();
            Map<String, String> map = getSortMap(object);

            boolean isNotFirst = false;

            for (Map.Entry<String, String> entry : map.entrySet()) {
                if(isNotFirst == true){
                    sign.append("&");
                }else{
                    isNotFirst = true;
                }

                sign.append(entry.getKey()).append("=").append(entry.getValue());
            }
            sign.append("&key=").append(KEY);

            return DigestUtils.md5Hex(sign.toString()).toUpperCase();

        }

     /**
      * 使用java反射机制,动态获取对象的属性和参数值,排除值为null的情况,并按字典序排序
      * @param object
      * @return
      * @throws Exception
      */
     private static Map<String, String> getSortMap(Object object) throws Exception{
            Field[] fields = object.getClass().getDeclaredFields();
            Map<String, String> map = new HashMap<String, String>();

            for(Field field : fields){
                 String name = field.getName();
                 String methodName = "get" + name.replaceFirst(name.substring(0, 1), name.substring(0, 1)
                         .toUpperCase());
                 // 调用getter方法获取属性值
//                 Method getter = object.getClass().getMethod(methodName);
//                 String value =  getter.invoke(object)+"";
                 field.setAccessible(true);
                 Object value = field.get(object);
                 if (value != null){
                     map.put(name, value.toString());
                 }
            }

            Map<String, String> sortMap = new TreeMap<String, String>(
                    new Comparator<String>() {
                        @Override
                        public int compare(String arg0, String arg1) {

                            return arg0.compareTo(arg1);
                        }
                    });
            sortMap.putAll(map);
            return sortMap;
        }

     public static SSLContext getSSL() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException, java.security.cert.CertificateException {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            //证书位置  放在自己的项目下面
            Resource resource = new ClassPathResource("apiclient_cert.p12");
            InputStream instream = resource.getInputStream();
            try {
                keyStore.load(instream, "填写证书密码,默认为商户号".toCharArray());
            } finally {
                instream.close();
            }
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, "填写证书密码,默认为商户号".toCharArray())
                    .build();
            return sslcontext;
        }

}

View Code

 

----------------------------------------------------------------------------------------------至此,微信公众号 发送红包   【待完善】---------------------------------------------------------------

 

时间: 2024-08-26 18:11:57

【微信公众号发红包转账】微信公众号上手机网页接收请求,通过公众号给用户发红包 开发流程的相关文章

微信公众号怎么设置摇一摇发红包,微信摇一摇发红包教程

微信公众号摇一摇发红包怎么设置 准备工作: 一个已开通微信支付的公众号 已申请"微信摇一摇·周边"的功能 佰睿Hibeacon(ibeacon终端设备) 智能手机(支持蓝牙4.0) 微信对公众号只开放了摇一摇红包的接口,要实现摇一摇发红包的功能需要调用红包接口进行开发,由于大多数用户不具备开发能力,通常选择第三方平台的功能应用.首先,我们要打开第三方平台的首页登录. 登录账号之后,首先选择授权绑定好公众号,然后选择公众号信息右侧的"功能管理",进入后台的管理中心页面

从陈坤微信号说起:微信公众平台开发者的江湖

  陈坤的微信公众号这段时间大火,企鹅君其实也想发表点意见的,但无奈不懂娱乐圈,姿势不够只有看的份. 不过看来看去吧,发现个问题:大家关注陈坤微信号如何圈钱的同时,就没想过问下,这个微信公众号到底谁做的? 如果你的答案是:当然是微信或者陈坤做的啊. 那我要恭喜你了,将此文好好读下去,涨姿势的时候到了. 1.南派三叔和陈坤微信号幕后推手:微信代开发公司 企鹅君此前写过个文章,大致意思是"南派三叔微信号改变网络文学玩法",内文提到过,南派三叔微信号的技术开发工作是由一家叫"比特海

微信公众号PHP简单开发流程

原文:微信公众号PHP简单开发流程 微信公众号开发分傻瓜模式和开发者模式两种,前者不要考虑调用某些接口,只要根据后台提示傻瓜式操作即可,适用于非专业开发人员. 开发模式当然就是懂程序开发的人员使用的. 下面简单说一下微信公众号开发的简易流程,新手看看会有帮助,高手请一笑而过. 1.配置服务器: A.首先在本机建立如下结构的文件夹(这里是我自己的习惯,仅供参考) MMPN:总目录mro message public number 微信公众号 backup:备份目录,主要用于备份php文件,每次修改

微信公众平台正式向具有微信支付权限的公众号开放模板消息接口

摘要: 昨天晚上,微信公众平台官方发布消息,微信公众平台正式向具有微信支付权限的公众号开放 模板消息接口 .公众号可以借此向其用户发送模板库中预设的消息. 这种模板消息仅用于 昨天晚上,微信公众平台官方发布消息,微信公众平台正式向具有微信支付权限的公众号开放模板消息接口.公众号可以借此向其用户发送模板库中预设的消息. 这种模板消息仅用于公众号向用户发送重要服务通知,必须在符合其要求的服务场景中使用,如信用卡刷卡通知,商品购买成功通知等,不支持广告等营销类消息以及其它所有可能对用户造成骚扰的消息.

百度直达号真的能颠覆微信公众号?

中介交易 SEO诊断 淘宝客 云主机 技术大厅 昨日百度世界大会上,最惊艳的产品莫过于其新推出的"百度直达号"了.按百度副总裁李明远的说法是"直达号"是百度推出的帮助服务商链接用户的方式,使得商家在百度移动平台有一个官方服务账号,基于移动搜索.@账号.地图.个性化推送等方式,让用户随时随地直达商家服务.关于百度直达号的价值已经有诸多文章叙述,老兵所在的企业尚品宅配也在第一时间拿到了内测码,这里结合我的观察分析一下. 百度直达号的创新在哪里? 官方的说法是:百度&qu

[福利]非认证公众帐号也能申请微信连Wi-Fi了

年初3月份时,拥有线下经营场所且开通微信认证的公众号可以开通微信连Wi-Fi接入,现在微信团队进一步开放了权限,非认证公众帐号也能申请微信连Wi-Fi了. 微信连Wi-Fi团队宣布,降低微信连Wi-Fi的准入门槛,面向所有公众号开放自助申请接口,未认证的公众号也可开通微信连Wi-Fi插件,向其用户提供微信连Wi-Fi服务. 微信连Wi-Fi怎么开通?未认证的商户公众帐号可按照原有的申请流程通过自助申请即可开通微信连Wi-Fi插件: 在微信公众平台(mp.weixin.qq.com)登陆公众号,进

如何查看微信公众号的历史文章(微信订阅号查看历史消息)

我们在关注微信公众号的时候会看到该公众号相关信息:微信公众号的logo.名称.微信号.功能介绍.微信认证情况.认证详情,通过这些信息我们可以大概了解这个公众号的运营主题内容,如果还想了解更多可以点击"查看历史消息"查看最近的群发消息.当然您还可以通过搜狗微信搜索直接在电脑上看微信订阅号内容 还没关注公众号前可以快速查看历史消息,关注完以后我们可不可以设置一个微信自定义菜单来显示这些历史消息呢?更直白的说是查看历史消息这个页面的URL. 点击"查看历史消息"页面右上角

百度直达号是来砸微信公众号场子的

毫无疑问,百度直达号是来砸微信公众号场子的,抢夺的也都是传统商户.但,问题是,谁更能击中商户的痛点.痒点.G点?本文即站在商户的视角来对两套系统进行拷问. 请注意,商户根本不关心概念.模式.生态,也不关心你到底是腾讯还是百度,只要能给老子订单,能赚钱,才是王道. 1.带来新客户的能力 PK结果:百度直达号胜出 微信公众号的粉丝从何而来?几乎没有一个粉丝是微信给的,而是商户拉来的,且往往花了代价,比如打折.活动.而且,请注意一点,微信公众号的粉丝往往是商户的老顾客. 拉新呢?微信没办法,它也在努力

PHP对接微信公众平台消息接口开发流程教程_php实例

一.写好接口程序 在你的服务器上上传好一个接口程序文件,如http://www.yourdomain.com/weixin.php  内容如下: 复制代码 代码如下: <?phpdefine("TOKEN", "weixin");//自己定义的token 就是个通信的私钥$wechatObj = new wechatCallbackapiTest();$wechatObj->valid();//$wechatObj->responseMsg();c