最近在做微信小程序,今天刚好做到小程序里的微信支付这块,踩过不少坑,特此写个博客记录下,希望能帮到其它人吧。

我总结了一下,小程序中的微信支付和之前其它的公众号里的微信支付有两个区别,第一就是小程序必须要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>";
}

微信小程序中实现微信支付的更多相关文章

  1. 微信小程序中的微信支付js代码和流程详解

    微信支付流程 步骤 (一)获取用户的信息 (二)统一下单(返回的prepay_id用于第(三)步的请求参数) (三)发起支付请求 操作(这边假设你已经获得了用户的openId) (一).获取用户ope ...

  2. 全栈开发工程师微信小程序-中(下)

    全栈开发工程师微信小程序-中(下) 微信小程序视图层 wxml用于描述页面的结构,wxss用于描述页面的样式,组件用于视图的基本组成单元. // 绑定数据 index.wxml <view> ...

  3. 微信小程序中发送模版消息注意事项

    在微信小程序中发送模版消息 参考微信公众平台Api文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/notice.html#模版消息管理 此参考地址 ...

  4. h5内嵌微信小程序,调用微信支付功能

    在小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的api进行支付. 因为需要在现在实现的基础上,再添加在小程序中调用微信支付功能,所以我的思路是这样的 1.在点击支付按钮时,判断是不 ...

  5. 网页或微信小程序中使元素占满整个屏幕高度

    在项目中经常要用到一个容器元素占满屏幕高度和宽度,然后再在这个容器元素里放置其他元素. 宽度很简单就是width:100% 但是高度呢,我们知道的是height:100%必须是在父元素的高度给定了的情 ...

  6. 在微信小程序中使用富文本转化插件wxParse

    在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...

  7. 微信小程序中placeholder的样式

    通常,现代浏览器大多支持::placeholder选择器,用于设置placeholder的样式,但是在微信小程序中并不支持这种方式,而是提供了一个专门的属性(placeholder-class)来处理 ...

  8. 微信小程序中转义字符的处理

    在微信小程序开发过程中,有时候会用到常用的一些特殊字符如:‘<’.‘>’.‘&’.‘空格’等,微信小程序同样支持对转义字符的处理,下面提供两种方法用来处理微信小程序中转义字符的处理 ...

  9. 微信小程序中用户登录和登录态维护

    提供用户登录以及维护用户的登录状态,是一个拥有用户系统的软件应用普遍需要做的事情.像微信这样的一个社交平台,如果做一个小程序应用,我们可能很少会去做一个完全脱离和舍弃连接用户信息的纯工具软件. 让用户 ...

随机推荐

  1. intra调用order

    response = orderMessageService.apply(mdpRequest[A1] ); public interface OrderMessageService[A2] { pu ...

  2. 使用 github 做代码管理,知道这些就够了

    只要掌握了下面的常用命令,基本上用使用 github 就没有问题.github 有两种认证方式,一种是通过 ssh 私钥的方式,一种通过 https 的账号名和密码.ssh 方式需要创建本地秘钥并且添 ...

  3. ASP.NET CSS 小结

    1.ASP.NET 引用CSS 1.Site.master里面设置webopt <webopt:bundlereferencerunat="server"path=" ...

  4. 凯撒密码加密解密--JAVA实现(基础)

    凯撒密码一种代换密码,据说凯撒是率先使用加密函的古代将领之一,因此这种加密方法被称为恺撒密码.凯撒密码的基本思想是:通过把字母移动一定的位数来实现加密和解密.明文中的所有字母都在字母表上向后(或向前) ...

  5. haproxy反向代理配置示例

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  6. xshell无法登录阿里云服务器

    1. 现象 a. 使用xshell无法登录服务器 b. 查看sshd服务 c. 不同公网ip的电脑正常登陆 2. 解决方案 a. 不同公网ip可以登录,断定是ip被黑名单,联系阿里云服务,把公网ip加 ...

  7. 学IT应该看些书?

    第一阶段:<数据结构><数据库><算法><信息系统管理><互联网>第二阶段:<莫生气><佛经><老子>& ...

  8. [Luogu4174][NOI2006]最大获益

    luogu sol 一周没摸键盘了回来刷刷水题练练手感 显然,最大化收益可以转化为最小化损失,从而建立最小割模型. 记\(tot=\sum_{i=1}^{m}C_i\),事先假设所有的获益都得到了,那 ...

  9. [BZOJ1022] [SHOI2008] 小约翰的游戏John (SJ定理)

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...

  10. TP5 路由使用

    这里可以直接从第四条开始看 原文http://www.upwqy.com/details/12.html 1 文档链接 tp5路由官方文档  https://www.kancloud.cn/manua ...