微信支付—微信H5支付「微信内部浏览器」

前言

微信支付-微信H5外部浏览器支付
微信支付-微信H5内部浏览器支付本文
微信支付-PC端扫码支付待写

本篇是微信支付系列的第二篇、微信H5内部浏览器支付,关于微信H5外部浏览器唤起微信APP支付,请参考上一篇文章。

开发环境:Java + SpringBoot + Vue +WxJava(开源SDK)

扫盲补充:关于微信内部浏览器支付,支付时会直接调起微信支付,不同于外部浏览器支付,内部浏览器支付首先需要获得当前支付用户对该公众号的唯一标识 openId「是否关注都是唯一的」,拿到 openId 后,结合后端其他参数调用微信预支付接口,获得预支付id,然后交由前端发起微信支付,支付成功后回调后端接口。

如下是正文部分。

1、获取Code

要想获得用户唯一标识 openid,首先需要办的事就是获得 code。

code 部分在本文中交由前端去获取「调用微信authorize授权方法」,拿到 code 后传递给后端换取 openid「用户唯一标识」;通常这个操作都是在用户登录时去实现的,登录成功后同时拿到 openid,而且还可以存(更新)到该用户的数据库方便后面使用。

前端获取code,具体如下:

let ua = navigator.userAgent.toLowerCase()if (ua.match(/MicroMessenger/i) == ‘micromessenger‘) {    if (!this.GetQueryString(‘code‘)) {        alert("跳转");        // this.$vux.toast.text(‘微信授权中……‘, ‘default‘)        let currentUrl = encodeURIComponent(window.location.href)        window.location.href = ‘https://open.weixin.qq.com/connect/oauth2/authorize?appid=我是appid&redirect_uri=‘+currentUrl+‘&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect‘    } else {        let code = this.GetQueryString(‘code‘)        // 此处调用后端方法,通过 code 换取 openid    }}

补充:授权链接中的 scope 参数分为 snsapi_base、snsapi_userinfo,snsapi_base 可以获得用户的唯一标识 openid,snsapi_userinfo 则在此基础上获得用户资料「昵称、头像等」

上述方法中 ua.match(/MicroMessenger/i) 是用来判断是否是微信环境的, GetQueryString 方法用来获取微信中的 code,如果当前浏览器 url 并没有附带 code 参数,那么就会调用微信的 authorize 方法进行授权,授权后获得 code,该方法具体如下:

GetQueryString (name) {    let url = new RegExp(‘(^|&)‘ + name + ‘=([^&]*)(&|$)‘)    let newUrl = window.location.search.substr(1).match(url)    if (newUrl != null) {        return unescape(newUrl[2])    } else {        return false    }},

2、换取openid

拿到 code 后,下一步就是调用后端接口换取 openid 了, 简单看一下换取 openid 的后端方法:

try {    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=我是appid&secret=我是secret&grant_type=authorization_code"+        "&code=" + loginRequest.getCode();    String body = RestTemplateUtils.get(url,new JSONObject());    JSONObject jsonObject = JSONObject.parseObject(body);    Integer errcode = jsonObject.getInteger("errcode");    if (errcode == null || errcode == 0) {        String openId = jsonObject.getString("openid");        //将此次登录的openId,暂且放入user的域里面,支付的时候会用到        System.out.println("openId:"+openId);        loginRequest.setOpenId(openId);        return ResultUtil.success(userService.login(loginRequest));    }else{        logger.error("[微信第三方登录] 异常”);        抛出自定义异常        throw new CommonException("微信第三方登录异常","");    }} catch (Exception e) {    logger.error("[微信第三方登录] 异常", e);    抛出自定义异常    throw new CommonException("微信第三方登录异常","");}

简单说一下该方法,前端传递 code 致后端方法,后端拿到 code 后,调用 access_token 接口获取 openid,同时完成登录操作。

至此,已经成功登录并拿到用户 openid 了,接下来就是调用支付接口。

3、预支付接口

上边已经提到了,内部浏览器支付是交由前端发起的,但是又依赖于后端的 预支付接口,所以先来看一下后端预支付接口:

/** * 生成订单「微信内部浏览器」 * @return */@Transactionalpublic Object wxPrepay(Orders orders,String openId) {    Object result = null;    try {        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();        orderRequest.setOutTradeNo(orders.getOrderId());        orderRequest.setOpenid(openId);        orderRequest.setBody(“我是商品描述信息");        orderRequest.setTotalFee(orders.getAmount().multiply(new BigDecimal("100")).intValue());        orderRequest.setSpbillCreateIp(DispatchParams.getInstance().getWechatSpbillCreateIp());        orderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);        result = wxPayService.createOrder(orderRequest);        if (result instanceof WxPayMpOrderResult) {            String prepayId = ((WxPayMpOrderResult)result).getPackageValue();            String paySign = ((WxPayMpOrderResult) result).getPaySign();            prepayId = prepayId.replace("prepay_id=", "");            orders.setPrepayId(prepayId);            orders.setSign(paySign);            ordersDao.updateOrders(orders);        }    } catch (WxPayException e) {        logger.error("[微信支付] 异常", e);        抛出自定义全局异常        throw new CommonException(WechatStatusEn.WECHAT_CREATE_CODE_ERROR.getErrorMsg()+"‘:微信支付异常", WechatStatusEn.WECHAT_CREATE_CODE_ERROR.getErrorCode());    } catch (Exception e) {        logger.error("[预付款异常]", e);        抛出自定义全局异常        throw new CommonException(WechatStatusEn.WECHAT_CREATE_CODE_ERROR.getErrorMsg()+"‘:预付款异常", WechatStatusEn.WECHAT_CREATE_CODE_ERROR.getErrorCode());    }    return result;}

简单说一下预支付方法,首先是根据自己情况创建订单记录,然后就是通过 openid 调用 wxPayService.createOrder 方法「WxJava」获取预支付id,该方法返回的实体为 WxPayMpOrderResult,实体参数为前端调起微信支付的必要参数,具体如下:

private String appId;private String timeStamp;private String nonceStr;@XStreamAlias("package")private String packageValue;private String signType;private String paySign;

为啥获得的预支付id没有用到呀?上方返回的参数并没有看到呀!

其实不然,属性 packageValue 的值为 prepay_id=预支付id ,该参数是必须的。

4、前端调用,发起支付

至此,后端基本完成了,我们将参数传递给前端调用,直接模拟返回后的数据:

假设下方是调用接口返回的数据

console.log(“我是后端返回的数据 - res:"+JSON.stringify(res))

const payParam = {    appId: res.appId,    nonceStr: res.nonceStr,    package: res.packageValue,    timeStamp: res.timeStamp,    signType: res.signType,    paySign: res.paySign,}

if (typeof WeixinJSBridge === ‘undefined‘) {    if (document.addEventListener) {        document.addEventListener(‘WeixinJSBridgeReady‘, this.onBridgeReady(payParam), false)    } else if (document.attachEvent) {        document.attachEvent(‘WeixinJSBridgeReady‘, this.onBridgeReady(payParam))        document.attachEvent(‘onWeixinJSBridgeReady‘, this.onBridgeReady(payParam))    }} else {    this.onBridgeReady(payParam)}

发起支付的 onBridgeReady 方法:

onBridgeReady(res){    alert("发起请求:"+JSON.stringify(res));    WeixinJSBridge.invoke(        ‘getBrandWCPayRequest‘, {            "appId":res.appId,     //公众号名称,由商户传入            "timeStamp":res.timeStamp, //时间戳,自1970年以来的秒数            "nonceStr":res.nonceStr, //随机串            "package":res.package, // prepay_id=xxx            "signType":res.signType, //微信签名方式:            "paySign":res.paySign //微信签名        },        function(res){            alert(JSON.stringify("我是支付返回的信息:\n"+res));            alert("我是支付返回的信息:\n"+res.err_msg);            if(res.err_msg == "get_brand_wcpay_request:ok" ){                // 使用以上方式判断前端返回,微信团队郑重提示:                //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。                alert("支付成功了");            }        }    );}

5、效果截图

再来简单总结一下,首先由前端获取 code,获取 code 后传递给后端换取 openid,openid 是预支付必须的参数,前端发起支付时,需要6个参数,此时调用后端预支付接口获取「wxPayService.createOrder」,前端支付成功后同样微信会自动回调后端 notify 接口,具体如下「代码仅供参考」:

@RequestMapping(value = "/notify")@ResponseBodypublic String notify(@RequestBody String body) throws Exception {

        WxPayOrderNotifyResult result = null;        try {            result = wxPayService.parseOrderNotifyResult(body);        } catch (WxPayException e) {            logger.error("[微信解析回调请求] 异常", e);            return WxPayNotifyResponse.fail(e.getMessage());        }        logger.info("处理微信支付平台的订单支付");        logger.info(JSONObject.toJSONString(result));

        String appid = result.getAppid();//应用ID        String attach = result.getAttach();//商家数据包        String bank_type =result.getBankType();//付款银行        Integer cash_fee = result.getCashFee();//现金支付金额        String fee_type = result.getFeeType();//货币种类        String is_subscribe = result.getIsSubscribe();//是否关注公众账号        String mch_id = result.getMchId();//商户号        String nonce_str = result.getNonceStr();//随机字符串        String openid = result.getOpenid();//用户标识        String out_trade_no = result.getOutTradeNo();// 获取商户订单号        String result_code = result.getResultCode();// 业务结果        String return_code = result.getReturnCode();// SUCCESS/FAIL        String sign = result.getSign();// 获取签名        String time_end = result.getTimeEnd();//支付完成时间        Integer total_fee = result.getTotalFee();// 获取订单金额        String trade_type = result.getTradeType();//交易类型        String transaction_id = result.getTransactionId();//微信支付订单号

        //如果成功写入数据库        if("SUCCESS".equals(return_code)) {// 如果微信返回的结果是success,则修改订单状态            Orders orders = ordersDao.selectByOrderId(out_trade_no);            // 验证签名            if(orders != null){                if(!"1".equals(orders.getOrderStatus())){//判断是否订单已经完成了                    // 判断金额是否跟数据库订单金额一致,放置人为修改                    if(orders.getAmount().multiply(new BigDecimal("100")).compareTo(new BigDecimal(total_fee)) == 0){                        //更新订单状态                        业务逻辑处理部分...                        return WxPayNotifyResponse.success("订单已经处理成功!");                    }else{                        logger.error("微信:金额不一致!");                        return WxPayNotifyResponse.fail("订单金额不一致");                    }                }else {                    return WxPayNotifyResponse.success("订单已经处理成功!");                }            }else{                return WxPayNotifyResponse.fail("商户订单号不匹配");            }        }        System.out.println("回调成功");        System.out.println("----返回给微信的xml:" + result);        return WxPayNotifyResponse.success("支付成功!");}

最后

博客地址:https://www.cgblog.com/niceyoo

如果觉得这篇文章有丶东西,不放关注一下我,关注是对我最大的鼓励~

18年专科毕业后,期间一度迷茫,最近我创建了一个公众号用来记录自己的成长。

原文地址:https://www.cnblogs.com/niceyoo/p/12235649.html

时间: 2024-10-07 08:50:00

微信支付—微信H5支付「微信内部浏览器」的相关文章

微信支付之扫码支付、公众号支付、H5支付、小程序支付相关业务流程分析总结

前言 很久以来,一直想写一篇微信支付有关的总结文档:一方面是总结自己的一些心得,另一方面也可以帮助别人,但是因种种原因未能完全理解透彻微信支付的几大支付方式,今天有幸做一些总结上的文章,也趁此机会,将一年多以来的相关经验分享一下. 概述 1. 扫码支付 商户在pc端展示一个支付二维码,用户使用微信扫一扫功能,扫码后实现付款的支付方式. 2. 公众号支付 商户在微信APP内(微信浏览器)打开H5网页,通过微信支付实现付款的支付方式. 3. H5支付 商户在微信浏览器以外的手机浏览器打开H5网页,通

微信公众号H5支付-JAVA版

微信开发之微信公众号H5支付-JAVA版 引子 从事JAVA开发一年多了,一直都在看博客园,CSDN的博客,从很多前人哪里学习了很多,突然觉得自己也要尽一份力,写点博客自己给自己做做记录,也给要开发微信人提提醒少遇点坑. 很多人开发微信的时候,总是在抱怨微信的开发文档很坑,里面的参数和使用方式很含糊,其实有时候自己想想,如果自己去研发API的时候,是否能够做的比微信更好呢?,大师都有一颗虔诚学徒的心,希望这篇文档能给予从事微信公众号H5支付焦头烂额的朋友,一点帮助. 一.前言 先给大家提提从事微

微信公共号H5支付。

1.接受支付信息. /** * 发起支付请求 * @return [type] [description] */ function pay($openid){ $nonce_str = $this->rand_code(); //调用随机字符串生成方法获取随机字符串 $data['appid'] = $this->appid; //appid $data['mch_id'] = $this->mch_id ; //商户号 $data['body'] = 'ceshi'; $data['s

asp.net core 微信支付工具类(H5支付,扫码支付,公众号支付,app支付)之2-H5支付

上一篇说到微信扫码支付,今天来分享下微信H5支付,适用场景为手机端非微信浏览器调用微信H5支付惊醒网站支付业务处理.申请开通微信H5支付工作不多做介绍,直接上代码. 首先是微信支付业务类(WxPayService)中的方法,传上必要的参数,该方法将会构造请求XML字符串到微信api接口,H5支付用到的是返回XML参数的mweb_url的值,控制器中的Aciton方法调用该业务层方法得到mweb_url的值,此时,前端ajax调用控制器返回mweb_url值,直接将window.localtion

微信H5支付demo

首先我们必须得在微信公众平台和微信商业平台那边配置好相关配置 1.注册微信服务号,开通微信支付权限绑定微信商业平台(这个具体怎么操作我就不说了) 2.获取应用(公众号)appid.应用(公众号)秘钥.商户号.商户API秘钥这四个配置信息 3.微信商业平台开通H5支付权限,配置支付域名(是要ICP备案的域名), 4.微信公众号配置白名单(也就是服务器ip) 5.开始写代码实现微信H5支付了(首先我们得理清H5支付跟其他类型支付的区别) 5.1.直接用微信客户段支付的那个是JSAPI支付模式 5.2

微信支付:手机系统自带的浏览器,调用微信支付如何实现(非扫码)

Q:翻看了微信支付的api没发现支持h5调支付接口的情况(微信js除外),然后却发现美团的支付成功调用了,这是怎么实现的?     A: 使用微信H5支付即可.H5支付通过URL调起微信APP,不涉及到应用签名,可解决一次申请给多款APP使用的问题,看看现在游戏分发行业就知道了. 现在从官网申请到的APP支付(即通过SDK调起微信APP),如果适用在公司只有几款APP的情况,完全没问题.但是如果一家公司有几十几百款APP的话,使用APP支付就不合适了.(APP支付要求申请APPID,但每家公司主

uni.app实践---微信公众号h5开发记实-----第一篇

介绍:==uni-app== 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可编译到iOS.Android.H5.以及各种小程序(微信/阿里/百度/头条/QQ)等多个平台. uni-app官网:传送门 uni-app插件市场:传送门 前一段时间因为个人了解到这个比较nb的多端开发框架,所以有兴趣自己去尝试了一下,从开始的搭建项目到微信公众号h5的登录-->微信支付都尝试了一遍.第一次尝试也踩了很多的坑.相信有很多小伙伴也遇到过这样的疑惑和问题.(大神略过),所以在这里写下

「每日一歌」微信公众号

最近弄了一个微信公众号,叫做「每日一歌」(微信ID:Song_Daily).每天早上6点,分享一首经典歌曲.欢迎各位来关注! 音乐,广义而言,就是指任何以声音组成的艺术.英文Music一词源于古希腊语的μουσικ?(mousike),意即缪斯(muse)女神的艺术.而中文的音乐二字,许慎<说文解字>解释为“音,声也.生于心,有节于外,谓之音.”认为音乐和声音的区别,在于音乐需要透过人心去想像和创造.音乐可分为创作.演奏.聆听三个过程,在不同文化和社会,对于音乐的过程及其重要性都有不同的理解.

支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结

前言 在上一篇文章<微信支付之扫码支付.公众号支付.H5支付.小程序支付相关业务流程分析总结>中,分析和总结了微信支付相关支付类型的业务流程,这里作为与微信支付平起平坐不相伯仲的支付宝支付,当然也是每个公司少不了的第三方支付接入选择. 因此,本篇文章主要分析和总结支付宝支付中的扫码支付.H5支付相关业务流程. 概述 1. 电脑网站支付 电脑网站支付,也称扫码支付,是专门针对电脑而开发的一种支付方式,既在网页展示一个动态生成的支付二维码,用户通过手机支付宝扫码以后可实现支付功能的一种支付方式.