美文网首页Java服务器端编程iOS学习笔记iOS程序猿
微信支付集成之3商户服务器(JAVA)搭建

微信支付集成之3商户服务器(JAVA)搭建

作者: WallisW | 来源:发表于2017-10-25 10:10 被阅读35次

    上节总结了微信支付的整体业务逻辑,这次总结一下我按部就班搭建商户服务器的步骤。这里后台语言用的是JAVA,我的目的是进一步理解并学习微信信支付业务逻辑,就随选了java。其他后台语言开发应该大同小异,具体实现语法和细节可能不同。

    首先,由于要搭建JAVA服务器。我们需要有java开发环境(我这里用的IDE是Eclipse),至于配置方法我之前有篇文章可以参考:微信支付集成之1Java环境配置

    准备工作

    1.打开Eclipse,创建一个新的Dynamic Web项目

    图1.1 图1.2

    2.在项目左侧找到WebContent/WEB-INF/lib,添加这几个库:gson,jdom,jsonObject,这都是java开发常用到的几个库,网上都能找到。添加,全选右键Build Path-Add to Build Path,这样才算将用到的库添加到了项目中。

    1.3

    添加后,左侧项目视图里Referenced Librayies下出现了相应的库,说明添加成功。

    1.4

    3.准备好从网上下载好的微信支付Java版工具类,这是我下载到的,个人觉得封装得还不错。

    1.5

    4.我们知道Java里的源代码在src目录下,所以依次打开到src,右键新建一个Packet命名为com.charos.CHWxPay.Utils

    1.6 1.7

    点击完成后,看左侧的工程目录src下就多了一个Utils的包。

    5.将下载的工具包(图1.5)的utils文件拷贝到该包下,然后以同样的方式新建一个http包,同样的方式将工具包内文件拷贝。
    此时,发现文件都拷贝过来了,但是会报错。这个错误一般可能是由于文件移动造成寻找路径不对,只需要打开对应文件停留光标到导入文件出:cmd+shift+o 修正文件路径即可。

    1.8

    写用于自己项目的支付类

    1. 新建一个支付类继承自httpServlet,这是我们自己写的在支付类
    2.1 2.2 2.3

    2.我们接着在这个类里,写自己项目的支付业务

    2.4

    基本步骤:
    第1步-签名订单信息,获取预支付标识
    第2步-调用微信统一下单接口
    第3步-处理接口返回信息进行二次签名
    第4步-将签名信息返回客户端

    3.业务代码
    在写这里的业务代码前,要配置一下支付服务的基本信息

    基本信息配置
    package com.chaors.CHWxPay;
    
    import java.io.IOException;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.chaors.CHWxPay.Http.bean.OrderResult;
    import com.chaors.CHWxPay.Http.bean.OrderResult.OrderBean;
    import com.chaors.CHWxPay.Http.impl.PrepayIdRequestHandler;
    import com.chaors.CHWxPay.Utils.ConstantUtil;
    import com.chaors.CHWxPay.Utils.OrderUtils;
    import com.chaors.CHWxPay.Utils.WXUtil;
    import com.google.gson.Gson;
    
    //接口名称:WxPayServlet
    //接口参数列表
    //name:商品名称
    //price:商品价格
    public class WxPayServlet extends HttpServlet {
    
        // 首先:定义支付应用ID、商户ID等等...
        // 应用ID
        public static String APP_ID = ConstantUtil.APP_ID;
        // 商户ID
        public static String PARTNER_ID = ConstantUtil.PARTNER_ID;
        // 商户好对应的密钥
        public static String PARTNER_KEY = ConstantUtil.PARTNER_KEY;
        // 统一下单的接口(微信支付服务器提供的)
        public static String URL_UNIFIEDORDER = ConstantUtil.URL_UNIFIEDORDER;
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            this.doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 第1步-签名订单信息
            // 第一点:获取客户端传递过来的参数
            // req:客户端请求
            // resp:响应客户端请求
            req.setCharacterEncoding("UTF-8");
            resp.setCharacterEncoding("UTF-8");
            String name = req.getParameter("name");
            String price = req.getParameter("price");
            // 第二点:设置访问微信支付服务器请求数据类型
            resp.reset();
            resp.setHeader("ContentType", "text/xml");
            // 第三点:创建请求微信支付服务器参数集合
            // 做了请求封装
            // 微信写好一个封装案例,你可以根据服务器需求,自己定义网络请求框架
            PrepayIdRequestHandler handler = new PrepayIdRequestHandler(req, resp);
            // 统一下单的接口(调用微信支付服务器需要的接口)--->公开的
            handler.setGateUrl(ConstantUtil.URL_UNIFIEDORDER);
            // 设置密钥
            handler.setKey(PARTNER_KEY);
            // 设置应用的ID
            handler.setParameter("appid", APP_ID);
            // 商户号
            handler.setParameter("mch_id", PARTNER_ID);
            // 随机字符串
            handler.setParameter("nonce_str", WXUtil.getNonceStr());
            // 商品描述(APP名-商品名)
            handler.setParameter("body", "超哥爱学习-超哥笔记");
            // 商户订单号(自己服务器生成订单号)
            String out_trade_no = OrderUtils.getOrderNumber();
            handler.setParameter("out_trade_no", out_trade_no);
            // 总金额
            handler.setParameter("total_fee", price);
            // 终端IP(客户端IP)
            handler.setParameter("spbill_create_ip", req.getRemoteAddr());
            // 通知地址(微信服务器回调商户服务器页面)
            handler.setParameter("notify_url", ConstantUtil.NOTIFY_URL);
            // 交易类型
            handler.setParameter("trade_type", "APP");
    
            // 第四点:对我们订单信息进行签名
            String sign = handler.createMD5Sign();
            // 设置签名
            handler.setParameter("sign", sign);
    
            // 第2步-调用微信统一下单接口(目的:获取prepay_id)
            // command+1
    
            OrderResult orderResult = new OrderResult();
            try {
                // 集合参数列表
                // 返回结果
                // <xml>
                // <return_code><![CDATA[SUCCESS]]></return_code>
                // <return_msg><![CDATA[OK]]></return_msg>
                // <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
                // <mch_id><![CDATA[10000100]]></mch_id>
                // <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
                // <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
                // <result_code><![CDATA[SUCCESS]]></result_code>
                // <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
                // <trade_type><![CDATA[APP]]></trade_type>
                // </xml>
                Map paramsMap = handler.sendPrepay();
                String prepay_id = (String) paramsMap.get("prepay_id");
                if (prepay_id != null && !"".equals(prepay_id)) {
                    // 统一下单接口调用成功
                    // 第3步-处理接口返回信息进行二次签名
                    // 调用支付接口:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
                    // 二次签名和一次签名,参数不一样(复用之前参数集合)
                    // 请求集合列表(情空:不影响新的参数签名)
                    // 微信服务器要求
                    handler.clear();
                    String noncestr = (String) paramsMap.get("noncestr");
                    String timestamp = WXUtil.getTimeStamp();
                    // 密钥
                    handler.setKey(PARTNER_KEY);
                    // 设置应用的ID
                    handler.setParameter("appid", APP_ID);
                    // 预付单ID
                    handler.setParameter("prepayid", prepay_id);
                    // 扩展字段
                    handler.setParameter("package", "Sign=WXPay");
                    // 商户号
                    handler.setParameter("partnerid", PARTNER_ID);
                    // 随机字符串
                    handler.setParameter("noncestr", noncestr);
                    // 时间戳
                    handler.setParameter("timestamp", timestamp);
    
                    // 进行二次签名(签名参数不一样)
                    // 第一次签名:对订单信息签名,获取prepay_id
                    // 第二次签名:对支付信息进行签名
                    sign = handler.createMD5Sign();
    
                    // 第4步-将签名信息返回客户端(xml、json都可以)
                    // 采用Json解析(构建json--->返回客户端)
                    OrderBean orderBean = new OrderBean();
                    orderBean.setAppid(APP_ID);
                    orderBean.setNoncestr(noncestr);
                    orderBean.setPackageValue("Sign=WXPay");
                    orderBean.setPartnerid(PARTNER_ID);
                    orderBean.setPrepayid(prepay_id);
                    orderBean.setTradeType((String) paramsMap.get("trade_type"));
                    orderBean.setSign(sign);
                    orderBean.setTimestamp(timestamp);
                    orderResult.setOrderBean(orderBean);
    
                    // 将model转json数据格式(框架)--->服务器开发(bean)
                    //resultCode:随便你定义(根据服务器要求)
                    //0:成功  1:失败  2:未知异常
                    orderResult.setResultCode(0);
                    orderResult.setResultMessage("获取成功!");
    
                } else {
                    // 调用失败
                    orderResult.setResultCode(9);
                    orderResult.setResultMessage("获取失败!");
                }
            } catch (Exception e) {
                e.printStackTrace();
                orderResult.setResultCode(6);
                orderResult.setResultMessage("未知异常!");
            }
    
            // 将json返回给客户端
            Gson gson = new Gson();
            String jsonStr = gson.toJson(orderResult);
            resp.getWriter().print(jsonStr);
    
        }
    
    }
    

    4.接口配置
    首先,从别的项目拷贝一份web.xml文件到WEB-INF下,按下图提示配置。

    2.4

    然后,从别的项目拷贝一份index.jsp文件到WEB-Content下,无需改动即可。

    这样,微信支付的商户服务器就基本搭建完成。选择项目,右键Run as Server运行便启动了商户服务器。正常运行,将得到的网址作为客户端提交订单信息的接口:

    服务器启动成功

    可能的问题

    1.运行项目出现Tomcat启动失败

    3.1

    这时,选择左上角Eclipse-设置-找Runtime Environments。删除现有的Tomcat服务器,然后新建一个服务器即可。

    3.2 3.3

    2.还有可能出现以下问题:

    3.4

    解决方案为:

    3.5 3.6

    终于写完了,我发现总结笔记可比实际项目操作慢多了。得考虑很多方面,不过同时也学到了许多以前忽视的地方。希望能在这条路上走得更远!

    晚安,这个世界!
    晚安,那些写代码的可爱的人儿!

    --20171023凌晨



    我们讲述生命,
    我们前行,
    同时告别它的正在移栖的鸟群,
    我们属于最美好的一代人。
    -----------------------------诗人 奥德修斯-埃利帝斯

    相关文章

      网友评论

        本文标题:微信支付集成之3商户服务器(JAVA)搭建

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