微信小程序中实现微信支付
最近在做微信小程序,今天刚好做到小程序里的微信支付这块,踩过不少坑,特此写个博客记录下,希望能帮到其它人吧。
我总结了一下,小程序中的微信支付和之前其它的公众号里的微信支付有两个区别,第一就是小程序必须要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)来处理 ...
- 微信小程序中转义字符的处理
在微信小程序开发过程中,有时候会用到常用的一些特殊字符如:‘<’.‘>’.‘&’.‘空格’等,微信小程序同样支持对转义字符的处理,下面提供两种方法用来处理微信小程序中转义字符的处理 ...
- 微信小程序中用户登录和登录态维护
提供用户登录以及维护用户的登录状态,是一个拥有用户系统的软件应用普遍需要做的事情.像微信这样的一个社交平台,如果做一个小程序应用,我们可能很少会去做一个完全脱离和舍弃连接用户信息的纯工具软件. 让用户 ...
随机推荐
- MPEG2_TS流基本概念和数据结构
时对应network_PID,program_number等于其它值时对应program_map_PID. (3)PMT PMT数据结构如下: TS_program_map_section(){ ...
- Linux显示内存状态
Linux显示内存状态 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ free total used free shared buffers cached M ...
- TypeError: Error #1034: 强制转换类型失败:无法将 flash.events::MouseEvent@73b7cc1 转换为 mx.events.ItemClickEvent。
1.错误描述 TypeError: Error #1034: 强制转换类型失败:无法将 flash.events::MouseEvent@73b7cc1 转换为 mx.events.ItemClick ...
- Codeforces Round #425 (Div. 2) D.Misha, Grisha and Underground
我奇特的脑回路的做法就是 树链剖分 + 树状数组 树状数组是那种 区间修改,区间求和,还有回溯的 当我看到别人写的是lca,直接讨论时,感觉自己的智商收到了碾压... #include<cmat ...
- js数组使用JSON.stringify()和toString()的区别,JSON.parse
JSON.stringify()中的<br><br>var arr = [1,2,3,4]; console.log(arr.toString()); // 1,2,3,4 a ...
- 论文笔记(3):STC: A Simple to Complex Framework for Weakly-supervised Semantic Segmentation
论文题目是STC,即Simple to Complex的一个框架,使用弱标签(image label)来解决密集估计(语义分割)问题. 2014年末以来,半监督的语义分割层出不穷,究其原因还是因为pi ...
- 自言自语WEB前端面试题(二)
今天换道题,新鲜出炉的 var Model=function(){ this.name='lilei'; this.age=20; } Model.prototype.say=function(){ ...
- webpack开发环境配置和生产环境配置
开发环境配置 在开发环境下,我们首先考虑的是方便开发,方便代码调试,不需要考虑代码合并和css样式分离这些. 这里主要说三个 :1.css模块化:2.模块热替换功能:3.source-map(代码映射 ...
- css学习の第三弹—盒模型的创建和使用
一.css盒模型: 元素分类: 块状元素.内联元素(又叫行内元素)和内联块状元素. >>常用的块状元素有: <div>.<p>.<h1>...<h ...
- centos7 升级 git(2.14.3) 版本
下载 wget https://www.kernel.org/pub/software/scm/git/git-2.14.3.tar.gz 安装依赖包 yum install curl-devel ...