一、微信授权
1、在对接微信之前,首先从微信官网(https://mp.weixin.qq.com)去注册微信公众公众账号,提交资料等待验证通过。

2、验证通过后就可以 微信公众平台 获取到 AppID 和 AppScret 两个参数值,如图:

3、网页授权域名
如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
在 “开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名” 进行网页域名授权,需要下载校验文件并放在项目根目录下,注意能被访问到,避免拦截器,过滤器等拦截了,如图:

4、此时,按照微信官方文档,需要进行 填写服务器配置,参考微信接入指南 (https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319),如图:

注意:
URL 参数是一个接口地址,需要写一个接口(http://xx.xx.com/x/xSignature类似的)供微信端调用校验。
Token 自己填写。
如图:

只要能返回 随机字符串 就可以通过。
调用成功后如图:

注意:只要验证通过,微信自定义菜单就会失效,需要调用接口生成自定义菜单,生成方式查看微信开发文档,可以在微信公众平台线接口调试生成。

5、因为需要调用接口生成菜单,所以需要获取 调用接口的 access_token。
https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?
grant_type=client_credential&appid=APPID&secret=APPSECRET
创建菜单接口 POST
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

6、在项目中进行拦截,微信端嵌套H5页面。
代码1

// 判断是否微信端跳转
if(userAgent.contains("micromessenger")){String version = userAgent.substring(userAgent.indexOf("micromessenger"));System.out.println("微信请求...去授权");weChatAuthorityUtil.weChatRedirect(request,response);
}

然后跳转到微信端进行授权,并且传入回调接口地址,用于获取code 和 state 两个参数值,code 和 state 两个参数用于获取微信用户信息,在微信端校验。

代码2

@RequestMapping(value = "/ucode", method = RequestMethod.GET)
public void weChatCode(HttpServletRequest request, HttpServletResponse response, String code, String state){if(code != null && code.length() > 0 && propertiesUtil.getState().equals(state)){//通过 code  获取 access_token,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期Map<String,String> param = new HashMap<String,String>();param.put("appid",propertiesUtil.getAppId());param.put("secret",propertiesUtil.getAppSecret());param.put("code",code);param.put("grant_type","authorization_code");//获取用户token openidString resStr = HttpUtil.doPostMap(WXPayConstants.WECHAT_ACCESS_TOKEN,param);if(resStr != null && resStr.length() > 0){System.out.println("获取token resStr = " + resStr);Map<String,Object> res = JSON.parseObject(resStr,Map.class);String errcode = (String) res.get("errcode");if(errcode == null){ //errcode 错误码String accessToken = (String) res.get("access_token");int expiresIn = (int) res.get("expires_in");String openId = (String) res.get("openid");String scope = (String) res.get("scope");//首先从数据库中获取用户信息,没有从微信端获取UserIdentity userIdentity = userService.getUserIdentityByOpenId(openId);if(userIdentity != null){ //数据库中没有获取到,第一次登录//数据库里面有,放入session//业务逻辑}else{//获取用户信息 存库  加入sessionuserIdentity = weChatAuthorityUtil.getUserInfoBy(openId,accessToken);//业务逻辑}}else{String errmsg = (String) res.get("errmsg");//此处,说明微信获取token失败}}}
}

二:微信支付
1、在对接微信支付之前,同上,也是需要去 “微信支付商务” 平台去开通;
选择支付方式 JSAPI,NATIVE,APP,MWEB–H5支付
在 微信商户平台 ——> 账户中心 配置个人信息; 在 API安全 中配置 API密匙(后面调用下单接口需要用到,32为码)
在 微信商户平台 ——> 产品中心——>开发配置 添加域名配置,授权等

2、此项目首先选择 JSAPI支付,首先需要调用 统一下单(URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder)接口在微信端下单。
注意:在 统一下单 接口里面,需要对接口参数(sign)进行一个签名认证,签名算法看官方文档(接口规则 --> 安全规范)

为了校验签名是否正确,用 签名校验工具 验证

此处 商户Key 为 商户号

把生成的xml结构的参数粘贴进去,参数中需要有 sign 已生成好的签名进行校验,代码3 类似这样:

<?xml version="1.0" encoding="UTF-8"?>
<xml><appid>wx69767be593fa4866</appid><body>水费-缴费</body><mch_id>1543011521</mch_id><nonce_str>20ef119e812exxxxxxxxxxa448b57ebc</nonce_str><notify_url>http://xx.xxx.com/xx/callback</notify_url><out_trade_no>82bae3axxxxxxxxxxxa17aff7310097b</out_trade_no><spbill_create_ip>123.151.0.0</spbill_create_ip><total_fee>50</total_fee><trade_type>JSAPI</trade_type><sign>758394EB3F6A59E60BE3BCB21D1DD166</sign><openid>oxrDv57zsMrMtnPvLoDZZmnAkWDE</openid>
</xml>

3、此时需要进行调用微信 统一下单(https://api.mch.weixin.qq.com/pay/unifiedorder) 接口生成微信端订单。
此接口 为 post提交,xml的形式传参数。类似上面提到的xml格式的数据 代码3。
统一下单接口中 签名校验 和 页面JS 发起支付需要的签名算法一样。
代码4

@RequestMapping(value = "/payment",method = RequestMethod.GET)
public ModelAndView wxPayment(HttpServletRequest request, HttpServletResponse response, Long id){ModelAndView modelAndView = new ModelAndView("view/");PayBill payBill = new PayBill();payBill.setId(BigInteger.valueOf(id));RsFeesMessage rsFeesMessage = payBillService.getFeesMessage(payBill);UserIdentity userIdentity = (UserIdentity) request.getSession().getAttribute(SessionConstant.ACCOUNT_SESSION_KEY);WxPayEntity result = new WxPayEntity();try {//查询账单信息,使用账单中的金额PayBill bill = payBillService.getBillMessage(id);//商户订单号String outTradeNo = WXPayUtil.getOut_trade_no();//产品价格,单位:分BigDecimal multiply = bill.getPaymentAmount().multiply(new BigDecimal(100));Integer totalFee = multiply.intValue();//客户端ipString ip = request.getRemoteAddr();//支付成功后回调的url地址String notifyUrl ="http//xx.xx.com/pay/callback";//String nonceStr = WXPayUtil.getNonceStr();//随机数据WxPayEntity payEntity = new WxPayEntity();payEntity.setBody("水费-缴费");payEntity.setOutTradeNo(outTradeNo);payEntity.setTotalFee(totalFee);payEntity.setNotifyUrl(notifyUrl);payEntity.setOpenId(userIdentity.getOpenId());payEntity.setAppId(propertiesUtil.getAppId());payEntity.setMchId(propertiesUtil.getMchId());payEntity.setAppKey(propertiesUtil.getAppKey());/*SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");long time = 30*60*1000;//30分钟Date afterDate = new Date(new Date().getTime() + time);//30分钟后的时间String timeExpire = sdf.format(afterDate);*///统一下单String strResult = WXPayUtil.unifiedorder("测试", outTradeNo, totalFee,ip, notifyUrl,userIdentity.getOpenId(),propertiesUtil.getAppId(),propertiesUtil.getMchId(),propertiesUtil.getAppKey());//将解析结果存储在HashMap中Map map = WXPayUtil.doXMLParse(strResult);//返回状态码String returnCode = (String) map.get("return_code");String resultCode = (String) map.get("result_code");System.out.println("resultCode = " + resultCode);System.out.println("----------------------------------------------");//两者都为SUCCESS才能获取prepay_idif( returnCode.equals(WXPayConstants.SUCCESS) && resultCode.equals(WXPayConstants.SUCCESS) ){System.out.println("统一下单成功...");//业务逻辑,写入订单日志(你自己的业务) .....payBill.setUserId(userIdentity.getId());//修改账单表 支付中payBillService.updatePayBillById(payBill);String timeStamp = WXPayUtil.getTimeStamp();//时间戳String nonceStr = WXPayUtil.getNonceStr();//随机字符串//注:上面这两个参数,一定要拿出来作为后续的value,不能每步都创建新的时间戳跟随机字符串,不然H5调支付API,会报签名参数错误String prepayId = (String) map.get("prepay_id");System.out.println("prepayId = " + prepayId);result.setResultCode(resultCode);result.setAppId(propertiesUtil.getAppId());result.setTimeStamp(timeStamp);result.setNonceStr(nonceStr);result.setPackageStr("prepay_id="+prepayId);result.setSignType(WXPayConstants.MD5);/*redisUtil.set(userIdentity.getId()+"_prepay_id",prepayId);redisUtil.setObject(RedisConstant.PREPAY_ID_KEY,userIdentity,RedisConstant.KEY_EXPIRE_30m);*///WXPayUtil.unifiedorder(.....) 下单操作中,也有签名操作,那个只针对统一下单,要区别于下面的paySign//第二次签名,将微信返回的数据再进行签名SortedMap<Object,Object> signMap = new TreeMap<Object,Object>();signMap.put("appId",propertiesUtil.getAppId());signMap.put("timeStamp", timeStamp);signMap.put("nonceStr", nonceStr);signMap.put("package", "prepay_id="+prepayId);  //注:看清楚,值为:prepay_id=xxx,别直接放成了wxReturnData.getPrepay_id()signMap.put("signType", WXPayConstants.MD5);String paySign = WxSign.createSign(signMap,  propertiesUtil.getAppKey());//支付签名result.setSign(paySign);}else{result.setResultCode(WXPayConstants.FAIL);if((map.get("return_code")).equals(WXPayConstants.FAIL)){saveBillLog(payBill,(String) map.get("return_msg"));}else if((map.get("result_code")).equals(WXPayConstants.FAIL)){saveBillLog(payBill,(String) map.get("err_code_des"));}}} catch (Exception e) {e.printStackTrace();}modelAndView.addObject("rsFeesMessage",rsFeesMessage);modelAndView.addObject("result",result);return modelAndView;
}

生成签名算法:
代码5

public static String createSign(SortedMap<Object,Object> parameters, String key){StringBuffer sb = new StringBuffer();Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)Iterator it = es.iterator();while(it.hasNext()) {Map.Entry entry = (Map.Entry)it.next();String k = (String)entry.getKey();Object v = entry.getValue();if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + key);String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();return sign;
}

4、下单成功后,将获取到的订单号 prepay_id 参数传递到页面进行调用JS支付此订单。
注意:传输到页面的package参数是订单号,参数格式为 prepay_id=11111111111
代码6

function onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest', {"appId":appId,           //公众号名称,由商户传入"timeStamp":timeStamp,  //时间戳,自1970年以来的秒数"nonceStr":nonceStr,  //随机串"package":package,"signType":signType,    //微信签名方式:"paySign":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 if(res.err_msg == "get_brand_wcpay_request:fail"){//支付遇到问题}});}var fn = function() {alert($("input[name='checkbox']").is('checked'));if(resultCode == "SUCCESS"){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();}}}

5、在前段用js发起支付,微信就可以支付了
6、支付成功,微信回调你的回调接口,放回支付成功信息,咋流中获取xml数据:

@RequestMapping("/callback")
@ResponseBody
public String callback(HttpServletRequest request, HttpServletResponse response){System.out.println("支付回调...");String resXml = "";InputStream inStream;Map resultMap = null;PayBill payBill = new PayBill();try {inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}// 获取微信调用我们notify_url的返回信息String result = new String(outSteam.toByteArray(), "utf-8");// 关闭流outSteam.close();inStream.close();resultMap = WXPayUtil.doXMLParse(result); //解析为Map//返回状态码String returnCode = (String) resultMap.get("return_code");String resultCode = (String) resultMap.get("result_code");//String sign = (String) resultMap.get("sign");if (resultCode.equals(WXPayConstants.SUCCESS)) {logger.info("wxnotify:微信支付----返回成功");String xmlStr = WXPayUtil.mapToXml(resultMap);//验证签名 和之前一样方式验证boolean flag = WXPayUtil.isSignatureValid(xmlStr,propertiesUtil.getAppKey());// 保存数据或者 处理业务}} else {logger.error("wxnotify:支付失败,错误信息:" + resultMap.get("return_msg"));resXml = resFailXml;}}catch (Exception e) {logger.error("wxnotify:支付回调发布异常:", e);} finally {//处理数据saveBillLog(payBill,(String)resultMap.get("return_msg"));}// <xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>//需要给微信端返回结果,要不一直调好几次return resXml;
}

从微信授权到微信支付相关推荐

  1. 微信授权及微信支付跳转回来的路径带有#的hash路径会被忽略

    使用微信授权和微信h5支付时,需要配置 redirect_uri 参数,如果参数里面的路是带有#的hash路径时,#后面的内容会被微信认为是不合法的,然后会被微信忽略掉,比如配置的是 http://w ...

  2. 微信公共平台接入之:网页授权(微信授权,微信access_token获取,获取微信用户信息),微信开发者工具使用,微信公众平台测试号申请接入

    1.微信公众平台文档入口 微信公众平台入口地址:https://mp.weixin.qq.com/,截图: 进入之后的文档地址: https://mp.weixin.qq.com/wiki?t=res ...

  3. 微信授权登录-微信公众号和PC端网站

    一.微信公众号授权登录--微信公众平台 微信授权登录,并调用后台接口,获取用户信息 1.网页授权回调域名 首先要在公众平台官网中的"开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授 ...

  4. html获取微信授权以及微信支付

    最近在写h5项目的时候,有个功能是扫描二维码,进行微信支付以及支付宝支付. 1:首先有一个扫码后需要跳转的页面,我这边使用的html,调用接口使用的是ajax,很长时间没用了,还有点不习惯. ①:先说 ...

  5. angularjs 微信授权登录 微信支付

    最近做一个项目,用angular 一个单页应用,打算打包成 跨平台移动App 以及在微信里面使用.给大家一个案例 首先,熟悉一下微信授权部分的源代码,如下所示: javascript 前端代码: va ...

  6. 小程序 - 微信授权登录 微信授权绑定手机号

    用户在使用小程序时,经常需要授权登录,授权登录的作用是获取用户的基本信息,如头像.昵称以及openid等,openid可用于微信授权手机号.微信支付. 微信授权登录 .xhtml如下,wxLogin为 ...

  7. 微信授权登录(微信订阅号使用测试账号)

    1.微信授权登录: 微信公众号测试登录: 准备: 1.1 花生壳! 下载地址:http://hsk.oray.com/download/ 1.2 微信公众号:https://mp.weixin.qq. ...

  8. 微信授权-获取微信授权后用户信息

    微信授权登陆: 我采用的是自定义的子菜单:登陆微信公众平台 第一步:用户同意授权.获取code 第二步:通过code换取网页授权access_token 详细步骤参考微信公众号平台 在页面地址输入授权 ...

  9. 微信小程序 微信授权登录 微信登录

    一.调用接口获取临时登录凭证(code) wx.login({success(res) {if (res.code) {// res.code => 登录凭证} else {console.lo ...

最新文章

  1. 第三百三十八节,Python分布式爬虫打造搜索引擎Scrapy精讲—深度优先与广度优先原理...
  2. 分享用mockplus原型图工具制作的
  3. 两个数据集,本地可以关联,正式库关联不了
  4. User-Agent-Switcher和fiddler
  5. zabbix nginx error log监控
  6. 电商网站前端架构 学习笔记(全是干货)
  7. android mvvm 官方例子,详解Android的MVVM框架 - 数据绑定
  8. 五年26个版本:Linux系统内核全程回顾
  9. 利用shell找出15分钟内修改的文件
  10. html5 跳转参数不显示_HTML5、CSS3、ES6新特性总结
  11. Eclipse或MyEclipse—在Eclipse或MyEclipse中的操作(1)
  12. 高数复习: 多元函数微分学及其应用
  13. qt打开xls文件_Qt读取excel文件的两种方法
  14. python猜数字统计游戏次数_猜数字游戏的实现(Python3.5)
  15. NO 00004 iOS实现打砖块游戏 一 素材的制作
  16. 一个简单的蓝牙指令测试工具
  17. vue中使用Vue-i18n插件实现页面中英文切换详细教程
  18. c语言tcp多线程聊天,基于tcp和多线程的多人聊天室-C语言
  19. mac latex使用记录
  20. 数据库cpu飙升,使用pt-kill工具记录慢sql,并杀死sql保障数据库不挂掉

热门文章

  1. OPPO手机如何下载便签里的文件
  2. 【Linux权限】Shell命令及运行原理 | Linux权限管理 | 粘滞位
  3. 软件工程职业_关于软件工程职业的7个关键思考
  4. pod install 报 cannot load such file -- executable-hooks/wrapper (LoadError)
  5. 2021年9月世界编程语言排行
  6. C语言游戏3:飞机游戏
  7. Skype营销大师群控版
  8. 中国金融认证中心技术标准
  9. VisionMaster与优傲机器人 UR5e 进行Modbus通讯
  10. android百度输入法源码,百度输入法V1.1.0.19 For Android发布