目录

​​支付页面​​

​​接口​​

​​后端实现​​

​​前端实现​​​​​​​​

​​​​​​​支付页面

步骤一:创建 flow3.vue组件

【畅购商城】微信支付之支付模块_mysql

步骤二:引入第三方资源(js、css)

<script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'

export default {
head: {
title: '首页',
link: [
{rel:'stylesheet',href: '/style/success.css'},
],
script: [

]
},
components: {
TopNav,
Footer,
},
}
</script>

​​​​​​​接口

POST http://localhost:10010/order-service/pay
{
"sn" : "1255513323915579400"
}


​​​​​​​后端实现

步骤一:编写 PayRequest,用于封装数据

【畅购商城】微信支付之支付模块_spring boot_02

package com.czxy.changgou4.vo;

import lombok.Data;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Data
public class PayRequest {
private Long sn;
}

步骤二:检查order服务,yml文件中是否有微信配置

【畅购商城】微信支付之支付模块_后端_03

sc:
pay:
appID: wx8397f8696b538317
mchID: 1473426802
key: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
httpConnectTimeoutMs: 5000
httpReadTimeoutMs: 10000

步骤三:编写PayProperties,用于加载微信配置

【畅购商城】微信支付之支付模块_微信_04

package com.czxy.changgou4.config;

import com.github.wxpay.sdk.WXPayConfig;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.io.InputStream;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Data
@ConfigurationProperties(prefix = "sc.pay")
public class PayProperties implements WXPayConfig {

private String appID; // 公众账号ID

private String mchID; // 商户号

private String key; // 生成签名的密钥

private int httpConnectTimeoutMs; // 连接超时时间

private int httpReadTimeoutMs; // 读取超时时间

@Override
public InputStream getCertStream() {
//加载证书,需要通过账号中心生成
return null;
}

}

步骤四:编写PayState,自定义支付状态

【畅购商城】微信支付之支付模块_后端_05

package com.czxy.changgou4.utils;

import lombok.Getter;

/**
* 自定义支付状态,微信支持多种状态,此处统一四种:
* SUCCESS—支付成功、NOTPAY—未支付、CLOSED—已关闭、PAYERROR--支付失败
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Getter
public enum PayState {
NOT_PAY(0,"未支付"),SUCCESS(1,"支付成功"),CLOSED(2,"已关闭"),PAY_ERROR(3,"支付失败");

PayState(int code,String desc) {
this.code = code;
this.desc = desc;
}
private int code; //自定义编码
private String desc; //描述信息
}

步骤五:编写PayHelper,用于微信操作的工具类

package com.czxy.changgou4.utils;

import com.czxy.changgou4.config.PayProperties;
import com.github.wxpay.sdk.WXPay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Component
@EnableConfigurationProperties(PayProperties.class)
public class PayHelper {

private WXPay wxPay;

@Bean
public WXPay wxPay(PayProperties payProperties){
if(wxPay == null){
wxPay = new WXPay(payProperties);
}
return wxPay;
}

private static final Logger logger = LoggerFactory.getLogger(PayHelper.class);

public PayHelper() {

}

public PayHelper(PayProperties payProperties) {
wxPay = new WXPay(payProperties);
}

public String createPayUrl(Long sn) {
String key = "pay.url." + sn;

try {
Map<String, String> data = new HashMap<>();
// 商品描述
data.put("body", "商城测试");
// 订单号
data.put("out_trade_no", sn.toString());
//货币
data.put("fee_type", "CNY");
//金额,单位是分
data.put("total_fee", "1");
//调用微信支付的终端IP(商城的IP)
data.put("spbill_create_ip", "127.0.0.1");
//回调地址
data.put("notify_url", "http://test.jingxi.com/wxpay/notify");
// 交易类型为扫码支付
data.put("trade_type", "NATIVE");
//商品id,使用假数据
data.put("product_id", "1234567");

Map<String, String> result = this.wxPay.unifiedOrder(data);
if ("SUCCESS".equals(result.get("return_code"))) {
if("SUCCESS".equals(result.get("result_code"))){
String url = result.get("code_url");

return url;
} else {
logger.error("创建预交易订单失败,错误信息:{}", result.get("err_code_des"));
return null;
}
} else {
logger.error("创建预交易订单失败,错误信息:{}", result.get("return_msg"));
return null;
}
} catch (Exception e) {
logger.error("创建预交易订单异常", e);
return null;
}
}

/**
* 查询订单状态
* 交易状态参考:(trade_state)
SUCCESS—支付成功
REFUND—转入退款
NOTPAY—未支付
CLOSED—已关闭
REVOKED—已撤销(付款码支付)
USERPAYING--用户支付中(付款码支付)
PAYERROR--支付失败(其他原因,如银行返回失败)
* @param sn
* @return
*/
public PayState queryOrder(Long sn) {
Map<String, String> data = new HashMap<>();
// 订单号
data.put("out_trade_no", sn.toString());
try {
Map<String, String> result = this.wxPay.orderQuery(data);
if("SUCCESS".equals(result.get("return_code"))){
if("SUCCESS".equals(result.get("result_code"))) {
String tradeState = result.get("trade_state");
if ("SUCCESS".equals(tradeState)) {
return PayState.SUCCESS;
}
if ("NOTPAY".equals(tradeState)) {
return PayState.NOT_PAY;
}
if ("CLOSED".equals(tradeState)) {
return PayState.CLOSED;
}
}
}
return PayState.PAY_ERROR;
} catch (Exception e) {
logger.error("查询订单状态异常", e);
return PayState.PAY_ERROR;
}
}
}

步骤五:编写PayService,调用工具类,用于生成支付接口

【畅购商城】微信支付之支付模块_微信_06

package com.czxy.changgou4.service;

import com.czxy.changgou4.vo.PayRequest;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface PayService {

public String pay(PayRequest payRequest);
}
package com.czxy.changgou4.service.impl;

import com.czxy.changgou4.service.PayService;
import com.czxy.changgou4.utils.PayHelper;
import com.czxy.changgou4.vo.PayRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
public class PayServiceImpl implements PayService {
@Resource
private PayHelper payHelper;

@Override
public String pay(PayRequest payRequest) {
//根据sn查询订单
//获得微信支付路径
String payUrl = payHelper.createPayUrl(payRequest.getSn());
//返回支付路径
return payUrl;

}
}

步骤六:编写PayController,根据sn生产微信支付路径

【畅购商城】微信支付之支付模块_spring boot_07

package com.czxy.changgou4.controller;

import com.czxy.changgou4.service.PayService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.PayRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/pay")
public class PayController {

@Resource
private PayService payService;


@PostMapping
public BaseResult pay(@RequestBody PayRequest payRequest){
//获得支付路径
String payUrl = payService.pay(payRequest);
//返回
return BaseResult.ok("二维码生产成功").append("wxurl",payUrl);
}

}

​​​​​​​前端实现

步骤一:修改apiclient.js文件,生成位置支付路径

【畅购商城】微信支付之支付模块_mysql_08

pay : ( params ) => {
return axios.post("/order-service/pay" ,params )
}

步骤二:拷贝qrcode.min.js 用于生成二维码

【畅购商城】微信支付之支付模块_微信_09

步骤三:导入qrcode.min.js

【畅购商城】微信支付之支付模块_后端_10

script: [
{ type: 'text/javascript', src: '/js/qrcode.min.js' }
]

步骤四:页面加载成功,把微信支付路径生产二维码

data() {
return {
sn: this.$route.query.sn,
}
},
async mounted() {
let {data} = await this.$request.pay({"sn":this.sn})
new QRCode( document.getElementById("qrcode") , data.other.wxurl )
},

步骤五:确定二维码生成的位置

【畅购商城】微信支付之支付模块_后端_11

<p>
<div id="qrcode" style="width:256px;margin: 0 auto;"></div>
</p>

步骤六:优化,添加样式,

<style>
#qrcode img {
background-color: #fff;
padding: 6px;
}
</style>