前言

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. 【小家Spring】老项目迁移问题:@ImportResource导入的xml配置里的Bean能够使用@PropertySource导入的属性值吗?

    #### 每篇一句 > 大师都是偏执的,偏执才能产生力量,妥协是没有力量的.你对全世界妥协了你就是空气.所以若没有偏见,哪来的大师呢 #### 相关阅读 [[小家Spring]详解Propert ...

  2. 数据库系统概念:基础的SQL

    public class DataBase { public static void main() { } } /* 3.1 SQL查询语言概览 SQL语言有一下几个部分: 数据定义语言:提供定义关系 ...

  3. 基于ng-zorro的ASP.NET ZERO前端实现之代码生成器

    上一篇介绍了集成ng-zorro的过程,本篇我们来看下如何用abp官方的生成器来生成前端代码. Abp官方提供了一个强大的代码生成器 ASP.NET Zero Power Tools,它的Visual ...

  4. 一位 iOS 大牛的 BAT面试心得与经验总结,送给正在迷茫 的你!

    前言: 目前形势,参加到 iOS 队伍的人是越来越多,可以说是已经达到了供过于求的地步了. 今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,之前实习的时候就想着写一篇面经,后来忙就给忘了, ...

  5. WSASocket()创建套接字不成功解决方法

    这几天我在写一个模仿windows自带的ping程序,可是套接字总是创建不成功,在网上找了一些资料最后总算把问题解决了,现在总结一下. 解决方法:以管理员运行VS就行了我的是vs2013,vs2010 ...

  6. 研究分布式唯一ID生成,看完这篇就够

    很多大的互联网公司数据量很大,都采用分库分表,那么分库后就需要统一的唯一ID进行存储.这个ID可以是数字递增的,也可以是UUID类型的. 如果是递增的话,那么拆分了数据库后,可以按照id的hash,均 ...

  7. spring的jdbcTemplate的使用

    转载:http://1358440610-qq-com.iteye.com/blog/1826816 一.首先配置JdbcTemplate: 要使用Jdbctemplate 对象来完成jdbc 操作. ...

  8. 记一次idea问题—performing vcs refresh...

    01.前言 本人出现该场景是,我把本地SVN A项目删了,而A项目与B项目同在一个SVN目录下,当我修改B项目且提交代码时,出现了该问题. idea不是很懂操作,就搜索了一下得出了三种答案,但只有其一 ...

  9. Spring中FactoryBean的作用和实现原理

    BeanFactory与FactoryBean,相信很多刚翻看Spring源码的同学跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的.BeanFactory是Spring中Bean工厂的顶层接口, ...

  10. Flink状态专题:keyed state和Operator state

            众所周知,flink是有状态的计算.所以学习flink不可不知状态.         正好最近公司有个需求,要用到flink的状态计算,需求是这样的,收集数据库新增的数据.       ...