前言

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. restapi(1)- 文件上传下载服务

    上次对restapi开了个头,设计了一个包括了身份验证和使用权限的restful服务开发框架.这是一个通用框架,开发人员只要直接往里面加新功能就行了.虽然这次的restapi是围绕着数据库表的CRUD ...

  2. 【动态规划例题-数塔问题】-C++

    描述 观察下面的数字金字塔.写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以 从当前点走到左下方的点也可以到达右下方的点. 在上面的样例中,从13到8到26到15到24 ...

  3. JDBC连接-操作数据库

    JDBC连接数据库的操作步骤 *条件:先启动mysql,然后创建新连接.这里我用Navicat工具来操作数据库. 前面是创建数据库,以及授权的问题.然后打开eclipse 这里我整理一下 抛出的两个异 ...

  4. 小白学python之整型,布尔值,十进制二进制转换和字符串详解for循环!

    整型与字符串转化 十进制转二进制. python2,存在int 整型和long(长整型),在python3里就是int/获取的是浮点数 小数 print(bin(15)) 这样可以通过代码来计算十进制 ...

  5. Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?

    导读 今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix.Ribbon以及Feign它们三者之 ...

  6. C#3.0新增功能09 LINQ 基础07 LINQ 中的查询语法和方法语法

    连载目录    [已更新最新开发文章,点击查看详细] 介绍性的语言集成查询 (LINQ) 文档中的大多数查询是使用 LINQ 声明性查询语法编写的.但是在编译代码时,查询语法必须转换为针对 .NET ...

  7. Java秒杀系统实战系列~构建SpringBoot多模块项目

    摘要:本篇博文是“Java秒杀系统实战系列文章”的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项目,即“秒杀系统”! ...

  8. Unity AR Foundation 和 CoreML: 实现手部的检测和追踪

    0x00 前言 Unity的AR Foundation通过上层抽象,对ARKit和ARCore这些底层接口进行了封装,从而实现了AR项目的跨平台开发能力. 而苹果的CoreML是一个可以用来将机器学习 ...

  9. 关于Spring的JDBC连接mysql(与传统jdbc比较)

    Spring的jdbc与Hibernate,Mybatis相比较,功能不是特别强大,但是在小型项目中,也到还是比较灵活简单. 首先可以看看一下传统的jdbc是如何操作的呢 传统JDBC 首先呢先要创建 ...

  10. 爬虫之解析库pyquery

    初始化 安装: pip install pyquery 字符串的形式初始化 html = """ <html lang="en"> < ...