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

微信支付开发教程(公众号支付)

2018-02-17 23:00 543 查看
    前段时间公司电商项目需要接入微信支付,因此研究了一下如何使用微信支付。和支付宝支付相比,微信支付相对复杂一些,需要配置的东西更多,限制也更多。经过两天的研究,终于搞定微信支付,在这里对于使用微信支付的经验进行一些总结。
    由于微信支付官方文档对微信支付进行了非常详细的说明,因此本文对微信支付相关API不会进行详细的说明,相关参考将会附上官方文档相关链接,本文力求以最简短的语言概述微信支付的各个流程,并提供相关demo,使大家以最快的速度上手微信公众号支付。

    首先微信公众号支付主要步骤为:开发配置-->获取openid-->调用统一下单接口-->唤起微信支付-->获得支付结果,接下来是具体的开发步骤:

    一.进行开发配置

    打开微信支付官方文档首页,根据你所需开发的具体微信支付类型点击查看相关文档,以公众号支付为例,打开后如图所示:


    可以先跳过案例介绍,直接查看开发步骤,然后按照文档说明设置支付目录以及授权域名,这里需要注意以下几点:

    1.支付目录以及授权目录必须是外网域名,不能为内网地址,如:localhost、127.0.0.1、192开头的等等。。。

    2.设置授权域名是为了获取openid,公众号支付统一下单接口openid为必传字段,本文也会着重讲解如何获取openid。,然后根据开发步骤中的描述将MP开头的文件上传到服务器根目录。
二、获取openid
    openid可以通过微信网页授权获取,网页授权有两种scope,分别为snsapi_base、snsapi_userinfo,这里我们简单的说明一下,具体区别见微信网页授权官方文档(建议仔细查看)。

    snsapi_base:是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面),也就是说该方式不会跳转到微信确认登录界面,就像直接打开某个页面一样。但这种方式的局限性为无法获取用户基本信息,如:微信头像,用户名等。如果不需要获取用户基本信息,建议采用此方式,因为可以不需要用户确认登录。

    snsapi_userinfo:是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。

    要获取openid首先要获取code,接下来看下如何获取code,这里我们以snsapi_base的scope为例。
//需要跳转的页面uri
var redirect_uri = 'http://www.xxxx.com/mobile';
//调用网页授权接口链接,注意,redirect_uri必须进行encode
var url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的appid&redirect_uri='+encodeURI(redirect_uri)+
'&response_type=code&scope=snsapi_base&state=1#wechat_redirect';
//执行跳转
window.location = url;这时如果appid以及跳转uri无误的话,微信服务器将自动将页面跳转到redirect_uri页面上,并在uri结尾带上code以及state参数,如:http://www.xxxx.com/mobile?code=081r2cZF0YJGzj2P75XF03l1ZF0r2cZ-&state=1,这时我们在后台就可以获取到code。
建议大家下载一个微信web开发者工具,可以模拟并调试微信内置浏览器环境,部分调试功能可能需要微信公众号平台授权。
获取完code之后我们具体看下如何获取openid //处理openId
/**
*
* @param request
* @param code 获取到的code
*/
private void handOpenId(HttpServletRequest request,String code){
String openId = (String)request.getSession().getAttribute("openid");
if(openId != null) {
return;
}else {
//你的appid
String appid = "xxxxxxxxxxx";
//你的appsecret
String appsecret = "xxxxxxxxxx";
//拼接url
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
+ appid
+ "&secret="
+ appsecret
+ "&code="
+ code
+ "&grant_type=authorization_code";
//发出请求
GetMethod getTokenMethod = new GetMethod(url);
HttpClient clientToken = new HttpClient();
getTokenMethod.getParams().setContentCharset("utf-8");
String res = "";
Map<String, String> resultMap = null;
try{
clientToken.executeMethod(getTokenMethod);
//获取响应结果
res = getTokenMethod.getResponseBodyAsString();
//将返回的参数转换为map
resultMap = WeiXinUtil.getWeiToken(res);
//如果获取到参数,则将openid放入session中
if(resultMap != null) {
request.getSession().setAttribute("openid",resultMap.get("openid"));
}
}catch (Exception e){
LOGGER.error("获取openId出错",e);
}
}
}
/**
* 获取微信token openid信息
*
* @param res
*            微信返回Json包
* @return Map<String,String> 处理后Map
*/
public static Map<String, String> getWeiToken(String res) {
Map<String, String> userData = new HashMap<String, String>();
JSONObject jsonData = JSONObject.fromObject(res);
userData.put(ACCESSTOKEN, jsonData.getString(ACCESSTOKEN).toString());
userData.put("openid", jsonData.getString("openid").toString());
return userData;
}
因为appsecret很重要,因此我们一般通过服务器请求来获取openid,正常情况下将返回一下数据:
{
    "access_token":"ACCESS_TOKEN",
    "expires_in":7200,
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID",
    "scope":"SCOPE"
}
获取后我们可以将openid放到session中,避免重复获取。其中access_token是获取用户信息用的,并且有过期时间以及每天获取次数限制,如果不需要获取用户信息可以忽略此参数。
三、调用统一下单接口
    统一下单接口是微信支付中各种类型支付必须要调用的后台接口,统一下单接口调用成功与否是决定能否唤起微信支付的前提,如果能成功调用统一下单接口,整个微信公众号支付已经成功99%了,而且调用统一下单接口不需要线上环境,通过本地环境就可以调试,我们可以通过下载官方SDK&DEMO来调试,也可以使用我提供的SDK&DEMO来调试,这里建议使用我提供的SDK来调试,我仅仅对官方SDK&DEMO中一些配置进行简化,更加清晰明了。大家可以直接 下载我的SDK&DEMO。接下来我们具体看下如何通过SDK进行调试。
    首先将下载下来的SDK&DEMO在Intellij Idea 或者Eclipse中打开并导入相关maven依赖,打开后我们只要关心两个java文件即可:
    1.微信支付配置文件:src/test/java/com/github/wxpay/sdk/WXPayConfigImpl.java
    2.微信支付测试文件:src/test/java/com/github/wxpay/sdk/TestWXPay.java

首先将WXPayConfigImpl中的AppId、mchId、key替换成自己的相关配置,如图所示:



然后打开TestWXPay文件,将doUnifiedOrder函数中notify_url以及openid的map参数替换成自己的,其它参数可以先不更改,具体如图所示:



如果只是测试调用统一下单接口是否能够成功,可以先不更改notify_url。但是必须填入正确的openid,否则将调用失败。接下来将是测试调用统一下单接口是否成功。
    在TestWXPay文件中找到mian函数并运行,将不需要测试的函数注释掉,只保留dodo.doUnifiedOrder()函数,然后等待响应结果,具体如图:



响应结果是一个json字符串,如果调用失败将会返回一些提示信息,如:



这时可以根据提示检查相关参数配置是否有误,下面展示一个调用成功的响应结果:



如出现上图所示,则代表账号以及后台代码没有问题,这时可以进行下一步,在微信浏览器内唤起微信支付。详情参见微信内H5调起支付官方文档,即:将后台成功调用统一下单接口后的返回的各个参数打包传给前端唤起微信支付的js中即可,主要前端代码如下:function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 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{
onBridgeReady();
}将appId等相关配置替换成后台统一下单接口返回的对应参数即可。这里需要注意的一点是:调起微信支付JS代码的环境不能是本地,必须是支付授权目录中JSAPI授权目录中出现的域名环境下调用。否则将无法唤起支付。
四、支付完成
    支付完成后微信支付后台服务器将自动将付款结果发送到用户配置的异步通知url中,即notify_url,因此notify_url也必须是外网可访问的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: