zoukankan      html  css  js  c++  java
  • 微信支付4步骤搞定

    在此更正,以前的微信支付借用了网上其他一些帖子,要么半桶水,要么有所隐藏,根本没法用。

    当你发现百度已经帮不了你的时候,其实你自身已经有一定的高度了。

    前面本文浏览次数在100多,可能坑了一些新手,我自己也被坑。再次抱歉!

    下面是我自己实际微信扫码支付的过程记录,以供分享!微信扫码支付也称为万金油支付方式,适用很多场合。

    首先前提条件得申请微信公众号,需要花一个星期以上的时间。

    1、注册公众号(必须选择服务号),注册类型必须(企业/公司,政府,媒体)三选一。

    2、认证,必须认真填写材料。认证300一次,不保证成功。被驳回钱打水漂了。

    3、提交申请资料:微信支付,1-5个工作日。

    4、开户成功,登录商户平台验证。进行测试转账1毛钱。

    5、在线签收协议。

    其他一些参数的设置可以参考我另一篇文章《微信支付的5个参数获取

    接入正题,开始开发。

    前面使用了其他一些三方jar包,其实后来自己做,感觉根本没必要。一个map和xml的转换以及签名,官方的微信SDK都有。感觉根本没必要,再说也不安全,其次是可用性差。

    讲讲开发者要做的事:

    1、商户后台调用微信接口统一下单,并返回一个code_url。

    2、后台把这个code_url发送给前端,前端生成二维码。与支付宝不同,这个二维码要我们自己生成。

    3、支付结果微信会通过回调地址返回给系统,系统再返回给前端。

    就这么点事,就这么简单、好多文章要么只写前端要么后台,要么简单变复杂化。所以很多新手因此而懵逼。

    下面直接上步骤:

    第一步:加入微信支付jar包。

    这个要自己编译到maven仓库:第三方开源的不安全,参见微信支付官方提示。

    怎么整呢?

    把官方下载的SDK打包成jar,然后编译到maven仓库就好了。Dfile就是你打包成jar的存放地址

    嫌麻烦,你把SDK那些代码拷到你的项目里直接用也是一样的。

        <!-- 微信公众号支付依赖 最新版本-->
            <!--install:install-file -Dfile=E:wxpay-sdk-0.0.3.jar -DgroupId=com.weixin -DartifactId=alipay-sdk-weixin -Dversion=1.0 -Dpackaging=Jar-->
            <dependency>
                <groupId>com.weixin</groupId>
                <artifactId>alipay-sdk-weixin</artifactId>
                <version>1.0</version>
            </dependency>


    第二步:编写微信支付配置类PayConfig

    import org.springframework.stereotype.Component;
    
    /**
     * 微信支付配置类
     */
    @Component
    public class PayConfig {
    
        //初始化
        public final static String APP_ID = "123456"; //公众账号appid(改为自己实际的)
        public final static String APP_PATH = "";//安全证书路径,没用到
        public final static String MCH_ID = "123"; //商户号(改为自己实际的)
        public final static String API_KEY = "pass"; //(改为自己实际的)key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
        //code_url请求地址
        public final static String UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        public final static String NOTIFY_URL = "http://www.a.com/weixinPay/notify"; //微信支付回调接口,就是微信那边收到(改为自己实际的),需要跟微信公众号微信支付设置的一致
        //企业向个人账号付款的URL
        public final static String SEND_EED_PACK_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
      //查询订单请求URL
      private static final String ORDER_QUERY_REQUEST_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
    }

    第三步:微信支付控制类


    (这个跟前端存在一个交互)service层的一些代码也写在了这里,有点乱。绿色部分是个人业务,不是核心。可以无视
    import com.github.wxpay.sdk.WXPayUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.*;
    
    /**
     * 微信支付
     */
    @Controller
    @RequestMapping("/weixinPay")
    public class PayController {
    
    
        final static Logger log = LoggerFactory.getLogger(PayController.class);
    
        @Resource
        private RentingtoolsBiz rentingtoolsBiz; //出租工具订单接口
        @Resource
        private CustomerOrderBiz customerOrderBiz;//客户订单接口
        @Resource
        private BrowseRecordsCommonUtil browseRecordsCommonUtil;//缓存类
        @Resource
        private WebSocketServer webSocketServer;//socket
        @Resource
        private PsUserUtils psUserUtils;//缓存类
    
    
    
        /**
         * 跳转到微信支付页面
         * @param request
         * @param model
         * @return
         */
        @RequestMapping("/payCode")
        public String payCode(HttpServletRequest request, Model model){
            BrowseRecordsUtil browseRecordsUtil= browseRecordsCommonUtil.getBrowseRecords(request);
            RentingToosOrder order = (RentingToosOrder)browseRecordsUtil.getPayOrder();
            model.addAttribute("order",order);
            return "business/payWeiXin";
        }
    
        /**
         * 获取微信支付二维码(前端根据这个返回的数据生成二维码)
         * @param request
         */
        @ResponseBody
        @RequestMapping("/weixinCode")
        public RestObject qrcode(HttpServletRequest request) {
            try {
                String data = weixinPay(request);
                return RestObject.newOk("ok",data);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 微信平台发起的回调方法,
         * 调用我们这个系统的这个方法接口,将扫描支付的处理结果告知我们系统
         * @throws
         * @throws Exception
         */
        @RequestMapping(value = "/notify")
        public void weixinNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
            //读取参数
            InputStream inputStream ;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s ;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null){
                sb.append(s);
            }
            in.close();
            inputStream.close();
            //解析xml成map
            Map<String, String> map = WXPayUtil.xmlToMap(sb.toString());
            // 账号信息
            String key = PayConfig.API_KEY; //key
            String userId = psUserUtils.getUserId(request);
            //判断签名是否正确
            if(WXPayUtil.isSignatureValid(sb.toString(),key)) {
                //------------------------------
                //处理业务开始
                //------------------------------
                String resXml = "";
                if("SUCCESS".equals((String)map.get("result_code"))){
                    // 这里是支付成功
                    //////////执行自己的业务逻辑////////////////
                    //String mch_id = (String)map.get("mch_id");
                    //String openid = (String)map.get("openid");
                    //String is_subscribe = (String)map.get("is_subscribe");
                    //String out_trade_no = (String)map.get("out_trade_no");
                    String total_fee = (String)map.get("total_fee");//注意这个金额单位是分
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
                            //这里处理更新数据库订单支付成功的信息#######################
    
                } else {
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                }
                //------------------------------
                //处理业务完毕
                //------------------------------
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
                webSocketServer.sendInfo("微信支付失败!","service"+userId);
            } else{
                System.out.println("通知签名验证失败");
            }
    
        }
        
        
        /**
         * 发起微信支付
         * @param request
         * @param
         * @return
         * @throws Exception
         */
        public String weixinPay(HttpServletRequest request) throws Exception {
            BrowseRecordsUtil browseRecordsUtil= browseRecordsCommonUtil.getBrowseRecords(request);
            Order order=browseRecordsUtil.getPayOrder();//获取缓存里的订单信息
            Map packageParams=new HashMap();
            //这里暂时只处理A类型的业务
            if(order instanceof RentingToosOrder){
                RentingToosOrder order1=(RentingToosOrder)order;
                //注意这里的参数都是String类型,否则会报类型转换错误
                packageParams.put("appid", PayConfig.APP_ID);//公众账号ID
                packageParams.put("mch_id", PayConfig.MCH_ID);//商户ID
                packageParams.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
                packageParams.put("body", "腾讯视频");  //(调整为自己的名称)
                packageParams.put("out_trade_no", order1.getId());//订单编号
                DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
                packageParams.put("total_fee",decimalFormat.format(order1.getTotalPrice() * 100)); //价格的单位为分
                packageParams.put("spbill_create_ip",request.getLocalAddr());//请求ip        
                packageParams.put("notify_url", PayConfig.NOTIFY_URL);//异步回调地址  
                packageParams.put("trade_type", "NATIVE");//交易类型   
            } 
            try { 
            
            //支付请求参数,WXPayUtil生成签名并转成xml 
            String xmlParam = WXPayUtil.generateSignedXml(packageParams, PayConfig.API_KEY); 
            
            //2.发送请求,HttpClientUtil类是封装的一个HttpClient类包含了Https请求兼容的处理方法  
            HttpClientUtil httpClient=new HttpClientUtil(PayConfig.UFDODER_URL); 
            httpClient.setHttps(true); httpClient.setXmlParam(xmlParam); httpClient.post(); 
            
            //3.获取结果。这里做一个说明,微信支付jsapi支付授权目录必须跟请求页面地址匹配:例如请求页面是www.a.com/weixinPay/weixin.html       
            // 那么jsapi支付授权目录必须要有www.a.com/weixinPay/的授权地址。其次回调地址要跟设置的一样       
            // 否则返回的数据为空 
            
            String xmlResult = httpClient.getContent(); 
            //log.error("打印微信支付返回的xml"+xmlResult); 
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult); 
            //log.error("打印微信支付返回的map"+mapResult); 
        log.error("打印微信支付返回的map"+mapResult);
        String urlCode = mapResult.get("code_url");
        log.error(urlCode);
        //对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX
            return urlCode;
            } catch (Exception e) {
                e.printStackTrace(); 
            } 
                return null; 
        } 
    }

    第四步:前端

    前端主要是生成了一个二维码,这里用的是纯前端技术qrious.js。没有后台生成,减少了后台的压力。
    再者前端和后台建了socket连接,因此前台也不用轮询请求后台支付是否成功。支付成功后台会告诉前台,且只有一次。
    没有建立socket连接的只用后台把支付结果保存,然后前端setInterval()轮询ajax请求返回即可。

    HTML
      <div id="tab-page">
         <img id="codeImg" alt="微信支付二维码"  width="300px" height="300px">
      </div>

     获取二维码

    $.ajax({
        type: "POST",//请求类型
        url: path + "/weixinPay/weixinCode",//请求的url
        dataType: "json",//ajax接口(请求url)返回的数据类型
        success: function (data) {//data:返回数据(json对象)
            if(data.data!=""){
                var qr = new QRious({
                    element:document.getElementById("codeImg"),
                    size:300,
                    level:'L',
                    value:data.data
                });
            }else {
                errerInformation("获取微信支付二维码失败!","javascript:void(0);");//弹窗告诉前台下单失败!
            }
        }
    });

      socket通知

        //获得消息事件
        socket.onmessage = function(msg) {
            console.log(msg.data);
            //发现消息进入    开始处理前端触发逻辑,连接成功不提示,烦
            if(msg.data!="连接成功"){
                errerInformation(msg.data,"javascript:void(0);");//alert弹窗socket信息
                setTimeout(function () {
                    if(msg.data=="微信支付成功!"){
                        window.location.href=path+"/index";//成功返回首页
                    }
                },2000);
            }
        };
        


    
    



  • 相关阅读:
    CF161D Distance in Tree
    [WC2010]重建计划 长链剖分
    [FJOI2014]最短路径树问题 长链剖分
    [Vani有约会]雨天的尾巴 线段树合并
    Friend Links
    Nerdtree+高亮+图标配置
    【CF1416C】XOR Inverse
    01-Trie 学习
    【[USACO19DEC】Milk Visits G
    【ARC069D】Flags
  • 原文地址:https://www.cnblogs.com/zeussbook/p/10239885.html
Copyright © 2011-2022 走看看