前言

1.微信小程序支付官方接口文档:[点击查看微信开放平台api开发文档]
2.遇到的坑:预支付统一下单签名结果返回[签名错误]失败,建议用官方[签名验证工具]检查签名是否存在问题.
3.遇到的坑:签名格式正确但统一下单接口依旧返回签名错误,解决方法=>去微信[商户平台]重新生成商户支付api密钥(文中提到的appKey),使用新的密钥进行调用接口。一般第一次生成的密钥是不可用的。

4.涉及的数据库表结构在最后面贴上

1.1 小程序支付说明

1.2 小程序轻量级支付模板(引用码云作者egan)引入jar包

       <dependency>
<groupId>com.egzosn</groupId>
<artifactId>pay-java-common</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.egzosn</groupId>
<artifactId>pay-java-wx</artifactId>
<version>2.12.1</version>
</dependency>

1.3 初始化微信支付配置存储类


private WxPayService wxUserPayService;
/**
* 微信支付必要信息初始化
* @param appId
*/
private void wxUserPayServiceInit(String appId) {
if (wxUserPayService == null) {
WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
wxPayConfigStorage.setMchId(mchId);//支付商户号
wxPayConfigStorage.setAppid(appId);//小程序appid
// wxPayConfigStorage.setKeyPublic("转账公钥,转账时必填");
wxPayConfigStorage.setSecretKey(appKey);// 商户支付密钥
wxPayConfigStorage.setNotifyUrl(domain + "/wx/userpaycallback");//支付结果回调接口地址,必须外网可访问的完整url地址
wxPayConfigStorage.setSignType("MD5");
wxPayConfigStorage.setInputCharset("utf-8"); // https证书设置,退款必须 方式一
/*HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
httpConfigStorage.setKeystorePath(keystorePath);//apiclient_cert.p12证书存放路径,填写绝对路径
httpConfigStorage.setStorePassword(mchId);
httpConfigStorage.setPath(true); httpConfigStorage.setMaxTotal(20);
httpConfigStorage.setDefaultMaxPerRoute(10);
wxUserPayService = new WxPayService(wxPayConfigStorage, httpConfigStorage);*/
wxUserPayService = new WxPayService(wxPayConfigStorage);
}
}

 

1.4 付款前生成微信预支付交易单,返回正确的预支付交易参数信息,供给微信小程序前端开发者调用付款API

       String title =  "开通会员";//支付下单标题
double total_fee = vipConfigInfoService.getInfo().getPrice();//实际支付金额
// 测试默认都是
// if (settingActive.equals("test")) {
// total_fee = 0.01;
// } // 添加支付记录信息,生成商户订单号,这里用支付记录id
String out_trade_no = payService.representVip(type, appId, openId, userId, total_fee, title); wxUserPayServiceInit(appId);//初始化微信支付配置存储类
PayOrder order = new PayOrder(title, type, new BigDecimal(total_fee), out_trade_no);
order.setTransactionType(WxTransactionType.JSAPI);
order.setOpenid(openId);
order.setSpbillCreateIp(spbill_create_ip);//终端ip,调用微信支付API的机器IP
order.setAddition(type);
JSONObject result = wxUserPayService.unifiedOrder(order);//微信统一下单接口,此方法在引入的jar中,直接传入必填的信息调用即可
System.out.println("请求微信支付统一下单结果:" + result.toString());
String timeStamp = System.currentTimeMillis() / 1000 + "";
JSONObject json = new JSONObject();
json.put("nonceStr", result.getString("nonce_str"));
json.put("package", "prepay_id=" + result.getString("prepay_id"));
json.put("timeStamp", timeStamp);
String stringSignTemp = "appId=" + appId + "&nonceStr=" + result.getString("nonce_str")
+ "&package=prepay_id=" + result.getString("prepay_id") + "&signType=MD5&timeStamp="
+ timeStamp;
json.put("paySign", wxUserPayService.createSign(stringSignTemp, "utf-8")); return json;//接口方法返回预支付交易信息,小程序前端获取返回参数,调用对应的付款接口

 

1.5 支付回调(付款后微信服务器后台回调支付结果信息)

/**
*
* 支付回调接口
*/
@RequestMapping("/userpaycallback")
public String wxUserPaycallback(HttpServletRequest request) {
try { Map<String, Object> params = wxUserPayService.getParameter2Map(request.getParameterMap(),
request.getInputStream());
if (null == params) {
throw new Exception("回调参数为空");
}
// 校验
if (!wxUserPayService.verify(params)) {
throw new Exception("校验失败");
}
payDone(params);//支付处理
return wxUserPayService.getPayOutMessage("SUCCESS", "成功").toMessage(); } catch (Exception e) {
e.printStackTrace();
return wxUserPayService.getPayOutMessage("FALL", "失败").toMessage();
}
} /**
* 支付结果处理
*/
private void payDone(Map<String, Object> dataMap) throws Exception {
System.out.println("支付回调:" + JSON.toJSONString(dataMap));
// {"transaction_id":"4200000109201805293331420304","nonce_str":"402880e963a9764b0163a979a16e0002","bank_type":"CFT","openid":"oXI6G5Jc4D44y2wixgxE3OPwpDVg","sign":"262978D36A3093ACBE4B55707D6EA7B2","fee_type":"CNY","mch_id":"1491307962","cash_fee":"10","out_trade_no":"14913079622018052909183048768217","appid":"wxa177427bc0e60aab","total_fee":"10","trade_type":"JSAPI","result_code":"SUCCESS","time_end":"20180529091834","is_subscribe":"N","return_code":"SUCCESS"}
String result_code = dataMap.get("result_code").toString();//支付结果code
String out_trade_no = dataMap.get("out_trade_no").toString();//商户交易订单id,此为支付记录id if (!result_code.equals("SUCCESS")) {
throw new Exception("支付回调失败:" + JSON.toJSONString(dataMap));
}
Pay pay = payService.getById(out_trade_no);//获取支付记录
if (pay == null || pay.getStatus() != 10) {//10=可用/待支付 20=支付成功 30=支付失败
throw new Exception("支付记录已经处理");
}
payService.pay(out_trade_no, result_code.equals("SUCCESS") ? 20 : 30);//根据回调结果更改支付结果状态
// 升级成会员的数据处理
if(result_code.equals("SUCCESS")) {//支付结果SUCCESS,支付成功开通会员,进行下一步操作
Document doc=new Document();
doc.put("vipStatus", 20);//状态20开通会员
doc.put("vipCreateTime", new Date());
doc.put("expireTime", StringUtil.getMonthNextOrBeforeDate(3));//设置过期时间为3个月后
userService.updateUserVip(pay.getUserId(),doc);
} }

 2.1数据库表

 支付记录表Pay

字段

名称

类型

备注

_id 唯一标识 String  
type 支付订单类型 String  
orderId 关联订单Id String  
remark 备注 String  
openId 微信用户openId String  
account 金额 double  
status 状态 int 10=可用/待支付 20=支付成功 30=支付失败
createTime 创建时间 Date  
callBackTime 回调时间 Date  
 
 
 
 
 
 
 
 
 
 
 
 
 
 

3.1需要引用的类class

import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.util.XML;
import com.egzosn.pay.wx.api.WxPayConfigStorage;
import com.egzosn.pay.wx.api.WxPayService;
import com.egzosn.pay.wx.bean.WxTransactionType;

结尾:此示例是用户开通vip的接口方法,重要的代码都有贴上。有疑问欢迎各位留言或联系邮箱laifw@foxmail.com,请多多指教

【原创】微信小程序支付java后台案例(公众号支付同适用)(签名错误问题)的更多相关文章

  1. 微信小程序登录JAVA后台

    代码地址如下:http://www.demodashi.com/demo/12736.html 登录流程时序登录流程时序 具体的登录说明查看 小程序官方API 项目的结构图: springboot项目 ...

  2. 微信小程序与Java后台通信

    一.写在前面 最近接触了小程序的开发,后端选择Java,因为小程序的代码运行在腾讯的服务器上,而我们自己编写的Java代码运行在我们自己部署的服务器上,所以一开始不是很明白小程序如何与后台进行通信的, ...

  3. 微信小程序与Java后台的通信

    一.写在前面 最近接触了小程序的开发,后端选择Java,因为小程序的代码运行在腾讯的服务器上,而我们自己编写的Java代码运行在我们自己部署的服务器上,所以一开始不是很明白小程序如何与后台进行通信的, ...

  4. 微信小程序内判断是否关注公众号(JAVA)

    微信小程序内判断是否关注公众号(JAVA) 思路来源(第二种): https://blog.csdn.net/Yanheeee/article/details/117295643 /** * 总体思路 ...

  5. 微信小程序:java后台获取openId

    一.功能描述 openId是某个微信账户对应某个小程序或者公众号的唯一标识,但openId必须经过后台解密才能获取(之前实现过前台解密,可是由于微信小程序的种种限制,前台解密无法在小程序发布后使用) ...

  6. 微信小程序与java后台交互

    java后台使用的ssm框架,小程序连接的本地接口.跟正常的web访问没什么区别,也是后台获取url,返回json数据:只是小程序前台请求的url要带上http://localhost:80801. ...

  7. 原创:微信小程序亲测体验,公众号入口曝光!

    扫描即可体验知乐微信小程序,并且看到入口 你可以在这里看到相应的小程序:微信小程序商店 发现内有历史列表入口 真实小程序 搜索 操作栏 放置到桌面示意图必须搜索全称,才可以搜索到小程序 推荐给朋友,可 ...

  8. 微信小程序知识总结及案例集锦

    微信小程序知识总结及案例集锦 微信小程序的发展会和微信公众号一样,在某个时间点爆发 学习路径 微信小程序最好的教程肯定是官方的文档啦,点击这里直达 微信官方文档 认真跟着文档看一遍,相信有vue前端经 ...

  9. 微信小程序需要https后台的创业机会思考

    最近比较关注微信小程序,而且微信小程序的后台必须强制要求https, https相对http成本要高很多了. 这里我感觉有2个商机 (1)提供https 中转服务器 ,按流量来收费 (2) 微信小程序 ...

  10. 原创:微信小程序开发要点总结

    废话不多少,下面是对我从开发微信小程序的第一步开始到发布的总结,觉得对您有帮助的话,可以赞赏下,以对我表示鼓励. 一:首先注册登录微信公众平台,这个平台很重要,以后查文档全在上面看.https://m ...

随机推荐

  1. CDQZ集训DAY3 日记

    早上起来之后依然开始考试.然而由于校方觉得都挨在一起没有考试氛围,分了两个机房,一开始还没人去,听说另一个机房配置好了之后一堆人开始往外冲,由于我天真的数了一下我是不是要走的,晚了一步,于是乎被教练员 ...

  2. EnjoyingSoft之Mule ESB开发教程第四篇:Mule Expression Language - MEL表达式

    目录 1. MEL的优势 2. MEL的使用场景 3. MEL的示例 4. MEL的上下文对象 5. MEL的Variable 6. MEL访问属性 7. MEL操作符 本篇主要介绍Mule表达式语言 ...

  3. WinForm控件之【CheckedListBox】

    基本介绍 复选框列表控件,以复选框的形式将一个或多个项列表展示,从目前的情况来看应用非常有限并不广泛. 常设置属性.事件 CheckOnClick:值为true时单击项即可更改项的勾选状态,值为fal ...

  4. NOIp2018 TG day1 T2暨洛谷P5020 货币系统:题解

    题目链接:https://www.luogu.org/problemnew/show/P5020 这道题感觉比较水啊,身为普及组蒟蒻都不费力的做出来了,而且数据范围应该还能大一些,n起码几万几十万都不 ...

  5. 个人永久性免费-Excel催化剂功能第29波-追加中国特色的中文相关自定义函数

    中文世界里,有那么几个需求在原生Excel里没提供,例如财务部的数字转大写金额,文字转拼音等,在其他插件里,大部分是以功能区菜单按钮的方式提供.Excel催化剂认为,最佳的使用方式乃是自定义函数的方式 ...

  6. 个人永久性免费-Excel催化剂功能第16波-N多使用场景的多维表转一维表

    Excel表的多维表数据结构转换为一维表的数据结构,以供更进一步对数据进行加工整理,生成另外格式的汇总表,这是Excel数据处理的一大刚需,几乎每个Excel表哥.表姐都会遇到这样的使用场景.很可惜, ...

  7. Netty(DotNetty)原理解析

    一.背景介绍 DotNetty是微软的Azure团队,使用C#实现的Netty的版本发布.不但使用了C#和.Net平台的技术特点,并且保留了Netty原来绝大部分的编程接口.让我们在使用时,完全可以依 ...

  8. nginx处理302、303和修改response返回的header和网页内容

    背景 遇到一个限制域名的平台,于是使用nginx在做网站转发,其中目标网站在访问过程中使用了多个302.303的返回状态,以便跳转到指定目标(为什么限制,就是防止他的网站的镜像). 在查找了一段资料后 ...

  9. MyBatis从入门到精通(十四):在MyBatis中使用类型处理器

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解在MyBatis中如何 ...

  10. JS+Jquery自定义格式导出HTML为Word(下列插件同样可以用于Excel导出)

    这里的word导出主要采用了jquery.wordexport.js.FileSaver.js,做功能之前我也是找了很多网上的资料,里面涉及到js导出word的用的都是这个插件,只是在自定义样式这一块 ...