普通商户模式微信支付之APP支付统一下单:

前言:

最近项目开发到微信支付的模块,经过一周的不懈努力,虽然微信支付流程跑通了,但当时的那些坑是真的烦,为了避免自己以后犯同样的错误,当然还有各位新接触微信支付的同仁们闭坑,所以自我觉得还是有必要写个博客记录记录,顺便提高一下自己的总结能力以及表达能力。

为了更加详细的记录微信支付的整个流程,我还是从微信支付的开发文档说起:
微信支付开发文档地址(我这里使用的微信支付V2版本开发文档):https://pay.weixin.qq.com/wiki/doc/api/index.html

打开链接会进入如下图的页面:

可以看到页面的上部分分别有 普通商户版 服务商版 和 银行服务商版 三个版本的文档 分类

还是要说一下区别:(自我理解的)

普通商户版:就是在微信商户平台使用企业公司资质等信息申请开通的微信普通商户,开通完成后会微信会分配一个商户号(mch_id)商户密钥(mch_secret),是在调用支付接口时使用的重要参数。

服务商版:大致和普通商户的申请规则一样,只不过可能会多一些申请资料之类的,经过微信审核通过,则成为微信支付服务商,服务商下面可以邀请多个子商户进入,服务商相当于就是一个管理员可以管理这些子商户,我们把这些子商户称为特约商户,同样微信支付也会给服务商商户分配 服务商商户号和服务商商户密钥 用于 提供其相关支付能力。

银行服务商版:暂时没有接触到,但大致原理都一样,需要银行资质申请,但其中支付产品较少。

在这里我先说一说普通商户版文档里面的APP支付这一支付产品

点击进入看到如下页面:侧边栏的文档说明,术语,支付账户,接口规则,运营规范这些等等都可以自己去看,可以仔细研究研究,因为可能很多支付遇到的细节性问题里面都能找到答案。我这里就不具体一一介绍了,直接进入正题,API列表


点击进入API列表:如下图,可以看到许多微信支付提供的对外接口,如统一下单,申请退款等。具体要查看哪一个文档,点击进入就行了。

在这里要先说一下自己理解的APP支付这一支付产品的支付流程:

1、前端选择商品提交订单,跳转到支付页面选择支付方式;
2、选择微信支付后,请求java后端根据微信app支付文档写好的的统一下单接口;
3、这个统一下单的接口在请求微信那边过后会返给前端一些重要的参数,用于唤醒手机app里的微信支付;
4、在统一下单接口中我们会给微信服务器那边一个回调地址路径,用户微信服务回调我们自己系统的通知接口,用于响应微信服务订单是否支付成功;

在写代码之前要做好微信支付的一些准备:

1、java项目中的配置文件配置好微信支付需要的相关参数,如你 应用 appid,应用 appsecret,商户号 mch_id,商户密钥
mch_secret 回调地址接口路径 2、要将应用 appid 和你的商户 产生绑定关系,这个可以在微信公众平台去绑定
3、要有切实可行的运行环境,保证微信回调可以成功。
4、有些微信API接口还需要商户证书文件,需要去商户平台下载并放置到你的项目中的resources文件夹下

准备工作完成之后就可以安心写代码了,不多说了,直接上代码:

统一下单接口:

 @RequestMapping("/wxAppPay")public ResBean<Object> wxAppPay(@RequestBody ReqWxPayBean reqWxPayBean, HttpServletRequest request){// 响应数据体ResBean<Object> resBean = new ResBean<>();//根据订单号去数据库拿出对应订单的价格(如果是前端传值价格的话可能会有风险,所以后端从数据库获取订单价格,单位为分)Long price = orderTooler.fetchPrice(reqWxPayBean.getPayOutTradeNo(), reqWxPayBean.getSessionId());//添加app唤醒支付所需支付信息的参数LinkedHashMap<String, String> params = new LinkedHashMap<>();params.put("appid", appId);//如果是app支付则为应用appidparams.put("attach", reqWxPayBean.getSessionId());params.put("body", reqWxPayBean.getPayBody());params.put("mch_id", mchId);//商户的商户号params.put("nonce_str", Long.toString(System.currentTimeMillis() / 1000));// 随机字符串params.put("notify_url", couponNoticeUrl);  // 支付成功回调地址params.put("out_trade_no", reqWxPayBean.getPayOutTradeNo());   // 自己系统生成的订单号params.put("spbill_create_ip", PayUtils.getIp(request));   // ipparams.put("total_fee", String.valueOf(price));   // 订单总价,单位为分params.put("trade_type", String.valueOf(WxPayApi.TradeType.APP));  // 指定支付方式,为app支付params.put("sign", PayUtils.getSign(params, mchSecret));   // 构造签名,这里的构造签名的方式的代码在后面说明//提交到微信服务器,这里的这个HttpUtils.post(“统一下单接口路径”,“xml格式的请求参数”),是微信提供的sdk里面的方法//package com.jfinal.weixin.sdk.utils;// PaymentKit来源于(package com.jpay.ext.kit;)String post = HttpUtils.post("https://api.mch.weixin.qq.com/pay/unifiedorder", PaymentKit.toXml(params));//4、解析xml格式的数据为map集合Map<String, String> result = PaymentKit.xmlToMap(post);//5、获得返回状态码String return_code = result.get("return_code");String result_code = result.get("result_code");String err_code = result.get("err_code");String err_code_des = result.get("err_code_des");String return_msg = result.get("return_msg");if (PaymentKit.codeIsOK(return_code)) {if (PaymentKit.codeIsOK(result_code)) {// 成功之后将一下参数返回给前端人员用于唤醒app支付Map<String, String> parameterMap = new LinkedHashMap<>();//非空参数值的参数按照参数名ASCII码从小到大排序(字典序)parameterMap.put("appid",appId);//服务商申请的公众号或移动应用appid。parameterMap.put("mch_id",result.get("mch_id"));  // 商户号parameterMap.put("nonce_str",String.valueOf(result.get("nonce_str")));  // 随机字符串parameterMap.put("packageValue", "Sign=WXPay");  // 默认为Sign=WXPayparameterMap.put("prepay_id", String.valueOf(result.get("prepay_id")));// 调用微信接口之后生成的预支付id最重要的参数parameterMap.put("timestamp", Long.toString(System.currentTimeMillis() / 1000));//时间戳Map<String, String> map = new LinkedHashMap<>();map.put("appid", appId);map.put("noncestr", String.valueOf(result.get("nonce_str")));map.put("package", "Sign=WXPay");map.put("partnerid", result.get("sub_mch_id"));map.put("prepayid", String.valueOf(result.get("prepay_id")));map.put("timestamp", Long.toString(System.currentTimeMillis() / 1000));//时间戳parameterMap.put("sign",PayUtils.getSign(map,serverMchSecret));resBean.setRes_code("0000");resBean.setRes_desc(result_code);resBean.setRes_content(parameterMap);} else {resBean.setRes_code("9999");resBean.setRes_desc(err_code_des);resBean.setRes_content(err_code);}} else {resBean.setRes_code("9999");resBean.setRes_desc(return_msg);resBean.setRes_content(err_code);}return resBean;}

辅助工具方法:

// PayUtils.getSign(params, mchSecret)  params:参与签名的参数,mchSecret:商户密钥public static String getSign(Map<String, String> params, String paternerKey){return MD5Utils.MD5Encode(createSign(params, false) + "&key=" + paternerKey,"utf-8").toUpperCase();}//MD5Utils.MD5Encode(createSign(params, false) + "&key=" + paternerKey,"utf-8")  md5加密
public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}

这里仅仅只是微信支付里面普通商户模式的app统一下单一个模块的记录,后面还会继续更新其他微信支付相关的采坑记录。

微信支付采坑记录(java后端 一:微信支付调用从哪一步开始)相关推荐

  1. iOS 微信SDK1.8.6后需要UniversalLink解决方案及采坑记录

    项目最初因审核原因,一直使用iOS原生分享, 最近因项目需求要求, 接入微信分享, 以为和原来的没有区别, 但是接入时才发现改动的地方还是挺多的, 主要是需要配置UniversalLink和提包时的一 ...

  2. Ubuntu18安装微信(deepin-wine版本)完整过程以及采坑记录

    Ubuntu18安装微信(deepin-wine版本)完整过程以及采坑记录(亲测运行) git clone https://gitee.com/wszqkzqk/deepin-wine-for-ubu ...

  3. php给微信公众号接入聊天机器人程序+采坑记录

    php给微信公众号接入聊天机器人程序 今天逛了下我的公众号,突然心血来潮,想添加个自动聊天功能,于是-动手-!! 主要用到的api: 图灵机器人api 青云客智能聊天机器人API 茉莉机器人API 至 ...

  4. 微信签名验证踩坑记录1

    @ 微信签名验证踩坑记录1 H5页面打开小程序的签名验证算法,我碰到个问题 有点奇葩,不过也算是自己吸取个教训. 在H5页面打开小程序需要调用jssdk签名.这里有个URL是前端传过来的参数,这时候要 ...

  5. 使用html2canvas,将页面转换成图片的采坑记录(Web/Taro h5)

    使用html2canvas将页面转换成图片的采坑记录 "html2canvas": "^1.4.1","@tarojs/taro": &qu ...

  6. mysql 触发器采坑记录(mysql 触发器采坑记录 由于不了解mysql创建触发器要记录创建者IP,导致更改创建者IP后,触发器不可执行。 当创建触发器(视图、存储过程、函数)时,如果没有)

    mysql 触发器采坑记录(语序有点凌乱,回头再整理) 由于不了解mysql创建触发器要记录创建者IP,导致更改创建者IP后,触发器不可执行. 当创建触发器(视图.存储过程.函数)时,如果没有指定创建 ...

  7. H5拍照、预览、压缩、上传采坑记录

    H5拍照.预览.压缩.上传采坑记录 公司项目前段时间需要实现手机拍照上传的功能,本来以为用createObjectURL和canvas可以很轻松的实现,结果发现问题多多,特此记录下来. DEMO预览( ...

  8. mysql8.0.19.0_分享MySql8.0.19 安装采坑记录

    上篇文章给大家介绍了MySql8.0.19 安装过程,需要的朋友可以点击查看.https://www.jb51.net/article/178988.htm 1.ERROR 1820 (HY000): ...

  9. mysql8.0依赖_分享MySql8.0.19 安装采坑记录

    上篇文章给大家介绍了MySql8.0.19 安装过程,需要的朋友可以点击查看.https://www.jb51.net/article/178988.htm 1.ERROR 1820 (HY000): ...

最新文章

  1. java的异常与记录日志
  2. PAT甲级1004 Counting Leaves (30分):[C++题解]树、邻接表存储树、dfs遍历树
  3. scala逻辑运算符的一览图和代码案例
  4. linux基础-第十五单元 软件包的管理
  5. Web程序员的Mysql进阶序一之sql使用分类及基础
  6. android audio 自动播放,HTML5之audio无法自动播放的问题
  7. input文本框的readonly和disabled属性区别
  8. NHibernate,我越看越傻了.........
  9. 阿里云 maven 镜像地址
  10. 读书文摘卡 -《大秦帝国》
  11. ZOOMIT的使用方法
  12. P4094 [HEOI2016/TJOI2016]字符串 [SA + 主席树]
  13. java线程池的参数设置
  14. 最新网络监视工具列表
  15. 虚拟化技术基础知识全面了解
  16. ESXI使用记录---esxi主机通过iscsi连接存储
  17. 新概念英语 学习 阶段总结
  18. 云主机是怎么配置软件的
  19. 动力焕新配置升级,价格不变是关键 迈腾2019年型诚意上市
  20. Dojo Toolkit 创始人谈Dojo学习

热门文章

  1. 湖科大 2022 计算机网络期末复习资料
  2. 电商营收增幅155%,Lululemon卖多少条瑜伽裤才能赶超耐克市值?
  3. python生成接口文档_使用apiDoc实现python接口文档编写
  4. Android权限列表permission说明,html5向右移动代码
  5. 初中信息技术用计算机做科学实验报告,平潭综合实验区教育局关于做好2018年初中英语口语、信息技术、综合实践活动、物理、化学、生物实验技能考查工作的通知...
  6. Linux 文件下载 解压缩
  7. 作为一名Java程序员,这8个锦囊你不得不知道啊!!!!!
  8. 手机桌面提醒工具 S60V5
  9. 星露谷物语服务器没有空闲位置什么意思,星露谷物语没有按照任务去找巫师 | 手游网游页游攻略大全...
  10. Python 爬虫笔记3