申请微信支付

一、微信支付首先需要先去申请资格,申请条件及步骤如下:

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. 微信支付申请资料及费率

    微信支付申请资料及费率 一.申请资料 1.(个体工商户)接入申请资料 2.(企业)接入申请资料 3.(民办非企业.社会团体.基金会等其他组织)接入申请资料 4.(党团组织)接入申请资料 5.(政府及事 ...

  2. 微信退款返回58 linux,小程序微信支付申请退款返回cUrl错误,错误码:58

    2019-04-03 15:15:29 如何看待微信公开课小程序热门讨论「小程序微信支付申请退款返回cUrl错误,错误码:58」 摘要:小程序微信支付申请退款返回cUrl错误,错误码:58 展开:调用 ...

  3. 前端--微信小程序(1) 小程序注册与微信支付申请

    1:注册微信小程序 (1)没有注册过的邮箱 (2)营业执照(没有的话,小程序会有很多限制) (3)对公账户 或者 法人个人银行账户 (4)运营者身份证.手机号 (5)运营者个人运营的微信号 (6)企业 ...

  4. 小程序微信支付申请与配置完整版操作流程

    小程序微信支付申请与配置完整版操作流程 一. 申请小程序微信支付 微信支付申请分为两种情况: 情况一,申请新的微信支付商户号: 情况二,绑定已有微信支付商户号 注意:申请微信支付的小程序账户需要进行微 ...

  5. 微信支付-“申请退款”接口遇到curl出错,错误码:58解决方案

    微信支付后 退款,接口遇到curl出错,错误码:58 这个问题基本上是证书没对应上(微信支付不需要申请证书,退款要用到证书),证书要去微信商户号后台(账户中心-API安全-申请证书)下载,已经下载过忘 ...

  6. 微信支付-----申请退款和退款通知接收

    这一篇博客跟着我上一篇博客的思路和流程继续,如果想看上一篇博客的童鞋,可以点击微信支付----统一下单接口对接进行阅读,本篇博客将介绍申请退款和退款通知两个接口的开发. 一,申请退款接口  注意点: ...

  7. 微信支付申请测试号 -- 填写接口配置信息提示配置失败

    背景 对接微信支付开发时需要申请商户号和公众号,对于个人开发来说门槛相对偏高,我们可以在微信官方申请测试号.微信官方申请链接 申请方式 主要就是第二步在填写接口配置信息的时候,经常会提示配置失败,具体 ...

  8. 微信支付退款 java_Java微信支付申请退款

    一.申请退款内容 1.证书使用 申请退款是需要证书的. 证书名字:证书使用中,说明了Java使用的是第一种:pkcs12格式的apiclient_cert.p12. 下载证书:微信商户平台--> ...

  9. 基本功能之-微信支付申请

    微信支付有的经营类目是要收取手续费的 申请流程 1.基本信息 1.1联系信息 1.2经营信息 1.3商户信息 1.4结算信息 2.账户验证 当第一步完成时,微信会给你的邮箱发送一个账号和密码,你可以在 ...

  10. 解决微信支付申请扫描提示“操作超时,请重新扫码确认问题”

    文章目录 问题 原因 解决 问题 在申请微信支付账号的时候,按照微信网站的提示"操作超时,请重新扫码确认" 原因 因为浏览器的原因,浏览器不兼容,醉了,这个年代了还有这个兼容的问题 ...

最新文章

  1. HttpServletResponse对象(一)
  2. php错误提示:date_default_timezone_get
  3. 确认访问用户身份的认证
  4. 中断/gic代码导读:在哪里配置安全中断的?
  5. qc linux mysql 安装教程_linux下安装mysql
  6. product text的language dropdown list里 没有对应语言的问题
  7. Qt 字符串QString arg()用法总结
  8. Qt使用udp的Broadcast实现广播图片
  9. rem,em,px的区别
  10. sql 会话_在特定会话中禁用SQL Server中的触发器
  11. http 和 https 区别
  12. easyUi后台,模板实现前台简易版网上书店功能实现
  13. 《内网安全攻防:渗透测试实战指南》读书笔记(三):隐藏通信隧道技术
  14. Proteus —— 电路仿真软件
  15. cad插入块_CAD软件中图块无法分解怎么办?
  16. springboot+pagehelper踩坑,PageHelper.startPage没有生效问题
  17. APS Interview - Operating System
  18. Airbnb NYC2019分析实战
  19. Windows系统 电脑系统重装详细图文教程(绝对够详细,看这一篇就够)
  20. 计算机类创新论文题目,计算机类学论文选题 计算机类论文标题怎样定

热门文章

  1. NHibernate 联合查询,解决方法-通过自动转换成DataTable
  2. 如何用vm虚拟机当服务器,vm虚拟机如何做云服务器
  3. CTFWeb——Bugku秋名山老司机 详细题解
  4. springboot jedis配置以及集群(第三篇) ubuntu16实现redis集群
  5. 天使轮,种子,A轮,B轮,C轮,Pre-IPO
  6. phalcon mysql_phalcon mysql_phalcon数据库操作
  7. DevOps系列之 —— 持续规划与设计(三)敏捷项目管理的方法【Kanban 与 Scrum】
  8. mysql计算月初日期_mysql 获取上月、本月月初月末
  9. Hyperledger Fabric系统架构
  10. CentOS8下载及设置安装源(最新设置)