Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

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

学不会丶 2019-02-16 17:16:00 阅读数:218 评论数:0 点赞数:0 收藏数:0

前言

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,请多多指教

版权声明
本文为[学不会丶]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/laifw/p/10388052.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领