Loading

微信支付二维码

需求分析

用户在提交订单后,如果是选择支付方式为微信支付,那应该跳转到微信支付二维码页面,用户扫描二维码可以进行支付,金额与订单金额相同。

实现思路

前端页面向后端传递订单号,后端根据订单号查询订单,检查是否为当前用户的未支付订单,如果是则根据订单号和金额生成支付url返给前端,前端得到支付url生成支付二维码。

代码实现

提交订单跳转支付页

1)更新changgou_web_order的application.yml,添加读取超时设置

#请求处理的超时时间
ribbon:
  ReadTimeout: 4000
  #请求连接的超时时间
  ConnectTimeout: 3000

2)在changgou_order_web工程resources/templates下添加 '资源/pay.html,fail.html,wxpay.html'。

3)更新changgou_service_order中add() ,设置返回值为订单Id

#orderServiceImpl
/**
     * 增加
     * @param order
     */
    @Override
    public String add(Order order){
        List<OrderItem> cartList = cartService.findCartList(order.getUsername());
​
        int totalMoney=0;
        int totalNum=0;
        int totalPayMoney=0;
        for (OrderItem orderItem : cartList) {
            totalMoney+=orderItem.getMoney();
            totalNum+=orderItem.getNum();
            totalPayMoney+=orderItem.getPayMoney();
        }
        order.setTotalNum(totalNum);
        order.setTotalMoney(totalMoney);
        order.setPayMoney(totalPayMoney);
        order.setPreMoney(totalMoney-totalPayMoney);
​
        //其他数据完善
        order.setCreateTime(new Date());
        order.setUpdateTime(order.getCreateTime());
        order.setBuyerRate("0");        //0:未评价,1:已评价
        order.setSourceType("1");       //来源,1:WEB
        order.setOrderStatus("0");      //0:未完成,1:已完成,2:已退货
        order.setPayStatus("0");        //0:未支付,1:已支付,2:支付失败
        order.setConsignStatus("0");    //0:未发货,1:已发货,2:已收货
        String orderId = idWorker.nextId() + "";
        order.setId(orderId);
        int result = orderMapper.insertSelective(order);
​
        for (OrderItem orderItem : cartList) {
            orderItem.setId(idWorker.nextId()+"");
            orderItem.setIsReturn("0");
            orderItem.setOrderId(order.getId());
            orderItemMapper.insertSelective(orderItem);
        }
​
        //扣减库存
        skuFeign.decrCount(order.getUsername());
​
        //清除缓存中的数据
        redisTemplate.delete("Cart_"+order.getUsername());
​
        return orderId;
    }
    
#orderController
@PostMapping
    public Result<String> add(@RequestBody Order order){
        String username = tokenDecode.getUserInfo().get("username");
        order.setUsername(username);
        String orderId = orderService.add(order);
        return new Result(true,StatusCode.OK,"添加成功",orderId);
    }

4) 更新order.html中添加订单js

add:function () {
                axios.post('/api/worder/add',this.order).then(function (response) {
                    if (response.data.flag){
                        alert("添加订单成功");
                        var orderId = response.data.data;
                        location.href="/api/worder/toPayPage?orderId="+orderId;
                    }else{
                        alert("添加失败");
                    }
                })
            }

5)在orderController中新增方法,用于跳转支付页

5.1)changgou_service_order_api的OrderFeign新增接口定义

/***
 * 根据ID查询数据
 * @param id
 * @return
 */
@GetMapping("/order/{id}")
public Result findById(@PathVariable("id") String id);

5.2) changgou_order_web中的orderController新增方法,跳转支付页

@GetMapping("/toPayPage")
    public String toPayPage(String orderId, Model model){
        Order order= orderFeign.findById(orderId).getData();
        model.addAttribute("orderId",orderId);
        model.addAttribute("payMoney",order.getPayMoney());
        return "pay";
    }

支付微服务-下单

(1)创建changgou_service_pay (支付微服务), pom.xml添加依赖

<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>3.0.9</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

排除log包,否则会因为包冲突无法正常启动

(2)创建配置文件application.yml

server:
  port: 9010
spring:
  application:
    name: pay
  rabbitmq:
    host: 192.168.200.128
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true

(3)创建com.github.wxpay.sdk包,包下创建Config类

public class MyConfig extends WXPayConfig {
    String getAppID() {
        return "wx8397f8696b538317";
    }
​
    String getMchID() {
        return "1473426802";
    }
​
    String getKey() {
        return "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb";
    }
​
    InputStream getCertStream() {
        return null;
    }
​
    IWXPayDomain getWXPayDomain() {
        return new IWXPayDomain() {
            public void report(String domain, long elapsedTimeMillis, Exception ex) {
            }
            public DomainInfo getDomain(WXPayConfig config) {
                return new DomainInfo("api.mch.weixin.qq.com",true);
            }
        };
    }
}

(4)创建com.changgou包,包下创建类PayApplication

@SpringBootApplication
@EnableEurekaClient
public class PayApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(PayApplication.class);
    }
​
    @Bean
    public WXPay wxPay(){
        try {
            return new WXPay( new MyConfig() );
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
​
}

(3)创建com.changgou.pay.controller包 ,新增WxPayController

@RestController
@RequestMapping("/wxpay")
public class WxPayController {
​
    @Autowired
    private WxPayService wxPayService;
​
    /**
     * 下单
     * @param orderId
     * @param money
     * @return
     */
    @GetMapping("/nativePay")
    public Result nativePay(@RequestParam("orderId")String orderId,@RequestParam("money") Integer money){
        Map map = wxPayService.nativePay( orderId, money );
        return new Result( true, StatusCode.OK,"",map );
    }
}

(4)创建com.changgou.pay.service包,包下创建接口WxPayService

public interface WxPayService {
​
    /**
     * 生成微信支付二维码
     * @param orderId
     * @param money
     * @return
     */
    Map nativePay(String orderId, Integer money);
}

(5)创建com.changgou.pay.service.impl 包 ,新增服务类WxPayServiceImpl

@Service
public class WxPayServiceImpl implements WxPayService {
​
    @Autowired
    private WXPay wxPay;
​
    @Override
    public Map nativePay(String orderId, Integer money) {
        try {
            //1.封装请求参数
            Map<String,String> map=new HashMap();
            map.put("body","畅购商城");//商品描述
            map.put("out_trade_no",orderId);//订单号
            //map.put("total_fee",String.valueOf(money*100));//金额,以分为单位
            BigDecimal payMoney = new BigDecimal("0.01");
            BigDecimal fen = payMoney.multiply(new BigDecimal("100")); //1.00
            fen = fen.setScale(0,BigDecimal.ROUND_UP); // 1
            map.put("total_fee",String.valueOf(fen));
            
            map.put("spbill_create_ip","127.0.0.1");//终端IP
            map.put("notify_url","http://www.itcast.cn");//回调地址,先随便填一个
            map.put("trade_type","NATIVE");//交易类型
            Map<String, String> mapResult = wxPay.unifiedOrder( map ); //调用统一下单
            return mapResult;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

测试:地址栏输入http://localhost:9010/wxpay/nativePay?orderId=990099&money=1

页面对接支付微服务

(1)新增changgou_service_pay_api模块 ,并添加common工程依赖,新增com.changgou.pay.feign包,包下创建接口

@FeignClient("pay")
public interface WxPayFeign {
​
    /**
     * 下单
     * @param orderId
     * @param money
     * @return
     */
    @GetMapping("/wxpay/nativePay")
    public Result nativePay(@RequestParam("orderId") String orderId,
                            @RequestParam("money") Integer money );
}

(2)changgou_web_order新增PayController

@Controller
@RequestMapping("/wxpay")
public class PayController {
​
    @Autowired
    private OrderFeign orderFeign;
​
    @Autowired
    private WxPayFeign wxPayFeign;
​
    /**
     * 微信支付二维码
     * @param orderId
     * @return
     */
    @GetMapping
    public String wxPay(String orderId, Model model){
        //根据orderId查询订单
        Result orderResult = orderFeign.findById( orderId );
        if(orderResult.getData()==null){ //如果订单不存在
            return "fail";//出错页
        }
       Order order = orderResult.getData();
        //判断支付状态
        if( !"0".equals( order.getPayStatus() )){// 如果不是未支付订单
            return "fail";//出错页
        }
        Result payResult = wxPayFeign.nativePay( orderId, order.getPayMoney() );
        if(payResult.getData()==null){
            return "fail";//出错页
        }
        Map payMap=  (Map)payResult.getData();
        payMap.put( "payMoney", order.getPayMoney() );
        payMap.put( "orderId" ,orderId );
        model.addAllAttributes( payMap );
        return "wxpay";
    }
​
}

(3)将静态原型中wxpay.html拷贝到templates文件夹下作为模板,修改模板,部分代码如下:

二维码地址渲染

<script type="text/javascript" th:inline="javascript">
let qrcode = new QRCode(document.getElementById("qrcode"), {
    width : 200,
    height : 200
});
qrcode.makeCode([[${code_url}]]);
</script>

显示订单号与金额

<h4 class="fl tit-txt"><span class="success-icon"></span><span  class="success-info" th:text="|订单提交成功,请您及时付款!订单号:${orderId}|"></span></h4>
<span class="fr"><em class="sui-lead">应付金额:</em><em  class="orange money" th:text="${payMoney}"></em>元</span>

设置支付跳转

<li><a th:href="|/api/wxpay?orderId=${orderId}|"><img src="/img/_/pay3.jpg"></a></li>

(4) 更新网关地址过滤器。添加wxpay路径的拦截

同时更新网关服务的application.yml。添加地址路由标识

posted @ 2021-08-11 14:36  1640808365  阅读(640)  评论(0编辑  收藏  举报