微信支付申请及简单使用
申请微信支付
一、微信支付首先需要先去申请资格,申请条件及步骤如下:
1、注册公众号(服务号-企业才能注册),可以根据营业执照类型选择:个体商户 | 企业/公司 | 政府 | 媒体 | 其他类型。
2、认证公众号(认证费:300元/年)
3、提交资料申请微信支付(审核时间为1-5个工作日内)。
4、开户成功,登录商户平台进行验证。
资料审核通过后,请登录联系人邮箱查收商户号和密码,并登录商户平台填写财付通备付金打的小额资金数额,完成账户验证。
二、获取公众号/商户信息支付信息
1、微信公众账号或开放平台APP的唯一标识 - appid
2、财付通平台的商户账号 - mch_id
3、财付通平台的商户密钥 - partnerkey
4、启用Native
5、根据API进行开发:https://pay.weixin.qq.com/wiki/doc/api/index.html
微信支付基本使用
一、创建二维码
后端需要根据订单id和支付金额来返回一个Map集合给前端,前端通过qrcode创建一个支付二维码。
先在微信支付相关操作的类里面注入商户信息(商户信息在properties配置文件中)
// 微信公众账号或开放平台APP的唯一标识
@Value("${appid}")
private String appid;
// 财付通平台的商户账号
@Value("${partner}")
private String partner;
// 财付通平台的商户秘钥
@Value("${partnerkey}")
private String partnerkey;
// 回调地址
@Value("${notifyurl}")
private String notifyurl;
1、后端代码
①Controller层代码 - 根据自己的业务来做
/*** 获取当前登录用户名,* 根据用户名获取redis中的支付日志对象,* 根据支付日志对象中的支付单号和总金额* 调用微信统一下单接口, 生成支付链接返回* @return*/
@RequestMapping("/createNative")
public Map createNative() {//1. 获取当前登录用户的用户名 - SpringSecurityString userName = SecurityContextHolder.getContext().getAuthentication().getName();//2. 根据用户名获取支付日志对象 - 根据自己业务调用PayLog payLog = orderService.getPayLogByUserName(userName);if (payLog != null) {//3. 调用统一下单接口生成支付链接 - 订单号、价格(单位:分)Map map = payService.createNative(payLog.getOutTradeNo(), "1");return map;}return new HashMap();
}
②Service层代码 - 根据自己的业务来做,传一些其他附加参数
*** 支付创建二维码* @param outTradeNo 订单号* @param totalFee 支付金额* @return 前端需要的相关信息*/
public Map createNative(String outTradeNo, String totalFee){// 创建参数MapMap<String, String> payParam = new HashMap<>();payParam.put("appid",appid); // 微信公众账号或开放平台APP的唯一标识payParam.put("mch_id",partner); // 财付通平台的商户账号payParam.put("body","可口可乐250ML"); // 商品描述payParam.put("nonce_str",WXPayUtil.generateNonceStr()); // 随机字符串payParam.put("out_trade_no",outTradeNo); // 订单号payParam.put("total_fee",totalFee); // 支付金额(单位:分)payParam.put("spbill_create_ip","127.0.0.1"); // APP和网页支付提交用户端ippayParam.put("notify_url",notifyurl); // 回调地址payParam.put("trade_type","NATIVE"); // 交易类型 - 二维码支付try{// 生成要发送的xml,调用微信SDK的API接口将封装的Map数据转换成Xml格式字符串String xmlParam = WXPayUtil.generateSignedXml(payParam, partnerkey); // 参数2:财付通平台的商户密钥// 使用HttpClient发送请求 - 参数为支付请求地址HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");client.setHttps(true);client.setXmlParam(xmlParam);client.post();// 获得结果 - xml字符串String result = client.getContent();// 调用微信SDK的API接口将Xml数据转换成Map对象Map<String, String> resultMap = WXPayUtil.xmlToMap(result);// 创建返回给前端去创建二维码的结果MapMap<String, String> returnMap = new HashMap<>();returnMap.put("code_url",resultMap.get("code_url")); // 支付地址returnMap.put("total_fee",totalFee); // 总金额returnMap.put("out_trade_no",outTradeNo); // 订单号}catch(Excption e){e.printStackTrace();return new HashMap<>();}
}
2、前端代码(Vue) - 请求创建二维码
/*** 创建支付二维码*/
createNative: function () {let _this = this;axios.get('/pay/createNative.do').then(function (response) {// 显示金额_this.money = (response.data.total_fee / 100).toFixed(2);// 显示订单号_this.out_trade_no = response.data.out_trade_no;// 使用QRcode创建二维码let qrcode = new QRCode(document.getElementById("qrcode"), {width: 250,height: 250});qrcode.makeCode(response.data.code_url);// 查询支付结果 - 这里采用的是长轮询方式查询支付结果_this.queryPayStatus(); }).catch(function (reason) {console.log(reason);})
},
二、查询订单支付结果
1、后端代码
①Controller层代码 - 根据自己的业务来做
/*** 调用查询订单接口, 查询是否支付成功* @param out_trade_no 订单号* @return*/
@RequestMapping("/queryPayStatus")
public MessageResult queryPayStatus(String out_trade_no) {String userName = SecurityContextHolder.getContext().getAuthentication().getName();MessageResult MessageResult = null;int flag = 1;// 长轮询的方式查询结果 - 建议使用WebSocket或通过消息中间件RabbitMQ Web STOMP来解决while(true) {// 1. 判断支付单号等于nullif (out_trade_no == null) {MessageResult = new MessageResult(false, "二维码超时");break;}// 2. 调用查询接口查询支付是否成功Map map = payService.queryPayStatus(out_trade_no);if ("SUCCESS".equals(map.get("trade_state"))) {MessageResult = new MessageResult(true, "支付成功!");//3. 如果支付成功, 支付日志表和订单表的支付状态改为已支付, redis的支付日志对象删除orderService.updatePayStatus(userName);break;}try {Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}// 如果5分钟没有支付则支付超时if (flag > 100) {MessageResult = new MessageResult(false, "二维码超时");break;}flag++;}return MessageResult;
}
②Service层代码 - 根据自己的业务来做
/*** 查询是否已经支付* @param out_trade_no 订单号* @return*/
@Override
public Map queryPayStatus(String out_trade_no) {Map param = new HashMap();param.put("appid", appid); // 微信公众账号或开放平台APP的唯一标识param.put("mch_id", partner); // 财付通平台的商户账号param.put("out_trade_no", out_trade_no); // 订单号param.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串String url = "https://api.mch.weixin.qq.com/pay/orderquery"; // 查询urltry {// 生成要发送的xml,调用微信SDK的API接口将封装的Map数据转换成Xml格式字符串String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey); // 参数2:财付通平台的商户密钥// 使用HttpClient发送请求 - 参数为支付请求地址HttpClient client = new HttpClient(url);client.setHttps(true);client.setXmlParam(xmlParam);client.post();// 获得结果 - xml字符串String result = client.getContent();// 调用微信SDK的API接口将Xml数据转换成Map对象Map<String, String> map = WXPayUtil.xmlToMap(result);return map;} catch (Exception e) {e.printStackTrace();return null;}
}
2、前端代码(Vue) - 查询支付结果
/*** 查询支付结果*/
queryPayStatus: function () {let _this = this;axios.get("/pay/queryPayStatus.do?out_trade_no=" + this.out_trade_no).then(function (response) {if (response.data.success) { // 跳转支付成功页面location.href = "paysuccess.html?money=" + _this.money;} else {if (response.data.message === '二维码超时') {// 重新生成二维码this.createNative();} else { // 跳转支付失败页面location.href = "payfail.html"}}}).catch(function (reason) {console.log(reason);});
}
三、关闭订单操作
这里只提供后端服务层代码,因为我的业务里因为之前没考虑周全,是没有做这个功能的。但是这个功能在真正的项目中是必须要有的,假如某个人下单买了一个东西,他一直不支付怎么办?通常业务里都会有30分钟不支付,关闭订单的操作(含关闭微信支付)。如果真的要做的话,可以通过MQ延时队列来做。
/***** 关闭订单操作* @param out_trade_no 订单号* @return*/
public Map closePay(String out_trade_no) {Map param=new HashMap();param.put("appid", appid); // 微信公众账号或开放平台APP的唯一标识param.put("mch_id", partner); // 财付通平台的商户账号param.put("out_trade_no", out_trade_no); // 订单号param.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串// 关闭微信支付UrlString url="https://api.mch.weixin.qq.com/pay/closeorder";try {// 生成要发送的xml,调用微信SDK的API接口将封装的Map数据转换成Xml格式字符串String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);HttpClient client=new HttpClient(url);client.setHttps(true);client.setXmlParam(xmlParam);client.post();// 获得结果 - xml字符串String result = client.getContent();// 调用微信SDK的API接口将Xml数据转换成Map对象Map<String, String> map = WXPayUtil.xmlToMap(result);return map;} catch (Exception e) {e.printStackTrace();return null;}
}
HttpClient源码
/*** http请求客户端* @author Administrator*/
public class HttpClient {/** 请求地址 */private String url;/** 参数 */private Map<String, String> param;private int statusCode;private String content;private String xmlParam;private boolean isHttps;public boolean isHttps() {return isHttps;}public void setHttps(boolean isHttps) {this.isHttps = isHttps;}public String getXmlParam() {return xmlParam;}public void setXmlParam(String xmlParam) {this.xmlParam = xmlParam;}public HttpClient(String url, Map<String, String> param) {this.url = url;this.param = param;}public HttpClient(String url) {this.url = url;}public void setParameter(Map<String, String> map) {param = map;}public void addParameter(String key, String value) {if (param == null)param = new HashMap<String, String>();param.put(key, value);}public void post() throws ClientProtocolException, IOException {HttpPost http = new HttpPost(url);setEntity(http);execute(http);}public void put() throws ClientProtocolException, IOException {HttpPut http = new HttpPut(url);setEntity(http);execute(http);}public void get() throws ClientProtocolException, IOException {if (param != null) {StringBuilder url = new StringBuilder(this.url);boolean isFirst = true;for (String key : param.keySet()) {if (isFirst)url.append("?");elseurl.append("&");url.append(key).append("=").append(param.get(key));}this.url = url.toString();}HttpGet http = new HttpGet(url);execute(http);}/*** set http post,put param*/private void setEntity(HttpEntityEnclosingRequestBase http) {if (param != null) {List<NameValuePair> nvps = new LinkedList<NameValuePair>();for (String key : param.keySet())nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数}if (xmlParam != null) {http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));}}private void execute(HttpUriRequest http) throws ClientProtocolException,IOException {CloseableHttpClient httpClient = null;try {if (isHttps) {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有public boolean isTrusted(X509Certificate[] chain,String authType)throws CertificateException {return true;}}).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();} else {httpClient = HttpClients.createDefault();}CloseableHttpResponse response = httpClient.execute(http);try {if (response != null) {if (response.getStatusLine() != null)statusCode = response.getStatusLine().getStatusCode();HttpEntity entity = response.getEntity();// 响应内容content = EntityUtils.toString(entity, Consts.UTF_8);}} finally {response.close();}} catch (Exception e) {e.printStackTrace();} finally {httpClient.close();}}public int getStatusCode() {return statusCode;}public String getContent() throws ParseException, IOException {return content;}}
经验记录:
1、二维码支付的时候查询是否支付成功的问题:
①Ajax短轮询,通过定时器异步刷新查询是否支付成功。
缺点:这种方式实时效果较差,而且对服务端的压力也较大。
②长轮询,后端循环查询是否支付成功。
缺点:长轮询服务端会长时间地占用资源,如果消息频繁发送的话会给服务端带来较大的压力。
③WebSocket 双向通信
RabbitMQ可以通过RabbitMQ Web STOMP 插件来做。
2、订单超时关闭订单的问题:
下单的时候发送MQ延迟消息,30分钟未支付,则消费这个延迟消息做一些未支付的业务处理。
3、微信支付回调地址需要外网能访问,如果是本地的话,可以通过内网穿透去做。
微信支付申请及简单使用相关推荐
- 微信支付申请资料及费率
微信支付申请资料及费率 一.申请资料 1.(个体工商户)接入申请资料 2.(企业)接入申请资料 3.(民办非企业.社会团体.基金会等其他组织)接入申请资料 4.(党团组织)接入申请资料 5.(政府及事 ...
- 微信退款返回58 linux,小程序微信支付申请退款返回cUrl错误,错误码:58
2019-04-03 15:15:29 如何看待微信公开课小程序热门讨论「小程序微信支付申请退款返回cUrl错误,错误码:58」 摘要:小程序微信支付申请退款返回cUrl错误,错误码:58 展开:调用 ...
- 前端--微信小程序(1) 小程序注册与微信支付申请
1:注册微信小程序 (1)没有注册过的邮箱 (2)营业执照(没有的话,小程序会有很多限制) (3)对公账户 或者 法人个人银行账户 (4)运营者身份证.手机号 (5)运营者个人运营的微信号 (6)企业 ...
- 小程序微信支付申请与配置完整版操作流程
小程序微信支付申请与配置完整版操作流程 一. 申请小程序微信支付 微信支付申请分为两种情况: 情况一,申请新的微信支付商户号: 情况二,绑定已有微信支付商户号 注意:申请微信支付的小程序账户需要进行微 ...
- 微信支付-“申请退款”接口遇到curl出错,错误码:58解决方案
微信支付后 退款,接口遇到curl出错,错误码:58 这个问题基本上是证书没对应上(微信支付不需要申请证书,退款要用到证书),证书要去微信商户号后台(账户中心-API安全-申请证书)下载,已经下载过忘 ...
- 微信支付-----申请退款和退款通知接收
这一篇博客跟着我上一篇博客的思路和流程继续,如果想看上一篇博客的童鞋,可以点击微信支付----统一下单接口对接进行阅读,本篇博客将介绍申请退款和退款通知两个接口的开发. 一,申请退款接口 注意点: ...
- 微信支付申请测试号 -- 填写接口配置信息提示配置失败
背景 对接微信支付开发时需要申请商户号和公众号,对于个人开发来说门槛相对偏高,我们可以在微信官方申请测试号.微信官方申请链接 申请方式 主要就是第二步在填写接口配置信息的时候,经常会提示配置失败,具体 ...
- 微信支付退款 java_Java微信支付申请退款
一.申请退款内容 1.证书使用 申请退款是需要证书的. 证书名字:证书使用中,说明了Java使用的是第一种:pkcs12格式的apiclient_cert.p12. 下载证书:微信商户平台--> ...
- 基本功能之-微信支付申请
微信支付有的经营类目是要收取手续费的 申请流程 1.基本信息 1.1联系信息 1.2经营信息 1.3商户信息 1.4结算信息 2.账户验证 当第一步完成时,微信会给你的邮箱发送一个账号和密码,你可以在 ...
- 解决微信支付申请扫描提示“操作超时,请重新扫码确认问题”
文章目录 问题 原因 解决 问题 在申请微信支付账号的时候,按照微信网站的提示"操作超时,请重新扫码确认" 原因 因为浏览器的原因,浏览器不兼容,醉了,这个年代了还有这个兼容的问题 ...
最新文章
- HttpServletResponse对象(一)
- php错误提示:date_default_timezone_get
- 确认访问用户身份的认证
- 中断/gic代码导读:在哪里配置安全中断的?
- qc linux mysql 安装教程_linux下安装mysql
- product text的language dropdown list里 没有对应语言的问题
- Qt 字符串QString arg()用法总结
- Qt使用udp的Broadcast实现广播图片
- rem,em,px的区别
- sql 会话_在特定会话中禁用SQL Server中的触发器
- http 和 https 区别
- easyUi后台,模板实现前台简易版网上书店功能实现
- 《内网安全攻防:渗透测试实战指南》读书笔记(三):隐藏通信隧道技术
- Proteus —— 电路仿真软件
- cad插入块_CAD软件中图块无法分解怎么办?
- springboot+pagehelper踩坑,PageHelper.startPage没有生效问题
- APS Interview - Operating System
- Airbnb NYC2019分析实战
- Windows系统 电脑系统重装详细图文教程(绝对够详细,看这一篇就够)
- 计算机类创新论文题目,计算机类学论文选题 计算机类论文标题怎样定
热门文章
- NHibernate 联合查询,解决方法-通过自动转换成DataTable
- 如何用vm虚拟机当服务器,vm虚拟机如何做云服务器
- CTFWeb——Bugku秋名山老司机 详细题解
- springboot jedis配置以及集群(第三篇) ubuntu16实现redis集群
- 天使轮,种子,A轮,B轮,C轮,Pre-IPO
- phalcon mysql_phalcon mysql_phalcon数据库操作
- DevOps系列之 —— 持续规划与设计(三)敏捷项目管理的方法【Kanban 与 Scrum】
- mysql计算月初日期_mysql 获取上月、本月月初月末
- Hyperledger Fabric系统架构
- CentOS8下载及设置安装源(最新设置)