微信支付开发h5调用

这两天做微信支付开发。碰到大坑。纠结死我了。好不容做完。

后台java:直接上代码:注意区分前后端的变量大小写。。。

@RequestMapping(value = "/index")
    public Model  index(@RequestParam(value = "openid", required = true) String openid ,Model model,HttpServletRequest request) throws Exception{
        logger.info("************openid***********为:"+openid);
        //获取prepayid
        Map<String ,String > map=new HashMap<String,String>();
        WeiXinConfig wcf=weiXinBaseService.getWeiXinConfig();
         String nonceStr=UUID.randomUUID().toString().substring(0, 32);

        oauthService.shareFactory(request);
        String appid=wcf.getAppid();
         long timestamp = System.currentTimeMillis() / 1000;
        map.put("appid", appid );
        map.put("mch_id", WebConfig.get("pay.mch_id"));
        map.put("nonce_str",nonceStr);
        map.put("body",  WebConfig.get("pay.body"));
        map.put("out_trade_no", payWxUtil.orderNum());
        map.put("total_fee", WebConfig.get("pay.price"));
        map.put("spbill_create_ip",request.getRemoteAddr());
        map.put("notify_url", WebConfig.get("hostAddress")+request.getContextPath()+"/babyShow/payInfo/info");
        map.put("trade_type", "JSAPI");
        map.put("openid", openid);
        String paySign=SignUtil.getPayCustomSign(map,WebConfig.get("pay.key"));
        map.put("sign",paySign);
        String xml=    CommonUtil.ArrayToXml(map);
        String prepayid=    payWxUtil.getPrepayid(xml);
        logger.info("prepareid*****************************="+prepayid);
       //封装h5页面调用参数
        Map<String ,String > signMap=new HashMap<String ,String >();
        signMap.put("appId", appid);
        logger.info("appId="+appid);
        signMap.put("timeStamp", timestamp+"");
        logger.info("timeStamp="+timestamp);
        signMap.put("package", "prepay_id="+prepayid);
        logger.info("package="+"prepay_id="+prepayid);
        signMap.put("signType", "MD5");
        logger.info("singType="+"MD5");
        signMap.put("nonceStr", nonceStr);
        logger.info("nonceStr="+nonceStr);
        model.addAttribute("paytimestamp", timestamp);
        model.addAttribute("paypackage", "prepay_id="+prepayid);
        model.addAttribute("paynonceStr", nonceStr);
        model.addAttribute("paysignType", "MD5");
        String paySign2=SignUtil.getPayCustomSign(signMap,WebConfig.get("pay.key"));
        model.addAttribute("paySign",paySign2 );
        logger.info("paySign="+paySign2);
        return model;

    }

以上代码获取openid需要根据网页授权来获取。这里就不多讲了。主要讲讲获取prepayid和生成h5页面所需参数,

这里面比较麻烦的就是签名的获取

查看方法SignUtil.getPayCustomSign(signMap,WebConfig.get("pay.key"))

代码如下

  /**
     * 获取支付所需签名
     * @param ticket
     * @param timeStamp
     * @param card_id
     * @param code
     * @return
     * @throws Exception
     */
    public static String getPayCustomSign(Map<String, String> bizObj,String key) throws Exception {

        String bizString = CommonUtil.FormatBizQueryParaMap(bizObj,
                false);
        logger.info(bizString);
        return MD5SignUtil.sign(bizString, key);
    }
   

其中CommonUtil.FormatBizQueryParaMap是用来做字典排序的。有参考了网上的例子。就没单独做。

public static String FormatBizQueryParaMap(Map<String, String> paraMap,
            boolean urlencode) throws Exception {

        String buff = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
                    paraMap.entrySet());

            Collections.sort(infoIds,
                    new Comparator<Map.Entry<String, String>>() {
                        public int compare(Map.Entry<String, String> o1,
                                Map.Entry<String, String> o2) {
                            return (o1.getKey()).toString().compareTo(
                                    o2.getKey());
                        }
                    });

            for (int i = 0; i < infoIds.size(); i++) {
                Map.Entry<String, String> item = infoIds.get(i);
                //System.out.println(item.getKey());
                if (item.getKey() != "") {

                    String key = item.getKey();
                    String val = item.getValue();
                    if (urlencode) {
                        val = URLEncoder.encode(val, "utf-8");

                    }
                    buff += key + "=" + val + "&";

                }
            }

            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return buff;
    }

其中MD5SignUtil.sign(bizString, key)方法如下

public static String sign(String content, String key)
            throws Exception{
        String signStr = "";
        signStr = content + "&key=" + key;

        return MD5Util.MD5(signStr).toUpperCase();

    }
其中MD5Util.MD5(signStr)方法如下
    public final static String MD5(String s) {
        char hexDigits[]={‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘,‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘};
        try {
            byte[] btInput = s.getBytes();
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
       }
    }
CommonUtil.ArrayToXml(map)方法如下
public static String ArrayToXml(Map<String, String> arr) {
        String xml = "<xml>";

        Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue();
            if (IsNumeric(val)) {
                xml += "<" + key + ">" + val + "</" + key + ">";

            } else
                xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
        }

        xml += "</xml>";
        return xml;
    }
public static boolean IsNumeric(String str) {
        if (str.matches("\\d *")) {
            return true;
        } else {
            return false;
        }
    }

 

发送请求到微信获取prepayid代码如下

public static String URL="https://api.mch.weixin.qq.com/pay/unifiedorder";
    @SuppressWarnings("deprecation")
    public  JSONObject getPrepayJson(String xml){
        HttpClient httpClient = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );
        InputStream is = null;
         PostMethod method=null;
        try {
            String url =URL;
             method = HttpClientUtils.postMethod(url);
             method.setRequestBody(xml);
            httpClient.executeMethod(method);
            //读取响应
             is = method.getResponseBodyAsStream();
            JSONObject o =Xml2JsonUtil.xml2JSON(is);
            return o;
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(method!=null){
                method.releaseConnection();
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return null;
    }
    public  String getPrepayid(String xml){
        try {
            JSONObject jo=getPrepayJson(xml);
            JSONObject element=jo.getJSONObject("xml");
            String prepayid=((JSONArray)element.get("prepay_id")).get(0).toString();
            return prepayid;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public  String orderNum(){
        String chars = "0123456789";
        String order = System.currentTimeMillis()+"";
        String res = "";
        for (int i = 0; i < 19; i++) {
            Random rd = new Random();
            res += chars.charAt(rd.nextInt(chars.length() - 1));
        }
        order+=res;
        return order;
    }

xml转json方法Xml2JsonUtil.xml2JSON(is);。摘自网络

 /**
         * 转换一个xml格式的字符串到json格式
         *
         * @param xml
         *            xml格式的字符串
         * @return 成功返回json 格式的字符串;失败反回null
         */
        @SuppressWarnings("unchecked")
        public static  JSONObject xml2JSON(InputStream is) {
            JSONObject obj = new JSONObject();
            try {
                SAXReader sb = new SAXReader();
                Document doc = sb.read(is);
                Element root = doc.getRootElement();
                obj.put(root.getName(), iterateElement(root));
                return obj;
            } catch (Exception e) {
                log.error("传入XML后转换JSON出现错误===== Xml2JsonUtil-->xml2JSON============>>",e);
                return null;
            }
        }  

 /**
         * 一个迭代方法
         *
         * @param element
         *            : org.jdom.Element
         * @return java.util.Map 实例
         */
        @SuppressWarnings("unchecked")
        private static Map  iterateElement(Element element) {
            List jiedian = element.elements() ;
            Element et = null;
            Map obj = new HashMap();
            List list = null;
            for (int i = 0; i < jiedian.size(); i++) {
                list = new LinkedList();
                et = (Element) jiedian.get(i);
                if (et.getTextTrim().equals("")) {
                    if (et.elements().size() == 0)
                        continue;
                    if (obj.containsKey(et.getName())) {
                        list = (List) obj.get(et.getName());
                    }
                    list.add(iterateElement(et));
                    obj.put(et.getName(), list);
                } else {
                    if (obj.containsKey(et.getName())) {
                        list = (List) obj.get(et.getName());
                    }
                    list.add(et.getTextTrim());
                    obj.put(et.getName(), list);
                }
            }
            return obj;
        }  
 

服务端基本这么多

前端被微信和我自己挖了大坑,整整搞了两天,擦

先是看的微信文档jssdk文档(开始埋坑。。)

页面引入js

加入

    wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: ‘${appid}‘, // 必填,公众号的唯一标识
        timestamp: ‘${timestamp}‘, // 必填,生成签名的时间戳
        nonceStr: ‘${nonceStr}‘, // 必填,生成签名的随机串
        signature: ‘${signature}‘,// 必填,签名,见附录1
        jsApiList: [
            ‘chooseWXPay‘
        ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2

    });

嗯。配置好了。如果传入jsconfig的参数。。。

然后看到jssdk里面有发送一个微信支付请求?

嗯加进去



function pay(){
        wx.chooseWXPay({
            timestamp: ${paytimestamp}, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
            nonceStr: ‘${paynonceStr}‘, // 支付签名随机串,不长于 32 位
            package: ‘${paypackage}‘, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
            signType: ‘${paysignType}‘, // 签名方式,默认为‘SHA1‘,使用新版支付需传入‘MD5‘
            paySign: ‘${paySign}‘, // 支付签名
            success: function (res) {
                alert("支付成功");
                // 支付成功后的回调函数
            }
        });
    }

 

然后发布,执行调试。。尼玛。怎么样都支付不了。一会儿报订单信息错误、一会儿报签名错误。。。找了N多资料均不对

后来想啊。大不了用商户平台提供的文档写接口什么的。于是加入了代码

      function onBridgeReady(){
            WeixinJSBridge.invoke(
                ‘getBrandWCPayRequest‘, {
                   "appId" : "${appid}",     //公众号名称,由商户传入
                    "timeStamp":"${paytimestamp}",         //时间戳,自1970年以来的秒数
                    "nonceStr" : "${paynonceStr}", //随机串
                    "package" : "${paypackage}",
                    "signType" : "${paysignType}",         //微信签名方式:
                    "paySign" : "${paySign}" //微信签名
               },
                function(res){
                   alert(res.err_msg);  // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返

               }
           );
         }
    function pay2(){
        if (typeof WeixinJSBridge == "undefined"){
           if( document.addEventListener ){
                 document.addEventListener(‘WeixinJSBridgeReady‘, onBridgeReady, false);
             }else if (document.attachEvent){
                 document.attachEvent(‘WeixinJSBridgeReady‘, onBridgeReady);
                document.attachEvent(‘onWeixinJSBridgeReady‘, onBridgeReady);
            }
         }else{
           onBridgeReady();
         }
     }

发布调试。。。还是不对。。两个按钮pay()和pay2()均不对。pay方法还是一会儿订单信息错误一会儿签名错误。pay2()方法则一直报签名错误。。。尼玛。吧经历放后台签名。。怎么改都不行。签名明明对的啊。可以获取prepayid的。为毛封装h5参数时就出错了呢。。。折腾啊。。。搞了N久。。就尼玛不对。。。后来一个小错误pay方法js报错了。。结果pay2方法确可以执行了。。。吧pay的js报错去了之后pay2又不能用了。。我擦。。哥有预感。。难道两种方式冲突了??于是我把config和pay方法删除了再试试。。。尼玛果然可以了。不能加入config和pay。。。果然可以了。。。我擦。折腾的。。微信啃爹啊。第一种方式无法用有没有,误导人啊。。。正确结果就是商品平台的文档使用方法js如下:

      function onBridgeReady(){
            WeixinJSBridge.invoke(
                ‘getBrandWCPayRequest‘, {
                   "appId" : "${appid}",     //公众号名称,由商户传入
                    "timeStamp":"${paytimestamp}",         //时间戳,自1970年以来的秒数
                    "nonceStr" : "${paynonceStr}", //随机串
                    "package" : "${paypackage}",
                    "signType" : "${paysignType}",         //微信签名方式:
                    "paySign" : "${paySign}" //微信签名
               },
                function(res){
                   alert(res.err_msg);  // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返

               }
           );
         }
    function pay(){
        if (typeof WeixinJSBridge == "undefined"){
           if( document.addEventListener ){
                 document.addEventListener(‘WeixinJSBridgeReady‘, onBridgeReady, false);
             }else if (document.attachEvent){
                 document.attachEvent(‘WeixinJSBridgeReady‘, onBridgeReady);
                document.attachEvent(‘onWeixinJSBridgeReady‘, onBridgeReady);
            }
         }else{
           onBridgeReady();
         }
     }

至此。终于把微信支付搞定了。留着博客。防止后人走弯路(config里面不能加入chooseWXPay方法。。切记)

时间: 2024-10-05 23:03:21

微信支付开发h5调用的相关文章

PHP微信支付开发实例

这篇文章主要为大家详细介绍了PHP微信支付开发过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 PHP微信支付开发过程,分享给大家,供大家参考,具体内容如下 1.开发环境 Thinkphp 3.2.3 微信:服务号,已认证 开发域名:http://test.paywechat.com (自定义的域名,外网不可访问) 2.需要相关文件和权限 微信支付需申请开通 微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 微信支付开发者文档

微信支付开发 c# SDK JSAPI支付开发的流程和微信大坑

微信支付开发流程 1. 开通微信支付功能 省略 2. 下载微信的C#版的微信SDK 下载连接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 各个版本的都有,可惜咱最熟悉C# 我的下载时间是2016-02-28日,所以所有的流程都是基于这个版本的SDK. 3. 配置各种参数 首先在微信支付的开发配置中配置发起支付的路径如下: 代码的solution中找到lib的config.cs文件,如下图,所有的参数都在这里,这里配置

微信支付开发流程

授人以鱼不如授人以渔 微信支付开发流程 下面以PHP语言为例,对微信支付的开发流程进行一下说明. 1.获取订单信息 2.根据订单信息和支付相关的账号生成sign,并且生成支付参数 3.将支付参数信息POST到微信服务器,获取返回信息 4.根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付. 下面分步骤的讲一下: 1.微信支付中相关的必须的订单参数有三个,分别是:body(商品名或订单描述),out_trade_no(一般为订单号)和total_fee(订单金额,单位“

微信支付开发(11) Native支付

关键字:微信公众平台 微信支付 Native原生支付作者:方倍工作室原文:http://www.cnblogs.com/txw1958/p/wxpay-native.html 在这篇微信公众平台开发教程中,我们将介绍如何开发实现微信支付的Native功能. 本文分为以下三个部分: 生成Native支付URL 生成二维码 生成Package 一.生成Native支付URL Native(原生)支付URL是一系列具有weixin://wxpay/bizpayurl?前缀的URL,同时后面紧跟着一系列

微信支付开发(7) 告警通知

本文介绍微信支付中如何获得告警通知. 一.告警通知 为了及时通知商户异常,提高商户在微信平台的服务质量.微信后台会向商户推送告警通知,包括发货延迟.调用失败.通知失败等情况,通知的地址是商户在申请支付时填写的告警通知URL,在"公众平台-服务-服务中心-商户功能-商户基本资料-告警通知URL"可以查看.商户接收到告警通知后需要尽快修复其中提到的问题,以免影响线上经营. 告警通知URL接收的postData中还将含xml数据,格式如下: <xml> <AppId>

微信支付开发(6) 发货通知

本文介绍微信支付中发货通知功能的实现. 一.发货通知 为了更好地跟踪订单的情况,需要第三方在收到最终支付通知之后,调用发货通知API告知微信后台该订单的发货状态. 发货时间限制:虚拟.服务类24小时内,实物类72小时内. 请在收到支付通知后,按时发货,并使用发货通知接口将相关信息同步到微信后台.若平台在规定时间内没有收到,将视作发货超时处理. 发货通知API的URL为: https://api.weixin.qq.com/pay/delivernotify?access_token=xxxxxx

PHP微信支付开发

1.开发环境 Thinkphp 3.2.3 微信:服务号,已认证 开发域名:http://test.paywechat.com (自定义的域名,外网不可访问) 2.需要相关文件和权限 微信支付需申请开通 微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 微信支付开发者文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 微信支付SDK下载地址:https://pay.weixin.

微信支付开发流程(1/2)

授人以鱼不如授人以渔 微信支付开发流程 下面以PHP语言为例,对微信支付的开发流程进行一下说明. 1.获取订单信息 2.根据订单信息和支付相关的账号生成sign,并且生成支付参数 3.将支付参数信息POST到微信服务器,获取返回信息 4.根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付. 下面分步骤的讲一下: 1.微信支付中相关的必须的订单参数有三个,分别是:body(商品名或订单描述),out_trade_no(一般为订单号)和total_fee(订单金额,单位“

微信支付开发关键点技术解析

微信支付是由微信及财付通联合推出的移动支付创新产品.如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及 商家申请微信支付时,面临着诸多疑惑.本文将结合微信支付接口开发的实践,从支付申请到各主要接口的使用方法等方面介绍微信支付的关键点技术. URL设置 目前,微信支付只能由通过微认证的服务号进行申请,订阅号及未认证的服务号均无法申请.登录微信公众平台后台,在左侧的栏目中可找到“微信支付”,点击进入申请界面,可以看到第一项中的“商户基本资料”,点击右侧的“填写”按钮后就