大家好, 我是上白书妖!
知识源于积累,登峰造极源于自律
今天我根据以前所以学的一些文献,笔记等资料整理出一些小知识点,有不当之处,欢迎各位斧正
一、添加依赖
service-order中添加微信sdk依赖
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
2、配置yml参数
微信参数
weixin:
pay:
#关联的公众号appid
appid: wx74862e0dfcf69954
#商户号
partner: 1558950191
#商户key
partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
#回调地址
notifyurl: http://guli.shop/api/order/weixinPay/weixinNotify
redis参数
spring:
redis:
host: 39.106.16.235
port: 6379
database: 0
timeout: 1800000
password: 123456
jedis:
pool:
max-active: 20 #最大连接数
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
max-idle: 5 #最大空闲
min-idle: 0 #最小空闲
3、参数读取工具类
package com.atguigu.guli.service.order.util;
@Data
@Component
//注意prefix要写到最后一个 "." 符号之前
@ConfigurationProperties(prefix="weixin.pay")
public class WeixinPayProperties {
private String appid;
private String partner;
private String partnerkey;
private String notifyurl;
}
4、httpClinet工具类
HttpClient.java放入当前项目
二、根据订单号生成支付二维码
1、API:统一下单接口文档
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
2、辅助业务方法
OrderService:getOrderByOrderNo
接口:
/**
* 根据订单号查询订单
* @param orderNo
* @return
*/
Order getOrderByOrderNo(String orderNo);
实现:
/**
* 根据订单号查询订单实体
*
* @param orderNo
* @return
*/
public Order getOrderByOrderNo(String orderNo) {
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_no", orderNo);
return orderMapper.selectOne(queryWrapper);
}
3、下单业务(生成支付二维码)
创建 WeixinPayService:createNative
接口:
package com.atguigu.guli.service.order.service;
public interface WeixinPayService {
/**
* 根据订单号下单,生成支付链接
* @param orderNo
* @return
*/
Map<String, Object> createNative(String orderNo, String remoteAddr);
}
实现:
package com.atguigu.guli.service.order.service.impl;
@Service
@Slf4j
public class WeixinPayServiceImpl implements WeixinPayService {
@Autowired
private OrderService orderService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private WeixinPayProperties weixinPayProperties;
/**
* 根据订单号下单,生成支付链接
* @param orderNo
* @return
*/
@Override
public Map<String, Object> createNative(String orderNo, String remoteAddr) {
try {
Map<String, Object> payMap = (Map)redisTemplate.opsForValue().get(orderNo);
if(payMap != null) {
return payMap;
}
Order order = orderService.getOrderByOrderNo(orderNo);
Map<String, String> m = new HashMap<>();
//1、设置参数
m.put("appid", weixinPayProperties.getAppid());
m.put("mch_id", weixinPayProperties.getPartner());
m.put("nonce_str", WXPayUtil.generateNonceStr());
m.put("body", order.getCourseTitle());
m.put("out_trade_no", orderNo);
int totalFee = order.getTotalFee().multiply(new BigDecimal("100")).intValue();
//转成string,否则在下面generateSignedXml中会有java.lang.Integer cannot be cast to java.lang.String
m.put("total_fee", totalFee + "");
m.put("spbill_create_ip", remoteAddr);
m.put("notify_url", weixinPayProperties.getNotifyurl());
m.put("trade_type", "NATIVE");
//2、HTTPClient来根据URL访问第三方接口并且传递参数
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//client设置参数
client.setXmlParam(WXPayUtil.generateSignedXml(m, weixinPayProperties.getPartnerkey()));
client.setHttps(true);
client.post();
//3、返回第三方的数据
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
//4、封装返回结果集
System.out.println(xml);
System.out.println(resultMap.get("return_code"));
System.out.println(resultMap.get("return_msg"));
System.out.println(resultMap.get("err_code"));
System.out.println(resultMap.get("err_code_des"));
if("FAIL".equals(resultMap.get("return_code")) || "FAIL".equals(resultMap.get("result_code")) ){
log.error("统一下单错误 - " +
"return_msg: " + resultMap.get("return_msg") + ", " +
"err_code: " + resultMap.get("err_code") + ", " +
"err_code_des: " + resultMap.get("err_code_des"));
throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
}
Map<String, Object> map = new HashMap<>();
map.put("result_code", resultMap.get("result_code"));
map.put("code_url", resultMap.get("code_url"));
map.put("course_id", order.getCourseId());
map.put("total_fee", order.getTotalFee());
map.put("out_trade_no", orderNo);
//微信支付二维码2小时过期,可采取2小时未支付取消订单
redisTemplate.opsForValue().set(orderNo, map, 120, TimeUnit.MINUTES);
return map;
} catch (Exception e) {
log.error(ExceptionUtils.getMessage(e));
throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
}
}
}
4、下单接口
ApiWeixinPayController:createNative
package com.atguigu.guli.service.order.controller.api;
@RestController
@RequestMapping("/api/order/weixinPay")
@Api(description = "网站微信支付")
@CrossOrigin //跨域
@Slf4j
public class ApiWeixinPayController {
@Autowired
private WeixinPayService weixinPayService;
/**
* 生成二维码
*
* @return
*/
@GetMapping("/createNative/{orderNo}")
public R createNative(@PathVariable String orderNo, HttpServletRequest request) {
String remoteAddr = request.getRemoteAddr();
Map map = weixinPayService.createNative(orderNo, remoteAddr);
return R.ok().data(map);
}
}
三、支付前端
根据微信支付下单接口返回的二维码url,在页面生成二维码,然后根据订单号定时调用支付查询接口,查看是否支付成功,如果支付成功返回课程详情页观看课程视频
1、安装二维码生成器
npm install [email protected]
2、配置插件
创建 plugins/vue-qriously-plugin.js
import Vue from 'vue'
import VueQriously from 'vue-qriously'
Vue.use(VueQriously)
nuxt.config.js中配置
plugins: [
{ src: '~/plugins/vue-qriously-plugin.js', ssr: false }
],
3、api
创建api/pay.js
import request from '@/utils/request'
const apiPath = '/api/order/weixinPay'
export default {
createNative(orderId) {
return request({
baseURL: 'http://localhost:8170',
url: `${apiPath}/createNative/${orderId}`,
method: 'get'
})
}
}
4、支付页面
创建pages/pay/_id.vue
<template>
<div class="cart py-container">
<!--主内容-->
<div class="checkout py-container pay">
<div class="checkout-tit">
<h4 class="fl tit-txt"><span class="success-icon"/><span class="success-info">订单提交成功,请您及时付款!订单号:{{ payObj.out_trade_no }}</span>
</h4>
<span class="fr"><em class="sui-lead">应付金额:</em><em class="orange money">¥{{ payObj.total_fee }}</em></span>
<div class="clearfix"/>
</div>
<div class="checkout-steps">
<div class="fl weixin">微信支付</div>
<div class="fl sao">
<p class="red">请使用微信扫一扫。</p>
<div class="fl code">
<!-- <img id="qrious" src="~/assets/img/erweima.png" alt=""> -->
<qriously :value="payObj.code_url" :size="338"/>
<div class="saosao">
<p>请使用微信扫一扫</p>
<p>扫描二维码支付</p>
</div>
</div>
</div>
<div class="clearfix"/>
<!-- <p><a href="pay.html" target="_blank">> 其他支付方式</a></p> -->
</div>
</div>
</div>
</template>
<script>
import pay from '~/api/pay'
export default {
async asyncData({ params }) {
const response = await pay.createNative(params.id)
return {
payObj: response.data.data
}
},
// 在created中获取数据,报告Invalid prop: type check failed for prop "value".
// created() {
// pay.createNative(this.$route.params.id).then(response => {
// this.payObj = response.data.data
// })
// }
}
</script>