前端
<template>
<div id="app">
<el-button type="primary" @click="pay">支付</el-button>
<el-dialog
title="收银台"
:visible.sync="dialogVisible"
width="30%"
>
<div style="text-align: center">
<p>微信支付{
{payResult.price}}</p>
<div style="border: 1px solid #f3f3f3;width: 220px;padding: 10px;margin:0px auto">
<vue-qr
:text="payResult.codeUrl"
:margin="0"
colorDark="red"
:logoSrc="require('@/assets/logo.png')"
colorLight="#fff"
:size="200"
></vue-qr>
</div>
</div>
<el-divider></el-divider>
<div style="font-size: 13px">
提示:<br>
支付成功前请勿关闭此页面<br>
二维码两小时内有效,请及时扫码支付
</div>
</el-dialog>
<!-- <!–渲染组件 渲染到这里–>-->
<!-- <!–路由视图 点击首页 通过路径渲染到这里–>-->
<!-- <router-view/>-->
</div>
</template>
<script>
import vueQr from "vue-qr"
export default {
name: 'app',
data(){
return{
orderNo:"c60801fbdd9d45f92d4",
payResult:{
price:0.01,
//借助vue-ur 可以吧二维码的地址转化为图片
codeUrl:"",
orderNo: "",
},
codeUrl:"",
dialogVisible:false,
timer1:""
}
},
components:{
vueQr
},
methods:{
//根据订单号查询支付状态
queryPayStatus(orderNo){
this.axios.post("/order/queryPayStutus/"+orderNo).then(result=>{
if(result.data.code===2000){
//消除定时器
clearInterval(this.timer1)
this.timer1=null;
this.$message.success("支付成功");
this.dialogVisible=false;
}
})
},
//支付
pay(){
this.dialogVisible=true
this.axios.post("/order/createNavite/"+this.orderNo).then(result=>{
console.log(result)
if(result.data.code===2000){
this.payResult=result.data.data;
//设置定时任务 3秒一次
this.timer1 = setInterval(()=>{
this.queryPayStatus(this.payResult.orderNo)
},3000)
}
})
}
}
}
</script>
<style>
</style>
package weixin.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import weixin.entity.Order;
import weixin.mapper.OrderMapper;
import weixin.service.IOrderService;
import weixin.utils.HttpClient;
import weixin.vo.CommonResult;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SimpleTimeZone;
/**
* <p>
* 订单 服务实现类
* </p>
*
* @author 小超超
* @since 2022-08-13
*/
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
@Autowired
private OrderMapper orderMapper;
@Value("${weixin.appid}")
private String appId;
@Value("${weixin.mch_id}")
private String mchId;
@Value("${weixin.api_key}")
private String apiKey;
@Override
public CommonResult createNavite(String orderNo) {
//1.根据订单号查询出订单信息
QueryWrapper wrapper = new QueryWrapper();
//前端传过来的订单号跟数据库中的订单号一致
wrapper.eq("order_no",orderNo);
//订单状态为0
wrapper.eq("status",0);
Order order = orderMapper.selectOne(wrapper);
//判断订单信息不为空
if (order != null) {
log.info("~~~~~~~~~~~~~~~~~~~~~~~~"+order);
try {
//接口里面的参数要的是xml类型
//设置请求的参数个数格式为xml格式
//将请求参数封装成map
Map<String, String> params = new HashMap<>();
//添加公众账号Id
params.put("appid", appId);
//添加商品号
params.put("mch_id", mchId);
//添加随机字符串--微信自带算法
params.put("nonce_str", WXPayUtil.generateNonceStr());
//添加商品描述
params.put("body", order.getCourseTitle());
//添加商品订单号
params.put("out_trade_no", orderNo);
//添加标价金额 --单位是分,要转换
params.put("total_fee", new BigDecimal(0.01).multiply(new BigDecimal(100)).longValue() + "");
//添加终端ip
params.put("spbill_create_ip", "127.0.0.1");
//添加通知地址
params.put("notify_url", "http://localhost:8888/pay/back");
//添加交易类型
params.put("trade_type", "NATIVE");
//创建HttpClient对象--作用远程调用
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//支持https协议
client.setHttps(true);
//将map转为xml格式--设置请求的参数
client.setXmlParam(WXPayUtil.generateSignedXml(params,apiKey));
//发送请求
client.post();
//获取请求响应响应的结果
String content = client.getContent();
//将String类型转换为map返回给前端
Map<String, String> map1 = WXPayUtil.xmlToMap(content);
if (map1.get("result_code").equals("SUCCESS")){
Map<String,Object> result=new HashMap<>();
result.put("codeUrl",map1.get("code_url"));
result.put("price",order.getTotalFee());
result.put("orderNo",orderNo);
return new CommonResult(2000,"生成二维码",result);
}
}catch (Exception e){
e.printStackTrace();
}
}
return new CommonResult(5000,"订单失效",null);
}
@Override
public CommonResult queryPayStutus(String orderNo) {
try{
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
Map<String, String> hashMap = new HashMap<>();
hashMap.put("appid",appId);
hashMap.put("mch_id",mchId);
hashMap.put("out_trade_no",orderNo);
hashMap.put("nonce_str",WXPayUtil.generateNonceStr());
client.setHttps(true);
client.setXmlParam(WXPayUtil.generateSignedXml(hashMap,apiKey));
client.post();
String content = client.getContent();
Map<String, String> xmlToMap = WXPayUtil.xmlToMap(content);
if(xmlToMap.get("trade_state").equals("SUCCESS")){
//1.修改订单状态
Order order = new Order();
order.setStatus(1);
order.setGmtModified(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
QueryWrapper<Order> wrapper = new QueryWrapper<>();
wrapper.eq("order_no",orderNo);
wrapper.eq("status",0);
orderMapper.update(order,wrapper);
//2.往记录表中添加支付记录
return new CommonResult(2000,"支付成功",null);
}
}catch (Exception e){
log.info("*************************"+e.getMessage());
e.printStackTrace();
}
return new CommonResult(5000,"支付失败",null);
}
}
再加个跨域
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。这里默认1天
private static final long MAX_AGE = 24 * 60 * 60;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}