微信支付之Native支付和JSAPI支付详细开发步骤!

article/2025/9/12 22:33:01

目录标题

    • 微信支付之扫码Native支付与JSAPI支付
      • 进入主题
        • 一、Native支付
          • 1. 使用场景
          • 2. 开发步骤
          • 3. 开始开发
        • 二、JSAPI支付
          • 1. 使用场景
          • 2. 开发步骤
          • 3. 开始开发

微信支付之扫码Native支付与JSAPI支付

在电商网站开发中,我们必不可少的功能环节就是“支付”了,我们可以根据公司或者自己的开发需求,选择不一样的支付方式,比如微信支付,支付宝支付,银联支付,以及跨境支付如PayPal等等的众多方式供你选择,今天,我将和大家聊聊微信支付之二微信扫码Native支付与微信JSAPI支付。

进入主题

根据微信官方提供的文档,我们来进行梳理。首先我们访问:微信支付-开发文档
进入如下界面:

在这里插入图片描述

一、Native支付

1. 使用场景

我们首先会调用微信提供的API得到二维码链接,这个链接可以通过前端qrcode.js将链接转换为二维码,也可以在后台通过谷歌的ZXing工具生成二维码。详细介绍如下:

在这里插入图片描述

2. 开发步骤

首先,你需要在微信支付的商户平台配置扫码支付的回调域名,具体位置为:商户平台–>产品中心–>开发配置。

在这里插入图片描述

当然,你也可以不用配置扫码支付的回调地址,而是在调用微信支付的统一下单API接口中传递参数notify_url。我选的是这种方式,可以将回调配置在yml文件中,自由定义,不需要关心商户平台的回调地址。

在这里插入图片描述

最后,还需要选择一种模式,我采用的是模式二,你也可以根据自己的需求,选择你认为合适的开发模式。如下图模式二说明了接下来我们编码的流程:

在这里插入图片描述

在这里插入图片描述

3. 开始开发

(1)商户后台系统根据用户选购的商品生成订单。

用户在商城平台提交订单,我们会生成初始订单。

在这里插入图片描述

商城平台生成订单之后,接着调用微信支付。进行第二,第三步骤,如下:

(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

这一步骤,有一个关键的地方是生成商户单号。如下是我生成商户单号的方式。

在这里插入图片描述

生成商户单号

@Override@Transactional(rollbackFor = Exception.class)public String generateCode(KeSequence.Tag tag,  String userMobile) {Long sequence = this.findSequence(Long.parseLong(tag.getCode()+""));this.updateSequence(Long.parseLong(tag.getCode()+""),sequence);return DateWithRandomUtils.numsToRandom()+ sequence+ ((userMobile.length()>4)?(userMobile.substring(userMobile.length()-4)):userMobile);}

调用工具方法

/*** 将生成的时间+num位随机数,打乱* @return*/public static String numsToRandom(){String randomNO = randomNO(4);char[] chars = randomNO.toCharArray();List<String> list = new ArrayList<>();for (char aChar : chars) {list.add(aChar+"");}Collections.shuffle(list);StringBuffer sb = new StringBuffer();list.forEach(ch->{sb.append(ch);});return sb.toString();}

工具方法细节:

/*** 唯一编号 = 点前时间年月日时分秒+num位随机数* @return*/public static String randomNO(int num){String newsNo = timeNoYMDHMS();long random = getRandom(num);return newsNo+random;}/*** 获取当前时间 yyyyMMddHHmmss* @return*/public static  String timeNoYMDHMS(){//设置日期格式SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");// new Date()为获取当前系统时间,也可使用当前时间戳String newsNo = df.format(new Date());return newsNo;}/*** 生成固定长度随机码* @param n    长度*/public static long getRandom(long n) {long min = 1,max = 9;for (int i = 1; i < n; i++) {min *= 10;max *= 10;}long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min ;return rangeLong;}

(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

生成商户单号,接着可以通过微信提供的SDK,调用统一下单的方法了,我的做法如下:

核心代码:

/*** 微信支付* @param keOrder* @return*/private ResultMsg WxUnifiedorder(KeOrder keOrder,String bizPayNo, Integer tradeType, String openid) throws Exception {//设置需要的参数WxParamQuery wxParamQuery = new WxParamQuery();//是wxParamQuery.setOut_trade_no(bizPayNo);//以分为单位wxParamQuery.setTotal_fee(keOrder.getActualTotal().multiply(BigDecimal.valueOf(100)).longValue()+"");String body = "";if(!StringUtils.isEmpty(keOrder.getProdName())){body = keOrder.getProdName().length()>15 ? keOrder.getProdName().substring(0,15)+"...":keOrder.getProdName();}wxParamQuery.setBody(body);wxParamQuery.setReceipt("N");// 注意:此处配置交易方式, JSPAI, NATIVE...wxParamQuery.setTrade_type(WxParamQuery.getTradeTypeMap(tradeType));//否wxParamQuery.setAttach(keOrder.getOrderNo());wxParamQuery.setProduct_id("");wxParamQuery.setOpenid(openid);wxParamQuery.setDetail("");wxParamQuery.setDevice_info("WEB");wxParamQuery.setUserId(keOrder.getUserId());return wxPayService.unifiedorder(wxParamQuery);}

调用统一下单API:

/*** 微信支付-统一下单* @param wxParamQuery* @return*/@Override@Transactionalpublic ResultMsg unifiedorder(WxParamQuery wxParamQuery) throws Exception {Map<String,String> data = new ConcurrentHashMap();data.put("device_info",wxParamQuery.getDevice_info());data.put("body",wxParamQuery.getBody());data.put("detail",wxParamQuery.getDetail());data.put("attach",wxParamQuery.getAttach());data.put("out_trade_no",wxParamQuery.getOut_trade_no());data.put("total_fee",wxParamQuery.getTotal_fee());data.put("trade_type",wxParamQuery.getTrade_type());data.put("product_id",wxParamQuery.getProduct_id());data.put("openid",wxParamQuery.getOpenid());data.put("receipt",wxParamQuery.getReceipt());data.put("spbill_create_ip", spbill_create_ip);if("JSAPI".equalsIgnoreCase(wxParamQuery.getTrade_type())){if(StringUtils.isEmpty(wxParamQuery.getOpenid())){return ResultMsg.fail("缺少参数openid",null);}}try {WXPayConfig payConfig =  new PayConfig(appID,mchID,key,domain,primaryDomain, true);WXPay wxPay = new WXPay(payConfig,notify_url,true,false);data = wxPay.fillRequestData(data);//微信提供的统一下单方法一:Map<String,String> resMap = wxPay.unifiedOrder(data);//主动调微信统一下单方法二/*String xml = WXPayUtil.mapToXml(data);String res = HttpHelper.post(pay_url, xml, "text/plain;charset=UTF-8");Map<String, String> resMap = WXPayUtil.xmlToMap(res);*/if("SUCCESS".equalsIgnoreCase(resMap.get("return_code"))){if("SUCCESS".equalsIgnoreCase(resMap.get("result_code"))){// 获取二维码链接String code_url = resMap.get("code_url");String prepay_id = resMap.get("prepay_id");Map<String, String> payParam = wxUtils.getJsapiPayParam(prepay_id);if(wxParamQuery.getTrade_type().equals(WxParamQuery.TradeType.NATIVE.name())){return ResultMsg.suc(code_url);}else{return ResultMsg.suc(payParam);}}}String return_msg = resMap.get("return_msg");return ResultMsg.fail(return_msg,return_msg);} catch (Exception e) {e.printStackTrace();return ResultMsg.fail(e.getMessage(),e.getMessage());}}

调用成功之后,微信会返回code_url, 二维码链接,至此,我们可以将二维码链接转换为二维码图片,即可。

当用户扫码支付完成之后,会进入回调,我们可以在回调中修改订单的状态或者其他必要的操作。如下,是我的回调代码。

核心代码:

@RequestMapping(value = "/notifyUrl")public void notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {String resXml = "";try {log.info("微信notifyUrl回调方法,开始进入。。。");//读取参数StringBuffer sb = new StringBuffer();InputStream inputStream = request.getInputStream();BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));String str = null ;while ((str = in.readLine()) != null){sb.append(str);}in.close();inputStream.close();//解析xml成mapMap<String, String> m = WXPayUtil.xmlToMap(sb.toString());//过滤空 设置 TreeMapSortedMap<String,String> packageParams = new TreeMap<>();Iterator<String> it = m.keySet().iterator();while (it.hasNext()) {String parameter = it.next();String parameterValue = m.get(parameter);String v = "";if(null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}log.info("微信支付返回回来的参数:"+packageParams);try {// 支付日志入库iKePayLogService.saveWxPayLog(packageParams);}catch (Exception e){e.printStackTrace();}//判断签名是否正确if(WXPayUtil.isSignatureValid(m, key, WXPayConstants.SignType.HMACSHA256)) {//------------------------------//处理业务开始//------------------------------if("SUCCESS".equalsIgnoreCase( packageParams.get("return_code")) &&"SUCCESS".equals(packageParams.get("result_code"))){// 这里是支付成功//执行自己的业务逻辑开始String app_id = packageParams.get("appid");String mch_id = packageParams.get("mch_id");String openid = packageParams.get("openid");//是否关注公众号String is_subscribe = packageParams.get("is_subscribe");//附加参数【订单号】String attach = packageParams.get("attach");//商户订单号String out_trade_no = packageParams.get("out_trade_no");//付款金额【以分为单位】String total_fee = packageParams.get("total_fee");//微信生成的交易订单号String transaction_id = packageParams.get("transaction_id");//支付完成时间String time_end= packageParams.get("time_end");log.info("app_id:"+app_id);log.info("mch_id:"+mch_id);log.info("openid:"+openid);log.info("is_subscribe:"+is_subscribe);log.info("out_trade_no:"+out_trade_no);log.info("total_fee:"+total_fee);log.info("额外参数_attach:"+attach);log.info("time_end:"+time_end);//执行自己的业务逻辑开始log.info("支付成功。。。执行自己的业务逻辑开始");OrderPayDTO orderPayDTO = new OrderPayDTO();orderPayDTO.setTransaction_id(transaction_id);orderPayDTO.setOut_trade_no(out_trade_no);orderPayDTO.setMch_id(mch_id);orderPayDTO.setApp_id(app_id);orderPayDTO.setAttach(attach);orderPayDTO.setTime_end(LocalDateTime.now());orderPayDTO.setOpenid(openid);orderPayDTO.setIs_subscribe(is_subscribe);orderPayDTO.setTotal_fee(BigDecimal.valueOf(Double.parseDouble(total_fee)));orderPayDTO.setPayType(KeOrder.orderPayType.WECHAT_PAY.getCode());//调用业务处理方法iKeOrderService.orderPaySuc(orderPayDTO);//执行自己的业务逻辑结束//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.resXml = notifyToWx("SUCCESS","OK");} else {log.info("支付失败,错误信息:" + packageParams.get("err_code"));resXml = notifyToWx("FAIL",packageParams.get("err_code"));}} else{resXml = notifyToWx("FAIL","签名验证失败");}}catch (Exception e){e.printStackTrace();resXml = notifyToWx("FAIL","程序异常");}//------------------------------//处理业务完毕//------------------------------BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();}public String notifyToWx(String return_code, String return_msg){return "<xml>" + "<return_code><![CDATA["+return_code+"]]></return_code>"+ "<return_msg><![CDATA["+return_msg+"]]></return_msg>" + "</xml> ";}

二、JSAPI支付

JSAPI支付的后端实现逻辑和Native之后一样,只需要多传入一个必传参数openid,上面已经列举,我就不必再次重复说明了。 接下来,我将说明和Native不同的实现逻辑。

1. 使用场景

我们开发公众号时,需要调用微信支付,这时候就是需要JSPAPI支付了,JSAPI需要通过网页授权,获取用户的openid,也就是上述步骤中调用微信的统一下单需要的步骤,然后再改变trade_type为JSAPI,如下
在这里插入图片描述
其余步骤与Native一致。

在这里插入图片描述

2. 开发步骤

JSAPI支付必须要在商户平台配置支付目录,所谓支付目录就是指:前端调起微信支付的当前URL地址。 设置如下:

在这里插入图片描述

3. 开始开发

调起支付,需要配置jsconfig,我用的是vue, 以下我将介绍vue的方式发起支付。
首先前端配置如下:

mounted() {this.axios.get("/kuais/essleyWeb/essley/wx/getWxConfigParams",{params: {webUrl: this.webUrl}}).then(res => {var data = res.data.data;console.log(data)wx.config({debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: data.appId, // 必填,公众号的唯一标识timestamp: data.timestamp, // 必填,生成签名的时间戳nonceStr: data.nonceStr, // 必填,生成签名的随机串signature: data.signature, // 必填,签名,见附录1jsApiList: ["chooseWXPay"]});wx.ready(function() {wx.checkJsApi({jsApiList: ["chooseWXPay"],success: function(res) {console.log("seccess");console.log(res);},fail: function(res) {console.log("fail");console.log(res);}});});});},

我们需要在后端,获取token,然后获取jsapi_ticket。 得到初始化参数之后,返回给前端,配置jsconfig。 可以通过微信开发者工具中查看是否配置成功,(有时候你看JS-SDK中提示签名错误,其实也是可以调起微信支付的)。 代码如下:

/*** 签名算法签名生成规则如下:参与签名的字段包括noncestr(随机字符串),有效的jsapi_ticket, timestamp(时间戳),url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。*/public Map<String,String> wxConfigParams(String webUrl){String jsapi_ticket = jsapiTicketFromRedis();String noncestr = WXPayUtil.generateNonceStr();String timestamp = WXPayUtil.getCurrentTimestamp()+"";String url = webUrl;String[] arr = new String[]{jsapi_ticket,noncestr, timestamp,url};String string1 = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;log.info("拼接好的string1: "+string1);String sha1Hex = DigestUtils.sha1Hex(string1.getBytes());log.info("jsapi_ticket签名:  "+sha1Hex);Map<String,String> resMap = new HashMap<>();resMap.put("appId", WebAppID);resMap.put("timestamp", timestamp);resMap.put("nonceStr", noncestr);resMap.put("signature", sha1Hex);return resMap;}

jsconfig配置成功之后,接下来就可以调用微信统一下单API了, 与Native扫码支付不同的是,它需要返回如下参数:

appId: data.appId,
timestamp: data.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: data.nonceStr, // 支付签名随机串,不长于 32
package: data.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: data.paySign, // 支付签名

如果后端返回的参数没有问题,这时候,就可以发起微信支付了。输入密码,就可以支付完成。


http://chatgpt.dhexx.cn/article/XSWSAr7A.shtml

相关文章

微信JSAPI支付对接流程及支付接口设计

文章目录 前言一、JSAPI支付场景及逻辑二、开发步骤1.设置支付目录2.设置授权域名3.业务流程 三、代码设计1. 支付页面2. Controller3. JS调起支付4. 工具类 前言 关于微信支付很早之前做过一次&#xff0c;近期项目再次使用就简单的记录一下。微信公众账号开通及微信支付认证…

【微信支付】jsApi支付 V3版本(附代码)

1、接入前的准备 官方文档地址 jsapi下单官方文档地址&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml jsapi调起支付官方文档地址&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml jsapi支付通知回调文档地址…

JAVA版微信支付V3—JSAPI支付

本人用的开发框架是:struts2&#xff08;用了struts2的0配置&#xff0c;对于struts的0配置不熟悉的可以看看这个博客了解下 http://www.cnblogs.com/fpjason/archive/2009/08/01/1536671.html&#xff09; 本人做的是微信V3版本的微信支付&#xff0c;也是目前最新的微信支付…

PHP微信支付JSAPI网页支付Native原生支付

微信JsApi网页支付链接&#xff08;微信中打开&#xff09;&#xff1a;微信安全支付 微信Native原生支付产生二维码链接&#xff1a;微信扫描支付样例 资源下载路径&#xff1a;PHP实现微信支付&#xff0c;支付宝支付对接_支付对接如何设置-PHP文档类资源-CSDN下载 使用PHP…

PHP实现微信支付(jsapi支付)流程

最近接触到一个项目&#xff0c;涉及到微信支付&#xff0c;搞微信开发这么久以来&#xff0c;还没搞过支付&#xff0c;之前也就搞过公众号发红包&#xff0c;感谢前辈们的探索&#xff0c;我看了他们的博文&#xff0c;让我少走了很多弯路。 前期准备&#xff1a; 1.微信认证…

【微信公众号】微信 jsapi 支付大概流程

文章目录 一、个人对微信 jsapi 支付的介绍二、微信支付需要的数据库表&#xff08;例子&#xff09;1. 订单表2. 支付信息表3. 退款信息表 三、微信支付必须的参数&#xff08;配置文件&#xff09;四、WxPayConfig.java1. MAVEN 依赖2. Java 代码&#xff08;商户私钥、签名验…

微信小程序支付V2版之JSAPI支付

文章目录 一、微信支付环境搭建1 企业微信小程序的开通2. 企业商户号的开通3 小程序号与商户号关联 二、微信小程序的支付流程1 JSAPI支付流程2 微信小程序获取openid3 微信小程序下单4 后台服务程序对订单的处理5 微信小程序发起支付6 支付结果的通知 三、微信支付API的使用1 …

Java实现微信支付(微信公众号JSAPI支付)

Java实现微信支付&#xff08;微信公众号JSAPI支付&#xff09; 第一步 开发环境准备 在接入微信支付之前&#xff0c;需要现在微信支付商户平台入驻&#xff0c;成为商家&#xff0c;才能继续后续的开发。 微信支付商户平台网址&#xff1a;https://pay.weixin.qq.com不过&…

微信 JSAPI 支付流程

微信支付分为5种&#xff1a; Jsapi支付&#xff0c;二维码支付&#xff0c;H5支付&#xff0c;小程序支付&#xff0c;App支付 Jsapi支付流程&#xff1a; (1) 通过oauth协议获取open_id a.第一步&#xff1a;用户同意授权&#xff0c;获取code 在确保微信公众账号拥有授权…

微信小程序微信支付《JSAPI支付》APIV3详细教程

文章目录 前提整体介绍我的maven依赖1、整体流程2、openid 的获取3、统一下单Controller&#xff08;预支付订单&#xff09;4、配置类和配置文件5、工具类6、前端接收到必要的参数&#xff0c;进行调起支付页面7、微信支付通知&#xff0c;notify_url的回调Controller8、前端小…

java对接微信支付:JSAPI支付(微信公众号支付)

本文是【微信JSAPI支付】文章&#xff0c;主要讲解商户对接微信支付&#xff0c;简洁版测试 文章目录 一、JSAPI支付接入前准备 二、代码片段 1.引入Maven依赖 2.后端业务请求接口 3.前端调起支付请求方法 总结 一、JSAPI支付接入前准备 1、JSAPI支付首先需要注册、认证一个公…

微信 JSAPI 支付流程

微信支付&#xff0c;开发文档地址&#xff1a; https://pay.weixin.qq.com/wiki/doc/api/index.html JSAPI支付文档地址&#xff1a; https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter9_2 微信支付分为5种&#xff1a; Jsapi支付&#xff0c;二维码支付&#xf…

微信公众号支付(JSAPI)

六年代码两茫茫&#xff0c;不思量&#xff0c;自难忘 6年资深前端主管一枚&#xff0c;只分享技术干货&#xff0c;项目实战分享 关注博主不迷路~ 文章目录 JSAPI支付简介应用场景支付的对接准备工作开发流程必填参数预支付统一下单公众号授权获取用户信息微信支付&#xff08…

微信支付之JSAPI支付

首先看一下&#xff0c;微信支付关于jsapi的官方文档&#xff0c;相关接口&#xff0c;一共有下单&#xff0c;查询订单&#xff0c;关闭订单&#xff0c;调起jsapi支付&#xff0c;支付结果通知&#xff0c;申请退款&#xff0c;查询单笔退款&#xff0c;退款结果通知&#xf…

微信支付JSAPI

一、什么是JSAPI支付 JSAPI支付是指商户通过调用微信支付提供的JSAPI接口&#xff0c;在支付场景中调起微信支付模块完成收款。 应用场景有&#xff1a; 线下场所&#xff1a;调用接口生成二维码&#xff0c;用户扫描二维码后在微信浏览器中打开页面后完成支付 公众号场景&…

微信支付之JSAPI支付开发流程

JSAPI支付 前言准备开发1.流程说明2.下单&#xff08;预支付&#xff09;3.前端调起支付4.支付结果异步通知5.退款申请6.退款结果异步通知 结语 前言 最近项目涉及到微信支付的功能&#xff0c;在这里简单分享下整体的开发流程,这里要介绍的是JSAPI支付。 JSAPI网页支付&#…

FME是一个好东东

FME产品分为三个层次&#xff1a; 一、入门级 1、特点&#xff1a;支持常见的GIS软件的数据交换&#xff0c;如 MapInfo TAB, DGN, DXF, DWG, SDTS, SHP, and TIGER&#xff1b;可以运行大部分函数&#xff08;Funtion和Factory&#xff09;&#xff1b;不支持由Plug-in开发的第…

黑马程序员Maven学习笔记

前言 这里是黑马程序员Maven学习笔记分享&#xff0c;这是视频链接。 我还有其它前端内容的笔记&#xff0c;有需要可以查看。 文章目录 前言基础Maven简介Maven是什么Maven的作用 Maven的下载Maven的基础概念仓库坐标本地仓库配置远程仓库的配置 第一个Maven项目Maven的项目…

MAEKDOWN

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

谷粒商城前端笔记

前端笔记 JavaScript ES6 ECMAScript6.0&#xff08;以下简称ES6&#xff0c;ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本&#xff09;&#xff0c;是JavaScript语言的下一代标准&#xff0c;2015年6月正式发布&#xff0c;从ES6开始的版本号采用年号&#xff0c;如…