文档章节

微信公众号支付总结

java9
 java9
发布于 2015/08/20 15:26
字数 1347
阅读 3232
收藏 20
点赞 2
评论 9

微信公众号支付总结大致可以分为三步, 第一步获取用户授权,第二步调用统一下单接口获取预支付id,第三步H5调起微信支付的内置JS进行支付

注意:

不得不提的是,每个公众号(公众平台),每一个APP(开放平台), 如果要进行微信支付得单独进行开通微信支付功能。开通成功后会为每一个公众号,APP 分配一个商户号。最开始没有搞清楚这层关系,导致出现类似“appid与商户号没有关联”,授权时没有“scope 权限”这样的问题。

获取用户授权


String wxaccessUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?";
            String uri = wxaccessUrl+"appid="+ConstantUtil.JS_APP_ID+"&redirect_uri="+URLEncoder.encode(vo.getRedirectUri(),"UTF-8")+"&response_type="+vo.getResponseType()+"&scope="+vo.getScope()+"&state="+vo.getState();
            logger.debug("authorize uri: "+uri);
            return "redirect:"+uri;



因为统一下单接口需要用户的openid,所以需要进行用户授权,这里只需要获取到最基本的用户openid就行了。redirectUri 是授权之后跳转到后台的地址,需要进行urlencode。这里存在一个疑问,就是微信授权之后跳转回来的地址栏地址还是授权的地址,但是网页的内容已经是我们自己的网页了。这样在第三步进行支付时,会导致配置的微信支付目录不正确,因此我这里授权跳转回来之后又进行了一次跳转,通过redirect 来保证网址在微信支付中配置的目录中。


授权之后微信会在链接上加上code ,拿上这个我们再进行授权的第二步:获取用户的openid.我把这一步写在一个jsp中。

code.jsp


String code = request.getParameter("code");
    String openid="";
    String accessCodeUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + ConstantUtil.JS_APP_ID + "&secret="+ConstantUtil.APP_SECRET+"&code=" + code + "&grant_type=authorization_code";
    if (code == null) out.println("用户授权失败。");
    HttpPost post = new HttpPost(accessCodeUrl);
    HttpResponse resp = HttpClients.createDefault().execute(post);
    if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        InputStream inputStream = resp.getEntity().getContent();
        byte[] buff = new byte[1024];
        int len;
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        while ((len = inputStream.read(buff)) != -1) {
            bout.write(buff, 0, len);
        }
        JSONObject result = JSON.parseObject(new String(bout.toByteArray()));
        openid = (String) result.get("openid");
        if (result.containsKey("errcode")){
            logger.error("wx access error code:"+result.get("errmsg"));
        }
    } else {
        out.println("用户授权失败。");
    }

这个页面包含到需要进行支付的页面中。code是从后台传过来的。

toPay.do 跳转到需要支付的页面toPay.jsp

order = URLEncoder.encode(request.getParameter("order"), "UTF-8");//从微信跳转过来,有中文的话需要进行url 编码
            String uri = "/wechat/activity/toPay.jsp?rid=" + request.getParameter("rid") + "&pid=" + request.getParameter("pid")+
                    "&sn="+request.getParameter("sn")+"&amount="+request.getParameter("amount")+"&order="+order+
                    "&code="+request.getParameter("code")+"&showwxpaytitle=1";
            logger.debug(uri);
            return "redirect:"+uri;



toPay.jsp需要配置到微信的支付目录中。(这里要说一下的是关于服务器的端口号最好是弄成80端口,如果还用到微信其他的js sdk 功能,会现invalid signature之类的错误)

统一下单

点击支付之后再向后发送下单请求。

将这一步获取到的openid 传给后台,

PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);//获取prepayid的请求类
            ClientRequestHandler clientHandler = new ClientRequestHandler(request, response);//返回客户端支付参数的请求类

            prepayReqHandler.setParameter("appid", ConstantUtil.JS_APP_ID);
            prepayReqHandler.setParameter("openid", payVO.getOpenid());
            prepayReqHandler.setParameter("body", snInfo.get("name").toString()); //商品描述
            prepayReqHandler.setParameter("device_info", "WEB"); //商品描述
            prepayReqHandler.setParameter("mch_id", ConstantUtil.JS_MCH_ID);
            String noncestr = WXUtil.getNonceStr();
            prepayReqHandler.setParameter("nonce_str", noncestr);
            prepayReqHandler.setParameter("notify_url", getServerUrl(request, notify_url)); //接收微信通知的URL
            prepayReqHandler.setParameter("out_trade_no", out_trade_no); //商家订单号
            prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr()); //订单生成的机器IP,指用户浏览器端IP
            prepayReqHandler.setParameter("total_fee", "" + (int) (((Float) snInfo.get("amount")) * 100)); //商品金额,以分为单位
            prepayReqHandler.setParameter("trade_type", "JSAPI");
            //生成获取预支付签名
            String sign = prepayReqHandler.createSHA1Sign(ConstantUtil.JS_APP_KEY);
            //增加非参与签名的额外参数
            prepayReqHandler.setParameter("sign", sign);

            String gateUrl = ConstantUtil.GATEURL;
            prepayReqHandler.setGateUrl(gateUrl);
            //获取prepayId
            String prepayid = prepayReqHandler.sendPrepay();



PrepayIdRequestHandler 这个类可以在微信的demo 找到。
这里的签名需要一个api key,同样的,每个appid 对应一个key,这个key 需要在微信支付的系统中去设置,不在公众号里面设置。

获取到prepayid 之后,将参数传给前台页面。

//输出参数列表
                clientHandler.setParameter("appId", ConstantUtil.JS_APP_ID);
                clientHandler.setParameter("nonceStr", noncestr);
                clientHandler.setParameter("package", "prepay_id="+prepayid);
                clientHandler.setParameter("timeStamp", "" + System.currentTimeMillis() / 1000);//秒
                clientHandler.setParameter("signType", "MD5");
                //生成签名
                sign = clientHandler.createSHA1Sign(ConstantUtil.JS_APP_KEY);
                clientHandler.setParameter("paySign", sign);
                Map map = clientHandler.getMapBody();
                return success(map);



调起支付

function onBridgeReady() {
                                WeixinJSBridge.invoke(
                                        'getBrandWCPayRequest', {
                                            "appId": data.appId,     //公众号名称,由商户传入
                                            "timeStamp": data.timeStamp,         //时间戳,
                                            "nonceStr": data.nonceStr, //随机串
                                            "package": data.package,
                                            "signType": data.signType,         //微信签名方式:
                                            "paySign": data.paySign //微信签名
                                        },
                                        function (res) {
                                            if (res.err_msg == "get_brand_wcpay_request:ok") {
                                                //支付成功后最好是到后台进行查询一下订单的状态,确保服务器后台相关的业务都已经执行成功。

                                            }     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
                                            else if(res.err_msg =='get_brand_wcpay_request:cancel'){
                                                
                                            }
                                            else{
                                                showTip("支付失败。");
                                            }
                                        }
                                );
                            }

                            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();
                            }



这一部分可以放在你的ajax success部分中进行。

后记

进行微信开发,主要是不好调试。

  1. 需要将网页链接通过你的公众号发到你的微信,然后在微信中打开链接。
  2. 尽量把代码写在jsp 中,避免写在class 中频繁重启。
  3. 碰到签名错误,可以在微信提供的签名工具中验证,如果是签名没有错,那就是算法没有错,传的参数不对了。比如app key 不对。
如果有其他的朋友有相关的问题,可以留言给我。我尽量帮大家解决,避免大家跳入微信的坑中。


© 著作权归作者所有

共有 人打赏支持
java9
粉丝 12
博文 65
码字总数 25460
作品 0
武汉
后端工程师
加载中

评论(9)

LUOYIRUIX
LUOYIRUIX
本人已经解决手机苹果浏览器和安卓95%以上浏览器外部链接直接跳入微信中打开链接,如果APP是自己的也同样可以跳入微信中打开页面,功能已经全部系统化,可直接提供API接口,普通用户直接对接到页面立马使用,需要的朋友找我拿 QQ 7 74 0 8 0 26
java9
java9

引用来自“小汤圆1”的评论

一切都没错 就是报支付验证签名失败
看看key是不是用错了
小汤圆1
小汤圆1
一切都没错 就是报支付验证签名失败
打扰一夏
打扰一夏
楼主你好,公司要求我用node.js开发 公众号支付 现在脑里一片空白,完全不知从哪开始.有许多小白问题请教,可以给个企鹅号么` 万分感谢
java9
java9

引用来自“3kqing”的评论

你好,获取用户openid的key和下单用的key不是一个吗?
不是一个。支付有单独的Key
Skqing
Skqing
你好,获取用户openid的key和下单用的key不是一个吗?
java9
java9

引用来自“失色太阳”的评论

你好,微信给的JSAPI没有java版本的,现在我做到统一下单,老是签名错误,尝试用接口调试工具对着做还是签名错误,这是什么情况?
你是用的公众号支付还是APP支付?两者下单的参数不一样。另外jsapi 没有java版本这个说法也不准确,下单操作都是通过后台去操作的。
失色太阳
你好,微信给的JSAPI没有java版本的,现在我做到统一下单,老是签名错误,尝试用接口调试工具对着做还是签名错误,这是什么情况?
似故人来
似故人来
能否给源码下,万分感谢。企鹅:757671834 万分感谢
支付宝H5支付和微信的H5支付

支付宝H5支付和微信的H5支付 PS:下面文章创建于2016年,当时微信还没有开放标准H5支付,只是可以通过公众号间接打通H5支付,所以下面的微信H5支付,归属于【公众号支付】方式 官网 支付宝:...

NO17 ⋅ 2016/08/30 ⋅ 0

微信支付2016开发调试过程记录

最近换了家公司,因为以前也是做支付的来这个公司直接让我从零开始搭建支付服务。首先是微信支付宝的第三方接入。我是做java开发的。支付宝有接入的sdk就是一个jar包。而且有沙箱环境测试帐号...

挨踢人生 ⋅ 2016/11/15 ⋅ 0

10步搞定微信支付的扫码支付

先要有微信公众号,从公众号左侧菜单进入微信支付,要先申请微信支付,申请通过之后,即可使用,涉及到2个后台:公众号后台和支付平台后台 首先要得到AppID(应用ID)和AppSecret(应用密钥),获...

爬墙 ⋅ 2016/01/23 ⋅ 2

微信公众号支付【Java版】

微信公众号支付【Java版】 说明: ① 本文主要讲解的是微信公众号内(商城)支付部分,如需了解其他微信公众号开发内容,请访问:http://blog.csdn.net/lyq8479/article/details/8944988 【柳...

大兵瑞恩 ⋅ 2016/05/31 ⋅ 5

Magento微信支付插件(JSAPI),微信公众号支付,支持Magento1.9.2

经过一周多的调试、修改、测试,Magento微信公众号支付插件终于完成了! 在网站上接入微信支付,有两种方式: 一、微信扫码支付:也称微信Native支付,适用于大家熟知的PC网站,访客在网站选...

Alipaymate ⋅ 2015/10/31 ⋅ 0

一张二维码集成微信、支付宝支付

解决方案是通过User-Agent 来判断扫描的来源 此项目已开源欢迎Start、PR、发起Issues一起讨论交流共同进步 https://github.com/Javen205/IJPay http://git.oschina.net/javen205/IJPay Http...

javen205 ⋅ 2017/01/20 ⋅ 0

微信营销初学者必须弄懂的名词解释

1.微信公众平台   微信公众平台是微信公众账号申请入口和管理后台。商户可以在公众平台提交基本资料、业务资料、财务资料申请开通微信支付功能。   平台入口:http://mp.weixin.qq.com。...

雪深 ⋅ 2015/06/27 ⋅ 0

php微信支付接口开发程序(概念篇)

From: https://www.bbsmax.com/A/KE5QLr1kJL/ 阅读对象 本文阅读对象:商户系统(在线购物平台、人工收银系统、自动化智能收银系统或其他)集成微信支付涉及的技术架构师,研发工程师,测试工...

朱先忠老师 ⋅ 2017/09/03 ⋅ 0

微信支付接入的那点事儿

本文来自作者 javen 在 GitChat 上分享「微信支付接入的那点事儿」,「阅读原文」查看交流实录 「文末高能」 编辑 | 嘉仔 前言 本次 Chat 中涉及到的图片、统计数据均来自于网络,截图均为 ...

gitchat ⋅ 2017/11/23 ⋅ 0

关于微信支付

微信支付作为当下第二大第三方,毋庸置疑是大家都要接入的支付方式。 我们就接入了微信支付除刷卡支付之外所有的支付方式,包括隐藏的wap支付。 微信支付和大众化的支付异同点: APP支付就是...

Object_小风 ⋅ 2016/07/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

istio 文档

https://istio.io/docs/concepts/ https://istio.io/docs/concepts/traffic-management/handling-failures/ https://istio.io/docs/concepts/traffic-management/rules-configuration/......

xiaomin0322 ⋅ 14分钟前 ⋅ 0

编程语言的作用及与操作系统和硬件的关系

一、编程语言的作用及与操作系统和硬件的关系 作用:编程语言是计算机语言,是一种程序员与计算机之间沟通的介质,通过编程语言可以使得计算机能够根据人的指令一步一步去工作,完成某种特定...

slagga ⋅ 25分钟前 ⋅ 0

runtime实现按钮点击事件

也不能说是实现吧,,,就是有点类似于RAC里边的写法,不用给btn添加另外的点击事件,就那个add...select...这样子很不友好,来看下代码: [self.btn handleControlEvent:UIControlEventTou...

RainOrz ⋅ 25分钟前 ⋅ 0

Windows系统运维转linux系统运维的经历

开篇之前,首先介绍一下我的背景把:我是一个三线城市的甲方运维。最近,在《Linux就该这么学》书籍的影响下和朋友小A(Linux运维已经三年了,工资也比我的高很多)的影响下,决定转行。最近...

linux-tao ⋅ 26分钟前 ⋅ 0

zip压缩工具,tar打包工具

zip压缩工具 zip打包工具跟前面说到的gzip,bz2,xz 工具最大的不一样是zip可以压缩目录。如果没有安装,需要使用yum install -y zip 来安装。安装完之后就可以直接使用了,跟之前提到的压缩...

李超小牛子 ⋅ 34分钟前 ⋅ 0

使用npm发布自己的npm组件包

一、注册npm账号 官网:https://www.npmjs.com/signup 注册之后需要进行邮箱验证,否则后面进行组件包发布时候会提示403错误,让进行邮箱核准。 二、本地新建一个文件夹,cd进入后使用npm i...

灰白发 ⋅ 36分钟前 ⋅ 0

010. 深入JVM学习—垃圾收集策略概览

1. 新生代可用GC策略 1. 串行GC(Serial Copying) 算法:复制(Copying)清理算法; 操作步骤: 扫描年轻代中所有存活的对象; 使用Minor GC进行垃圾回收,同时将存活对象保存到“S0”或“S...

影狼 ⋅ 36分钟前 ⋅ 0

JVM性能调优实践——JVM篇

在遇到实际性能问题时,除了关注系统性能指标。还要结合应用程序的系统的日志、堆栈信息、GClog、threaddump等数据进行问题分析和定位。关于性能指标分析可以参考前一篇JVM性能调优实践——性...

Java小铺 ⋅ 37分钟前 ⋅ 0

误关了gitlab sign-in 功能的恢复记录

本想关sign-up的,误点了sign-in 退出后登录界面提示: No authentication methods configured 一脸懵逼.. 百度后众多方案说修改application_settings 的 signin_enabled字段; 实际上新版本字段...

铂金蛋蛋 ⋅ 38分钟前 ⋅ 0

登录后,后续请求接口没有带登录cookie可能原因

1.XMLHttpRequest.withCredentials没设置好,参考https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/withCredentials...

LM_Mike ⋅ 38分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部