首先,我先简要说明一下微信支付开发的流程

众所周知,工欲善其事,必先利其器,微信官方推出了web微信开发工具,有windows、linux、版本的,根据自己的开发环境选择合适自己的,登陆公众平台-->开发-->开发工具。

根据官网的文档说明,先在微信公众平台里点击微信支付,填写测试授权或支付授权目录,支付测试状态下,设置测试目录,测试人的微信号添加到白名单,发起支付的页面目录必须与设置的精确匹配,而且该域名必须是通过备案的,自己可以写个简单的servlet验证token,如果验证通过,说明该域名是有效的,如果没有验证通过,则说明该域名肯定有问题(排除servlet写的有问题)这一步是可选的,不是必须的,反正,我是当时测过的。

接着,添加测试白名单,填写支付申请。

最后,记得在开发-->接口权限-->网页服务-->网页账号,修改网页授权回调页面域名,授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权

好了,到这里,微信支付的配置信息暂且告一段落,下面开始微信支付开发流程

1)先进行微信网页授权,获取code,引导关注者打开如下页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect若提示“该链接无法访问”,请检查参数是否填写错误。

参数说明:

部分代码:

<pre name="code" class="java"><pre name="code" class="java">@SuppressWarnings("deprecation")public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//共账号及商户相关参数String appid = "";//String backUri = "";String backUri = "";//授权后要跳转的链接所需的参数一般有会员号,金额,订单号之类,//最好自己带上一个加密字符串将金额加上一个自定义的key用MD5签名或者自己写的签名,//比如 Sign = %3D%2F%CS% String totals = request.getParameter("totals");String orderNo=request.getParameter("orderNO");//String orderNo=appid+Sha1Util.getTimeStamp();backUri = backUri+"?orderNo="+orderNo+"&describe=test&money="+totals;//URLEncoder.encode 后可以在backUri 的url里面获取传递的所有参数backUri = URLEncoder.encode(backUri);//scope 参数视各自需求而定,这里用scope=snsapi_base 不弹出授权页面直接授权目的只获取统一支付接口的openidString url = "http://open.weixin.qq.com/connect/oauth2/authorize?" +"appid=" + appid+"&redirect_uri=" +backUri+"&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect";response.setCharacterEncoding("UTF-8");  response.sendRedirect(url);}

如果用户同意授权,页面将跳转至  redirect_uri/?code=CODE&state=STATE 。若用户禁止授权,则重定向后不会带上 code 参数,仅会带上 state 参数 redirect_uri?state=STATE

2)通过code换取openid

获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

正确时返回的JSON数据包如下:

{

"access_token":"ACCESS_TOKEN",

"expires_in":7200,

"refresh_token":"REFRESH_TOKEN",

"openid":"OPENID",

"scope":"SCOPE",

"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"

}

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}在这里我遇到了第一坑,openid拿不到,究其原因是网页授权的域名写错了。

3)调用支付接口https://api.mch.weixin.qq.com/pay/unifiedorder

在这里我遇到了第二坑,prepay_id为空,最后查出来是因为商户密钥配错了

请求参数如下:

字段名

变量名

必填

类型

示例值

描述

公众账号ID

appid

String(32)

wxd678efh567hg6787

微信分配的公众账号ID(企业号corpid即为此appId)

商户号

mch_id

String(32)

1230000109

微信支付分配的商户号

设备号

device_info

String(32)

013467007045764

终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"

随机字符串

nonce_str

String(32)

5K8264ILTKCH16CQ2502SI8ZNMTM67VS

随机字符串,不长于32位。推荐随机数生成算法

签名

sign

String(32)

C380BEC2BFD727A4B6845133519F3AD6

签名,详见签名生成算法

商品描述

body

String(128)

Ipad mini  16G  白色

商品或支付单简要描述

商品详情

detail

String(8192)

Ipad mini  16G  白色

商品名称明细列表

附加数据

attach

String(127)

深圳分店

附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据

商户订单号

out_trade_no

String(32)

20150806125346

商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号

货币类型

fee_type

String(16)

CNY

符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型

总金额

total_fee

Int

888

订单总金额,单位为分,详见支付金额

终端IP

spbill_create_ip

String(16)

123.12.12.123

APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。

交易起始时间

time_start

String(14)

20091225091010

订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则

交易结束时间

time_expire

String(14)

20091227091010

订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则

注意:最短失效时间间隔必须大于5分钟

商品标记

goods_tag

String(32)

WXG

商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠

通知地址

notify_url

String(256)

http://www.weixin.qq.com/wxpay/pay.php

接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。

交易类型

trade_type

String(16)

JSAPI

取值如下:JSAPI,NATIVE,APP,详细说明见参数规定

商品ID

product_id

String(32)

12235413214070356458058

trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。

指定支付方式

limit_pay

String(32)

no_credit

no_credit--指定不能使用信用卡支付

用户标识

openid

String(128)

oUpF8uMuAJO_M2pxb1Q9zNjWeS6o

trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。openid如何获取,可参考【获取openid】。企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid,再调用【企业号userid转openid接口】进行转换

部分代码:

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//网页授权后获取传递的参数//String userId = request.getParameter("userId");  String orderNo = request.getParameter("orderNo"); String money = request.getParameter("money");String code = request.getParameter("code");//金额转化为分为单位float sessionmoney = Float.parseFloat(money);int paymoney=(int) (sessionmoney*100);String finalmoney=String.valueOf((paymoney));//商户相关资料 String appid = "";String appsecret = "";String partner = "";// 商户号String partnerkey = "";//商户号密钥String openId ="";String URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+appsecret+"&code="+code+"&grant_type=authorization_code";JSONObject jsonObject = CommonUtil.httpsRequest(URL, "GET", null);if (null != jsonObject) {openId = jsonObject.getString("openid");System.out.println(openId);PrintWriter pw = response.getWriter(); //pw.print("openId----------->"+openId);}//获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorderString currTime = TenpayUtil.getCurrTime();//8位日期String strTime = currTime.substring(8, currTime.length());//四位随机数String strRandom = TenpayUtil.buildRandom(4) + "";//10位序列号,可以自行调整。String strReq = strTime + strRandom;//商户号String mch_id = partner;//子商户号  非必输//String sub_mch_id="";//设备号   非必输//String device_info="";//随机数 String nonce_str = strReq;//商品描述//String body = describe;//商品描述根据情况修改String body = orderNo;//附加数据//String attach = userId;//商户订单号String out_trade_no = orderNo;int intMoney = Integer.parseInt(finalmoney);//总金额以分为单位,不带小数点int total_fee = intMoney;//订单生成的机器 IPString spbill_create_ip = request.getRemoteAddr();//订 单 生 成 时 间   非必输
//              String time_start ="";//订单失效时间      非必输
//              String time_expire = "";//商品标记   非必输
//              String goods_tag = "";//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。String notify_url ="";String trade_type = "JSAPI";String openid = openId;//非必输
//              String product_id = "";SortedMap<String, String> packageParams = new TreeMap<String, String>();packageParams.put("appid", appid);  packageParams.put("mch_id", mch_id);  packageParams.put("nonce_str", nonce_str);  packageParams.put("body", body);  //packageParams.put("attach", attach);  packageParams.put("out_trade_no", out_trade_no);  //这里写的金额为1 分到时修改//packageParams.put("total_fee", "1");  packageParams.put("total_fee", finalmoney);  packageParams.put("spbill_create_ip", spbill_create_ip);  packageParams.put("notify_url", notify_url);  packageParams.put("trade_type", trade_type);  packageParams.put("openid", openid);  RequestHandler reqHandler = new RequestHandler(request, response);reqHandler.init(appid, appsecret, partnerkey);String sign = reqHandler.createSign(packageParams);String xml="<xml>"+"<appid>"+appid+"</appid>"+"<mch_id>"+mch_id+"</mch_id>"+"<nonce_str>"+nonce_str+"</nonce_str>"+"<sign>"+sign+"</sign>"+"<body><![CDATA["+body+"]]></body>"+//"<attach>"+attach+"</attach>"+"<out_trade_no>"+out_trade_no+"</out_trade_no>"+//金额,这里写的1 分到时修改//"<total_fee>"+1+"</total_fee>"+"<total_fee>"+finalmoney+"</total_fee>"+"<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+"<notify_url>"+notify_url+"</notify_url>"+"<trade_type>"+trade_type+"</trade_type>"+"<openid>"+openid+"</openid>"+"</xml>";System.out.println(xml);String allParameters = "";try {allParameters =  reqHandler.genPackage(packageParams);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";String prepay_id="";try {prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);PrintWriter pw = response.getWriter(); if(prepay_id.equals("")){request.setAttribute("ErrorMsg", "统一支付接口获取预支付订单出错");String json="{\"status\":\"error\",\"message\":\"prepay_id is null\"}";pw.print(json);//response.sendRedirect("error.jsp");return;}} catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();}SortedMap<String, String> finalpackage = new TreeMap<String, String>();String appid2 = appid;String timestamp = Sha1Util.getTimeStamp();String nonceStr2 = nonce_str;String prepay_id2 = "prepay_id="+prepay_id;String packages = prepay_id2;finalpackage.put("appId", appid2);  finalpackage.put("timeStamp", timestamp);  finalpackage.put("nonceStr", nonceStr2);  finalpackage.put("package", packages);  finalpackage.put("signType", "MD5");String finalsign = reqHandler.createSign(finalpackage);//System.out.println("pay.jsp?appid="+appid2+"&timeStamp="+timestamp+"&nonceStr="+nonceStr2+"&package="+packages+"&sign="+finalsign);response.sendRedirect("pay.jsp?appid="+appid2+"&timeStamp="+timestamp+"&nonceStr="+nonceStr2+"&package="+packages+"&sign="+finalsign+"&orderNO="+orderNo);return; }

4)前台页面掉微信支付 js 接口

示例代码如下:

unction onBridgeReady(){WeixinJSBridge.invoke('getBrandWCPayRequest', {"appId" : "",     //公众号名称,由商户传入     "timeStamp":" ",         //时间戳,自1970年以来的秒数     "nonceStr" : "", //随机串     "package" : "prepay_id=u802345jgfjsdfgsdg888",     "signType" : "MD5",         //微信签名方式:     "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 },function(res){     if(res.err_msg == "get_brand_wcpay_request:ok" ) {}     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 });
}
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)处理回调逻辑

3)步棸自己配置notify_url即为支付过后的回调地址,可以为action,静态页面等,自己可以在改回调地址里处理支付过后的业务逻辑

到这里,微信jsAPI开发流程已基本全部讲完,最后,在测试的过程中,微信支付是不允许一个订单经常改价钱的,微信支付默认以第一次提交订单的价钱为基准,以后再提交该订单如果价钱不是第一次的价钱,微信支付默认通不过(切记!我这个坑查了我一天),最后,祝大家开发顺利

JSAPI微信支付开发流程和坑相关推荐

  1. 小程序微信支付开发流程记录

    我所在公司需要开发一款商城小程序,里面需要用到微信支付,我负责里面的下单功能,从小程序端到后台的支付流程都是我自己开发的,由于我们组没有人有开发微信支付的经验,只有我有开发过JSAPI的微信支付的经验 ...

  2. 微信支付开发流程_清晰_易懂_有源码

    转自 https://blog.csdn.net/weixin_41497737/article/details/80547243 最近因为公司需求开始开始做微信支付的开发,在网上参考来了很多文章,大 ...

  3. iOS之“微信支付”开发流程

    实现微信支付的开发,iOS端里面只需要四个步骤: 向服务端请求预支付,获得prepayid以及noncestr: 把参数拼起来签名: 发起支付请求: 处理支付结果. iOS的微信SDK的接入:即为&q ...

  4. android支付宝、微信支付开发流程

    这一段时间项目需要加上微信支付和支付宝支付,经过一段时间摸索,总算能够正常进行支付使用了.想想在支付上遇到的坑,我觉得有必要进行一个记录,在后续的开发中避开支付中遇到的坑: 一.支付宝支付: ps:支 ...

  5. PHP版本微信支付开发----电脑网站扫码支付(native)(心得、总结)

    早就听说微信支付比支付宝支付的坑多,但还得得该填的填,该绕的绕, 最终我们网站的微信支付功能成功上线啦♪(^ ∇ ^*) 首先自报家门,我的PHP版本是7,微信demo用的是php_sdk_v3.0. ...

  6. 微信支付开发(只针对公众号里的h5支付JSAPI)

    微信支付后台: https://pay.weixin.qq.com 只有这里设置了,程序中才能使用这个key /*** 微信支付统一下单接口** @param userOrder 订单信息* @ret ...

  7. 微信支付开发准备工作和详细步骤

    微信支付前的准备工作 1 开发者资质认证 微信支付开发第一步就是使用公司管理者/高层帐号登录微信开放平台,进入"账号中心",进行开发者资质认证,需要填写公司资料,包括但不限于,公司 ...

  8. 微信公众平台微信支付打通流程

    //针对v3版本,jsapi支付,php 1.收到邮件后先去设置api密钥,下载api证书,多次需要手机验证码 2.到公众平台找到开发者中心-接口中找到'网页授权获取用户基本信息',点击修改,加入支付 ...

  9. 工作笔记——微信支付开发相关知识整理

    在最近的工作中,引入了微信小程序支付,在开发过程中积累和整理了一些技术知识,现将其整理如下 目录 一.概念认识 (一)术语介绍 (二)名词解释 (四)对接微信支付接口规则整理 二.微信支付开发参考 ( ...

最新文章

  1. linux ubuntu kubuntu与xubuntu等各版本差别
  2. c语言程序的多文件组织,C代码多文件的组织
  3. Linxu嵌入式汇编语言
  4. 手机端适应_不轻易透露的超强技巧!详解iVX中怎样做设备自适应
  5. Bootstrap导航栏
  6. 作者:李姣(1981-),女,博士,中国医学科学院医学信息研究所副研究员、硕士生导师。...
  7. 50行代码的MVVM,感受闭包的艺术
  8. 国内比较好的几大酷站收藏网分享
  9. redis LRU淘汰策略原理
  10. 计算机专业学ROSTCM,ROST-CM软件分词和词频统计用法体验
  11. 威纶通触摸屏上传错误_轻松学会威纶通触摸屏上传与反编译
  12. 超好用的数据迁移工具
  13. javascript 动态画心加文字
  14. C++17之std::apply与std::make_from_tuple
  15. 熊猫在线压缩图_回归图与熊猫和脾气暴躁
  16. 01_Snaker简介
  17. powerbi python词云图_用Power BI制作词云
  18. Unity 常见英文单词
  19. LibVLC —— 本地音视频例子、Qt播放例子
  20. KSO-.NETCore中实现跨域的代码以及几种跨域方式

热门文章

  1. 攻略:手把手教你如何看懂以太坊区块链浏览器(配图更清晰)
  2. 【06】Spring源码-分析篇-ApplicationContext
  3. osgEarth使用笔记4——加载矢量数据
  4. python统计中文字符_使用 Python 统计中文字符的数量
  5. starCTF2019-oob
  6. 超大容量充电宝哪个好,大容量移动充电宝哪个品牌好?
  7. Java基础 —— 编程入门
  8. Java数组,集合,列表的使用与区别
  9. oracle练习题(二)
  10. Text-CNN 文本分类