1. 微信支付快速入门 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/10-3.png?lastModify=1568098353 1.1 微信支付申请(了解)第一步:注册公众号(类型须为:服务号) 请根据营业执照类型选择以下主体注册:个体工商户| 企业/公司| 政府| 媒体| 其他类型。 第二步:认证公众号 公众号认证后才可申请微信支付,认证费:300元/次。 第三步:提交资料申请微信支付 登录公众平台,点击左侧菜单【微信支付】,开始填写资料等待审核,审核时间为1-5个工作日内。 第四步:开户成功,登录商户平台进行验证 资料审核通过后,请登录联系人邮箱查收商户号和密码,并登录商户平台填写财付通备付金打的小额资金数额,完成账户验证。 第五步:在线签署协议 本协议为线上电子协议,签署后方可进行交易及资金结算,签署完立即生效。 本课程已经提供好“传智播客”的微信支付账号,学员无需申请。 完成上述步骤,你可以得到调用API用到的账号和密钥 appid:微信公众账号或开放平台APP的唯一标识 wx8397f8696b538317 mch_id:商户号 1473426802 key:商户密钥 T6m9iK73b0kn9g5v426MKfHQH7X8rKwb 1.2 微信支付开发文档与SDK在线微信支付开发文档: [https://pay.weixin.qq.com/wiki/doc/api/index.html 微信支付接口调用的整体思路: 按API要求组装参数,以XML方式发送(POST)给微信支付接口(URL),微信支付接口也是以XML方式给予响应。程序根据返回的结果(其中包括支付URL)生成二维码或判断订单状态。 我们解压从官网下载的sdk ,安装到本地仓库 微信的SDK一定要从官网上下载,不要使用资料中提供的。 1.3 统一下单API(1)新建工程,引入微信支付Api(需要提前安装到本地仓库,maven仓库中没有) <dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.9</version>
</dependency>(2)创建Config类 ,继承自抽象类WXPayConfig 当前的Config类必须要和WXPayConfig在一个包下(包名一致即可为com.github.wxpay.sdk) public class Config 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);//第二个参数为是否为主域名
}
};
}
}(3)创建测试类,编写代码 Config config=new Config();
//1.封装请求参数
Map<String,String> map=new HashMap();
map.put("appid",config.getAppID());//公众账号ID
map.put("mch_id",config.getMchID());//商户号
map.put("nonce_str",WXPayUtil.generateNonceStr());//随机字符串
map.put("body","青橙");//商品描述
map.put("out_trade_no","555552");//订单号
map.put("total_fee","1");//金额
map.put("spbill_create_ip","127.0.0.1");//终端IP
map.put("notify_url","http://www.baidu.com");//回调地址
map.put("trade_type","NATIVE");//交易类型
String xmlParam = WXPayUtil.generateSignedXml(map, config.getKey()); //xml格式的参数,参数2为config中的秘钥
System.out.println("参数:"+xmlParam);
//2.发送请求
WXPayRequest wxPayRequest=new WXPayRequest(config);
String xmlResult = wxPayRequest.requestWithCert("/pay/unifiedorder", null, xmlParam, false);//附一个参数为接口连接的URL后缀,第二个参数无意义,第三个参数为上边的请求参数
System.out.println("结果:"+xmlResult);//响应结果
//3.解析返回结果
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);//解析结果
String code_url = mapResult.get("code_url");//获取结果集中的二维码
System.out.println(code_url);在调用API的代码中,我们经常用到WXPayUtil提供的以下功能: WXPayUtil.generateNonceStr();//获取随机字符串
WXPayUtil.generateSignedXml(param, partnerkey);//MAP转换为XML字符串(自动添加签名)
WXPayUtil.xmlToMap(result);//将XML字符串转换为MAPWXPayRequest为API的支付请求类,封装了httpClient。 执行后返回结果 <xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx8397f8696b538317]]></appid>
<mch_id><![CDATA[1473426802]]></mch_id>
<nonce_str><![CDATA[jcWWtgnQ1aYXmErr]]></nonce_str>
<sign><![CDATA[EBBB64AB3BA017B4C60C09C507E36C1B]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx23202155305471f07f6c3d398026955400]]></prepay_id>
<trade_type><![CDATA[NATIVE]]></trade_type>
<code_url><![CDATA[weixin://wxpay/bizpayurl?pr=Y3hDTZy]]></code_url>
</xml>其中的code_url就是我们的支付URl ,我们可以根据这个URl 生成支付二维码 1.4 二维码JS插件- QRcode.js QRCode.js (在资料中)是一个用于生成二维码的 JavaScript 库。主要是通过获取 DOM 的标签,再通过 HTML5 Canvas 绘制而成,不依赖任何库。支持该库的浏览器有:IE6~10, Chrome, Firefox, Safari, Opera, Mobile Safari, Android, Windows Mobile, 等 我们新建页面,编写一下代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
<head>
<title>QRCode</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="qrcode.min.js"></script>
</head>
<body>
<div id="qrcode"></div>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 200,
height : 200
});
qrcode.makeCode("weixin://wxpay/bizpayurl?pr=Y3hDTZy");
</script>
</body>
</html>1.5 内网映射工具EchoSite 在请求统一下单接口时,有个参数notify_url ,这个是回调地址,也就是在支付成功后微信支付会自动访问这个地址,通知业务系统支付完成。但这个地址必须是互联网可以访问的(也就是有域名的)。 那么如何测试呢?我们可以借助一个工具 EchoSite 内网映射工具 (1)打开网址: https://www.echosite.cn/ 注册用户,登录到控制台下载客户端。 (2)支付3元买一个域名(可以用1个月),点击域名端口---抢注域名 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/10-4.png?lastModify=1568098353 (3)下载客户端 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/1565786009316.png?lastModify=1568098353 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/1565786044360.png?lastModify=1568098353 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/1565786098890.png?lastModify=1568098353
解压下载后的压缩包得到运行文件。 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/1565786973957.png?lastModify=1568098353 (4)使用课程提供的软件echosite ,添加config.yml # 这是你的 EchoSite 购买域名的服务器标志
server_addr: easy.echosite.cn:4443
trust_host_root_certs: false
#填写自己的echo账号
echosite_id: 17799998888
#修改为自己的token
echosite_token: $2y$10$bY081mt/2KAFJLJXrsSNHe3f.6SM.SGfXgu1gG7aJvmPMPN9BTqrS
# 以下是你需要开启的通道,只能开启属于你的域名通道
# 以下分别是 http 和 https 以及 tcp 协议的示例
tunnels:
name1:
subdomain: "qingcheng" #修改为自己域名
proto:
http: 127.0.0.1:9102然后在echosite目录中输入以下命令 echosite -config=config.yml start-all这样你购买的域名就映射到127.0.0.1:9102上了。 ctrl+c 结束程序
由于门户工程使用域名来访问。那么下面的一些配置需要修改 1.qingcheng_web_portal中的cas.properties需要修改为 service_url=http://自己购买的域名.easy.echosite.cn2.cas服务中的application.properties文件需要修改 cas.logout.redirectUrl=http://自己购买的域名.easy.echosite.cn/index.do
2. 青橙-微信支付二维码 2.1 需求分析 用户在提交订单后,如果是选择支付方式为微信支付,那应该跳转到微信支付二维码页面,用户扫描二维码可以进行支付,金额与订单金额相同。 file://E:/6%E9%A1%B9%E7%9B%AE%E4%B8%80/%E9%A1%B9%E7%9B%AE%E4%B8%80%E8%AE%B2%E4%B9%89/day18/img/10-1.png?lastModify=1568098353 2.2 实现思路 1.前端页面向后端传递订单号,后端根据订单号查询订单 2.检查是否为当前用户的未支付订单, 3.如果是则根据订单号和金额生成支付url返给前端, 4.前端得到支付url生成支付二维码。 2.3 代码实现 2.3.1 后端代码 (1)qingcheng_service_order服务 pom.xml添加依赖 <dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>3.0.9</version>
</dependency>(2)创建config类 package com.github.wxpay.sdk;
import java.io.InputStream;
public class Config extends WXPayConfig {
public String getAppID() {
return "wx8397f8696b538317";
}
public String getMchID() {
return "1473426802";
}
public String getKey() {
return "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb";
}
public InputStream getCertStream() {
return null;
}
public 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);
}
};
}
}在spring配置文件中进行配置 <!--微信支付配置-->
<bean id="config" class="com.github.wxpay.sdk.Config"></bean>(3)qingcheng_interface创建包com.qingcheng.service.pay ,包下创建接口 /**
* 微信支付接口
*/
public interface WxPayService {
/**
* 生成微信支付二维码
* @param orderId 订单号
* @param money 金额(分)
* @param notifyUrl 回调地址
* @return
*/
public Map createNative(String orderId,Integer money,String notifyUrl);
}(4)qingcheng_service_order新增服务类 @Service
public class WxPayServiceImpl implements WxPayService {
@Autowired
private Config config;
public Map createNative(String orderId, Integer money,String notifyUrl) {
try {
//1.创建参数
Map<String,String> param=new HashMap();//创建参数
param.put("appid", config.getAppID());//公众号
param.put("mch_id", config.getMchID());//商户号
param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
param.put("body", "青橙");//商品描述
param.put("out_trade_no", orderId);//商户订单号
param.put("total_fee",money+"");//总金额(分)
param.put("spbill_create_ip", "127.0.0.1");//IP
param.put("notify_url", notifyUrl );//微信服务调用青橙的地址
param.put("trade_type", "NATIVE");//交易类型
String xmlParam = WXPayUtil.generateSignedXml(param, config.getKey());
//2.发送请求
WXPayRequest wxPayRequest = new WXPayRequest(config);
String result = wxPayRequest.requestWithCert("/pay/unifiedorder", null, xmlParam, false);
//3.封装结果
System.out.println(result);
Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
Map<String, String> map=new HashMap();
map.put("code_url", resultMap.get("code_url"));//支付地址
map.put("total_fee", money+"");//总金额
map.put("out_trade_no",orderId);//订单号
return map;
} catch (Exception e) {
e.printStackTrace();
return new HashMap();
}
}
}(5)qingcheng_web_portal新增WxPayController @RestController
@RequestMapping("/wxpay")
public class WxPayController {
@Reference
private OrderService orderService;
@Reference
private WxPayService wxPayService;
@GetMapping("/createNative")
public Map createNative(String orderId ){
String username = SecurityContextHolder.getContext().getAuthentication().getName();
Order order = orderService.findById(orderId);
if(order!=null){
if("0".equals(order.getPayStatus()) && "0".equals(order.getOrderStatus()) && username.equals(order.getUsername()) ){
return wxPayService.createNative(orderId,order.getPayMoney(),"http://qingcheng.easy.echosite.cn/wxpay/notify.do");
}else{
return null;
}
}else{
return null;
}
}
/**
* 回调
*/
@RequestMapping("/notify")
public void notifyLogic(){
System.out.println("支付成功回调。。。。");
}
}2.3.2 前端代码 (1)qingcheng_web_portal新增weixinpay.html 、paysuccess.html、payfail.html(资源中提供) (2)将二维码插件 qrcode.min.js 拷贝到qingcheng_web_portal下的js目录 (3)修改weixinpay.html 添加js代码 <script src="/js/vue.js"></script>
<script src="/js/axios.js"></script>
<script src="/js/qrcode.min.js"></script>
<script src="/js/util.js"></script>
<script>
new Vue({
el:'#app',
data(){
return {
orderId:"",
money:""
}
},
created(){
this.createNative();
},
methods:{
createNative(){
let orderId = getQueryString("orderId");//订单编号
axios.get(`/wxpay/createNative.do?orderId=${orderId}`).then( response=>{
if( response.data.out_trade_no!=null ){//商户订单号
let qrcode = new QRCode(document.getElementById("qrcode"), {
width : 200,
height : 200
});//生成支付二维码1
qrcode.makeCode(response.data.code_url); //生成支付二维码2
this.orderId= response.data.out_trade_no;
this.money= response.data.total_fee;
}else{
location.href="payfail.html";//失败页面
}
} )
}
}
});
</script>显示订单号和金额 <div class="checkout-tit" id="app">
<h4 class="fl tit-txt"><span class="success-icon"></span><span class="success-info">订单提交成功,请您及时付款!订单号:{{orderId}}</span></h4>
<span class="fr"><em class="sui-lead">应付金额:</em><em class="orange money">¥{{ (money/100).toFixed(2) }}</em>元</span>
<div class="clearfix"></div>
</div>修改页面二维码部分 <div id="qrcode"></div>(4)修改pay.html,增加Vue方法,完成到微信支付页面的跳转 methods:{
wxPay(){
location.href='/weixinpay.html?orderId='+this.ordersn;
}
}调用 <li @click="wxPay()"><img src="./img/_/pay3.jpg"></li>
2.3.3 修改配置文件并测试
修改spring-security-portal.xml,添加配置 <http pattern="/wxpay/notify.do" security="none"></http>
|