微信小程序中实现微信支付
最近在做微信小程序,今天刚好做到小程序里的微信支付这块,踩过不少坑,特此写个博客记录下,希望能帮到其它人吧。
我总结了一下,小程序中的微信支付和之前其它的公众号里的微信支付有两个区别,第一就是小程序必须要Https接口,第二服务器在返回给小程序之前需要二次签名,记住要二次签名。
我发现网上的相关例子很多,但是也很乱,各种封装类,五花八门的,在这里我用的是微信官方的方法,简单,无脑,高效。
1,我们需要在Maven坐标系里导入官方封装好的方法
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency> 2,写一个MyConfig类继承WXPayConfig
import com.baibeiyun.robot.base.util.PropertiesUtils;
import com.github.wxpay.sdk.WXPayConfig; import java.io.InputStream; /**
* 配置类
*
* @author liyuan
* @date 2018/3/30
**/
public class MyConfig implements WXPayConfig { @Override
public String getAppID() {
// 放你的appid
return PropertiesUtils.getInstace("conf/webService.properties").getProperty("appId");
} @Override
public String getMchID() {
// 商户号
return PropertiesUtils.getInstace("conf/webService.properties").getProperty("mchId");
} @Override
public String getKey() {
// 你的商户号里的key
return PropertiesUtils.getInstace("conf/webService.properties").getProperty("key");
} @Override
public InputStream getCertStream() {
return null;
} @Override
public int getHttpConnectTimeoutMs() {
return 8000;
} @Override
public int getHttpReadTimeoutMs() {
return 10000;
}
}
3. 在服务器端充值接口里获取到那5个关键参数传给小程序
@ApiOperation("小程序充值接口")
@RequestMapping(value = "saveMoney", method = RequestMethod.POST)
public String saveMoney(@ModelAttribute SaveMoney1Dto dto, HttpServletRequest request) throws Exception {
if (!dto.checkParam()) {
throw new MyParameterException(400, "请求参数异常");
}
// 获取用户userId
Integer userId = Integer.valueOf(redisService.get(dto.getUuidKey()).substring(52));
// 生成交易订单号
String orderNum = CommonUtils.getOrderNumber();
MoneyTransaction moneyTransaction = new MoneyTransaction();
moneyTransaction.setPayUserId(userId);
moneyTransaction.setOrderNum(orderNum);
moneyTransaction.setMoney(dto.getMoney());
// 交易时间
moneyTransaction.setGmtCreate(new Date());
// 将交易订单存入数据库
iMoneyTransactionService.insertSelective(moneyTransaction);
// 给微信服务器统一下单
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
// 封装入参字典
Map<String, String> data = new HashMap<>(16);
// 商品描述
data.put("body", "机器人服务充值");
// 商户订单号
data.put("out_trade_no", orderNum);
// 随机字符串
data.put("nonce_str", WXPayUtil.generateNonceStr());
// 总金额 分 将BigDecimal乘以100再转为字符串
String totalFee = (dto.getMoney().multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP)).toString();
data.put("total_fee", totalFee);
// 终端IP
data.put("spbill_create_ip", request.getRemoteAddr());
// 接收微信支付异步通知回调地址
data.put("notify_url", PropertiesUtils.getInstace("conf/webService.properties").getProperty("notifyUrl"));
// 交易类型
data.put("trade_type", "JSAPI");
// 获取opneid
String openid = redisService.get(dto.getUuidKey()).substring(24, 52);
data.put("openid", openid);
// 和微信服务器交互,统一下单
Map<String, String> resp = wxpay.unifiedOrder(data);
log.info("微信返回: " + resp);
// 小程序再次签名
Map<String, String> data2 = new HashMap<>(16);
data2.put("appId", resp.get("appid"));
String timeStamp = System.currentTimeMillis()/1000 + "";
data2.put("timeStamp", timeStamp);
String nonceStr = WXPayUtil.generateNonceStr();
data2.put("nonceStr", nonceStr);
String packages = "prepay_id="+resp.get("prepay_id");
data2.put("package", packages);
data2.put("signType", "MD5");
String sign2 = WXPayUtil.generateSignature(data2, PropertiesUtils.getInstace("conf/webService.properties").getProperty("key"));
// 封装返回给前端map
Map<String, String> result = new HashMap<>(16);
result.put("timeStamp", timeStamp);
result.put("nonceStr", nonceStr);
result.put("package", packages);
result.put("signType", "MD5");
result.put("paySign", sign2);
log.info("返回给前端: " + result);
return YuanResultUtil.successWithDataAndMsg(result, "OK");
}
在这里直接用微信的工具类,微信的方法比较高效,直接用map字典比较直观,犯不上像网上大多数人那样造一个封装类转来转去的麻烦
4 微信通知回调类
@ApiOperation("小程序充值结果(自动从微信服务器获取,前端用不到)")
@RequestMapping(value = "saveMoneyResult", method = RequestMethod.POST)
public String saveMoneyResult(HttpServletRequest request) throws Exception {
// 获取支付结果,XML格式
String notifyData = StreamUtil.read(request.getInputStream());
log.info("支付结果: " + notifyData);
MyConfig config = new MyConfig();
WXPay wxPay = new WXPay(config);
// 支付结果转成map
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);
if (wxPay.isPayResultNotifySignatureValid(notifyMap)) {
// 签名正确
log.info("签名正确: " + notifyMap);
// 获取订单号
String orderNum = notifyMap.get("out_trade_no");
log.info("订单号:" + orderNum);
// 获取金额(分)
String totalFee = notifyMap.get("total_fee");
// 转为BigDecimal
BigDecimal totalFee2 = new BigDecimal(totalFee);
totalFee2 = totalFee2.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
// 根据订单号获取交易记录
MoneyTransaction moneyTransaction = iMoneyTransactionService.getMoneyTransactionByOrderNum(orderNum);
if (moneyTransaction != null && moneyTransaction.getStatus() == 0 && moneyTransaction.getMoney().equals(totalFee2)) {
// 设置状态为支付成功
moneyTransaction.setStatus(1);
moneyTransaction.setGmtCreate(new Date());
log.info("修改成功");
iMoneyTransactionService.updateByPrimaryKeySelective(moneyTransaction);
return "<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>";
} else {
log.info("修改失败");
}
} else {
// 签名错误
throw new BuinessException(501, "签名错误");
}
return "<xml><return_code>FALL</return_code><return_msg>失败</return_msg></xml>";
}
微信小程序中实现微信支付的更多相关文章
- 微信小程序中的微信支付js代码和流程详解
微信支付流程 步骤 (一)获取用户的信息 (二)统一下单(返回的prepay_id用于第(三)步的请求参数) (三)发起支付请求 操作(这边假设你已经获得了用户的openId) (一).获取用户ope ...
- 全栈开发工程师微信小程序-中(下)
全栈开发工程师微信小程序-中(下) 微信小程序视图层 wxml用于描述页面的结构,wxss用于描述页面的样式,组件用于视图的基本组成单元. // 绑定数据 index.wxml <view> ...
- 微信小程序中发送模版消息注意事项
在微信小程序中发送模版消息 参考微信公众平台Api文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html#模版消息管理 此参考地址 ...
- h5内嵌微信小程序,调用微信支付功能
在小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的api进行支付. 因为需要在现在实现的基础上,再添加在小程序中调用微信支付功能,所以我的思路是这样的 1.在点击支付按钮时,判断是不 ...
- 网页或微信小程序中使元素占满整个屏幕高度
在项目中经常要用到一个容器元素占满屏幕高度和宽度,然后再在这个容器元素里放置其他元素. 宽度很简单就是width:100% 但是高度呢,我们知道的是height:100%必须是在父元素的高度给定了的情 ...
- 在微信小程序中使用富文本转化插件wxParse
在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...
- 微信小程序中placeholder的样式
通常,现代浏览器大多支持::placeholder选择器,用于设置placeholder的样式,但是在微信小程序中并不支持这种方式,而是提供了一个专门的属性(placeholder-class)来处理 ...
- 微信小程序中转义字符的处理
在微信小程序开发过程中,有时候会用到常用的一些特殊字符如:‘<’.‘>’.‘&’.‘空格’等,微信小程序同样支持对转义字符的处理,下面提供两种方法用来处理微信小程序中转义字符的处理 ...
- 微信小程序中用户登录和登录态维护
提供用户登录以及维护用户的登录状态,是一个拥有用户系统的软件应用普遍需要做的事情.像微信这样的一个社交平台,如果做一个小程序应用,我们可能很少会去做一个完全脱离和舍弃连接用户信息的纯工具软件. 让用户 ...
随机推荐
- Java中集合List,Map和Set的区别
Java中集合List,Map和Set的区别 1.List和Set的父接口是Collection,而Map不是 2.List中的元素是有序的,可以重复的 3.Map是Key-Value映射关系,且Ke ...
- hdu5860 Death Sequence
这题一开始写的线段数是从中间开始查找 k个 导致是nlogn 每次查找应该都是从头找每次找的个数不同就好了 还有一种递推的写法我放下面了 #include<bits/stdc++.h> u ...
- 你需要了解的高可用方案之使用keepalived搭建双机热备一览
在之前一篇使用nginx搭建高可用的解决方案的时候,很多同学会问,如果nginx挂掉怎么办,比如下面这张图: 你可以清楚的看到,如果192.168.2.100这台机器挂掉了,那么整个集群就下线了,这个 ...
- canvas焰火特效
之前在抖音上看到了一个很漂亮的焰火效果.这会儿有时间就用canvas实现了一下. 演示地址:http://suohb.com/work/firework4.htm 先看效果:(静态图片看不太出效果,请 ...
- linux用户和群组
1.用户的主要群组和次要群组 切换用户:su -username 查看群组:#vi /etc/passwd //主要群组 #vi /etc/gro ...
- 用Python来找合适的妹子
时间真的有点仓促,匆匆忙忙撸完这篇文章. 虽然今天是情人节,但还是要关心一下单身狗们,帮助他们俩脱单. 古人云:知己知彼,百战不殆. 好好去了解一下妹子们的内心想法,早日脱单! 这次我在一个某知名婚 ...
- 关于C++ const 的全面总结《转》
C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类 ...
- C++学习-10
类型转换:自动转换,显示转换,强转 总结:CPP编译的时候,从上往下,遇到不匹配,声明扩展了一个类的作用域(此时最多只能创建类的指针或者引用), 由于没有定义是不可能使用到类的成员 完 ...
- 进程优化工具Process Lasso Pro 8.4官方版+激活破解方法
Process Lasso是一款来自美国的系统进程优化工具,基于特殊算法动态调整进程的优先级别,通过合理的设置进程优先级来实现降低系统负担的功能.可有效避免蓝 屏.假死.进程停止响应.进程占用 CPU ...
- 学习python之路_入门篇A
偶尔经同事的介绍进入了金角大王的博客里,看到大王编写的文章都是关于python编程的,由于自己一直也是做软件测试方面的工作,也一直想往自动化测试方面发展,了解到利用python可以进行自动化测试操作, ...