您的位置:首页 > 移动开发 > 微信开发

Java-Web微信网页支付开发流程以及各种坑

2016-12-28 15:09 585 查看

微信网页支付流程概览

生成Oauth2.0授权链接获得code

使用code获得用户信息(OpenId)

向微信统一下单接口提交订单获得PrepayID

在JS页面中向用户发起支付请求

用户输入支付密码完成支付

使用weixin-java-tools工具可以快速完成以下开发


1.生成Oauth2.0授权链接

为什么要生成授权链接:当要为某用户提交支付订单时必须要得到该用户的OpenId(OpenId是加密后的微信帐号,同一个用户在不同的公众号内的该值是不同的)

而获得用户的OpenId,就需要用户对你的公众账号进行授权(可以不需要关注),用户授权之后微信将会发送一个code到你提供的页面(redirect_uri)

你需要提供和关心的内容

参数说明
appid公众号的唯一标识
redirect_uri授权后重定向的回调链接地址,请使用urlencode对链接进行处理
scope应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
使用开源的“weixin-java-tools”可以方便地生成授权链接:

//首先配置你的公众号信息
WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
config.setAppId("你的APPID");
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);
//轻松地拼接一个Oauth2.0授权链接
System.out.println(wxMpService.oauth2buildAuthorizationUrl("你的redirect_uri","snsapi_userinfo","传递一个state参数(可为null)"));


例如这里redirect_uri填写: http://mytest.com/test/pay

运行后会生成类似如下链接:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx19c7c9777756d0cc&redirect_uri=http%3A%2F%2Fmytest.com%2Ftest%2Fpay&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

上述链接需要你放置在你的微信公众号或者提交订单时的H5页面中,引导用户点击进行授权。从而可以进行以后的支付操作。

用户在该链接中选择授权您的公众号之后,微信会立即发送code值和state(你自己设定的字段)到你的redirect_uri中:

http://mytest.com/test/pay?code=CODE&state=STATE

因此你的redirect_uri应当指向一个服务而不是一个静态页面,这里使用tomcat+Java Servlet实现后续步骤

本章节会遇到的坑:

1.实际测试点击授权页面时提示redirect_uri参数错误

这里需要在微信公众号后台-接口权限-网页授权获取用户基本信息-修改 中添加你的redirect_uri的域名,注意是域名哦!此时会获得一个授权文件(txt)需要将该文件放置到你站点的根目录下。

2.使用code获得用户信息(OpenId)

上一步结束之后我们已经在Servlet中拿到code值,接下来我们需要去请求Access_Token和用户的OpenId(关键是要得到OpenId)(注意此处的Access_Token不同于微信开发中的Access_Token并不混用也不会互相刷新。code的有效期限为5分钟,且每申请一次只能使用一次)

//同样需要先配置公众号信息,但本次要求的参数为4个
WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
config.setAppId("你的APPID");
config.setSecret("你的APPSECRET");
config.setPartnerId("你的商户ID");
config.setPartnerKey("你的商户SecretKey");
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);
//使用已经得到的code获取AccessToken和OpenId
WxMpOAuth2AccessToken wxMpOAuth2AccessToken= null;
WxMpUser wxMpUser = null;
try {
wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
//下面的方法会获得用户的详细信息,本例用不到但是如有需要之前的步骤也是这么进行
wxMpUser = wxMpService.oauth2getUserInfo(wxMpOAuth2AccessToken, null);
} catch (WxErrorException e) {
e.printStackTrace();
}
String Openid=wxMpOAuth2AccessToken.getOpenId();
System.out.println("已经获得获得用户Openid:"+ Openid);


3.向微信统一下单接口提交订单

在下单之前我们需要组织参数

官方:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

下述实例将只进行关键必要参数的设置

WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
//由于我们前面的config配置 因此各种ID会被默认配置进去,NonceStr生成方法是System.currentTimeMillis()也已经默认添加。MD5签名加密问题也无需考虑,其内置的签名方法已经搞定。
orderRequest.setBody("商品描述");
orderRequest.setOutTradeNo("订单ID"); //商户唯一订单号
orderRequest.setTotalFee(1);//价格单位为‘分’
orderRequest.setOpenid(Openid);
orderRequest.setNotifyURL("http://www.weixin.qq.com/wxpay/pay.php");//微信回调地址 用户支付成功后微信会向该接口推送结果
orderRequest.setTradeType("JSAPI");//不要修改
orderRequest.setSpbillCreateIp("172.168.1.1");//当前用户的IP
WxMpPayService wxMpPayService = wxMpService.getPayService();
String mypackage="";
String nonceStr="";
try {           mypackage=""+wxMpPayService.getPayInfo(orderRequest).get("package");
nonceStr=""+wxMpPayService.getPayInfo(orderRequest).get("nonceStr");
System.out.println("prepayID:"+mypackage);
} catch (WxErrorException e) {
e.printStackTrace();
}


我们现在已经在微信上创建了一笔订单,并且返回我们需要的关键信息为package(包含prepayId),当然nonce_str是之前weixin-java-tools生成的,此时微信也会返回该值直接取得即可。

万事俱备,只欠从界面向用户发起支付请求

4.在JS页面中向用户发起支付请求

我们需要准备一个JSP请求支付的页面,并且在Servlet向其转发刚才获取的关键订单信息

<%@ page import="java.sql.Timestamp" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title><link rel="stylesheet" href="js/weui/css/weui.min.css" type="text/css">
<script type="text/javascript" src="js/weui/js/zepto.min.js"></script>
<script type="text/javascript" src="js/weui/js/jweixin.js"></script>
<script type="text/javascript" src="js/weui/js/weui.min.js"></script>
</head>

<body ontouchstart>
<div>
<div class="page">
<a href="javascript:;" class="weui-btn weui-btn_primary" id="btnPay">立即支付</a>
</div>
</div>
<script type="text/javascript">
$("#btnPay").on('click',function(){
console.log("TEST");
});
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "${APPID}",     //公众号名称,由商户传入
"timeStamp":"${TIMEST}",         //时间戳,自1970年以来的秒数
"nonceStr" : "${NOCESTR}", //随机串
"package" : "${PREPAYID}",
"signType" : "MD5",         //微信签名方式:
"paySign" : "${MYMD5}" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {}
}
);
}
if (typeof WeixinJSBridge == "undefined"){

if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
alert('调用WeiXin支付');
onBridgeReady();
}
</script>
</body>
</html>


本章节会遇到的坑:

1.实际测试时页面提示当前URL页面未注册

这里需要在微信公众号后台-微信支付-授权测试目录里面添加你当前支付JSP页面的目录。

比如我的支付页面是 http://a.com/test/pay/pay.jsp

那么我就需要填写 http://a.com/test/pay/

然而这里有一个坑就是,在实际发起支付的时候他会检查你发起支付的路径是什么,也就是说如果你如果之前使用servler获取数据后向JSP转发数据的话,那么用户在支付的时候url就不是http://a.com/test/pay/pay.jsp

而可能变成了http://a.com/test/pay?key=value

如此一来你填写的支付测试路径就出现了错误。因此需要修改测试路径为 http://a.com/test/ 即可通过。

至此用户在微信中访问第一步的授权链接后,会提示授权,然后跳转到JSP进行支付
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: