开通JSAPI支付产品
首先要申请成为 微信支付商户
,成功后在管理后台开通微信支付中具体支付产品如 JSAPI
支付产品,默认(似乎)是开通的。
将支付商户与公众号关联
拥有支付功能的商户需要与某公众号关联,才能互相获取相应权限和数据,如支付需要通过关联的公众号获取用户 openid
。进入商户后台 APPID授权管理
页面,新增提交要关联某公众号申请,需要输入的 APPID
要从被关联的公众号处获得。申请提交后该公众号在 微信支付 商户号管理 待关联商户号
处进行确认授权。
成功关联商户号后,可以实现在当前小程序中使用微信支付收款,营销等相关功能的需求。点击查看指引
一通配置( !!-- )
管理后台配置
- 支付授权目录
进入商户后台 开发配置 支付配置
,新增 公众号支付
的支付授权目录,该目录是商家的后台(开发)服务也就是向微信支付发起请求的服务器的程序运行目录,支持路径,但似乎不支持自定义端口。按网文介绍,必须设置为接口所在目录,即如果接口完整路径为 http://domain/wxpay/jsapi.php
那该目录应该被设置为 http://domain/wxpay/
而不应该是其它任何形式
- 公众号接口权限
进入公众号后台,进入 设置 公众号设置 功能设置 网页授权域名
,将网页授权域名按官方指导设置为开发服务器上能获取微信用户 openid
的域名,也就是微信授权数据回调要访问的域名,只有先在微信这儿登了记的域名微信才会传数据,相当于白名单。本例中,将目录设置为 wxpay.txxxt.com
,并将该页面中微信提供的验证文件按要求放到目录下,即可正确设置。可以通过查看 开发 接口权限 网页授权获取用户基本信息
的显示结果判断是否设置完毕。
用于开发调试的微信号要关注该公众号
绑定开发人员微信号
进入该公众号的管理后台,开发 开发者工具 web开发者工具
页面中,点击 绑定开发者微信号
将关注了该公众号的开发所用的微信号添加到列表中,在使用 web开发者工具
时用被绑定的微信号登录开发者工具,将可以获取到相关数据,如 openid
,否则无法获取,因为公众号不认识当前调用它的人。
开发环境准备
Web(H5+后端接口)可以使用任何习惯的工具开发即可
下载
微信web开发者工具
如果涉及到微信Api调用(访问微信服务器)的,均需使用 微信web开发者工具
的公众号网页调试打开运行,不能使用普通浏览器。因为 开发者工具
具有普通浏览器没有的微信Api特性。
- 微信的商户后台、公众号后台都有很多白名单的配置,而且这白名单通常有必须是备案域名、仅支持80端口之类的限制,本例尝试选用一款内网穿透的代理工具比如
花生壳
。将工具所产生的外网地址提交给后台配置,本机运行代理工具,即可把对该地址的访问“转接”到本地。但有一个问题就是此类工具通常会使用非80端口,因此不能完美解决所有后台配置问题。因此本例中最终也没能用此方式解决,而是将代码上传到了服务器wxpay.txxxt.com
运行。
开发实践
第一步,用户同意授权,获取 code
code
是用来取得openid
的钥匙,先访问微信指定的api取得code
,再拿code
去换取openid
是第一步要做的事情。
获取 code
只需按照微信给出的固定访问方式,拼接参数,请求指定接口,如无错误即可获得,详见下
这是微信的“标准”接口,我们需要处理里边几个参数
- appid,必填,公众号APPID值,在
微信公众平台 基本配置 公众号开发信息 开发者ID(APPID)
处获取 - redirect_uri,必填,urlencode处理,如参数无误微信接口将跳转回调此地址,并附带上结果参数,详见下方
返回值
说明 - response_type,必填,返回类型,固定填写字符串
code
- scope,必填,应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
- state,选填,开发者自定义参数,可以填写a-zA-Z0-9,最多128字节,重定向后会带上
- #wechat_redirect,必填,无论直接打开还是做页面302重定向,必须带此参数
按微信要求,除参数名和参数值要正确填写外,顺序也不可更改,否则请求将失败,见下例
//header('content-type:application:json;charset=utf8');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:GET');
header('Content-type: text/html; charset=utf-8');
$appId = ""; // 此处填写公众号 appid
$redirectUrl = "http://wxpay.txxxt.com/jsapi/openIdRedirect.php"; //此处填写回调地址
$state = strval(time()); // 模拟自定义 state 参数
$baseUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?";
//拼接字符串得到完整接口地址,要保证参数顺序与官方一致
$requestUrl = $baseUrl;
$requestUrl = $requestUrl."appid=".$appId;
$requestUrl = $requestUrl."&redirect_uri=".urlencode($redirectUrl);
$requestUrl = $requestUrl."&response_type=code&scope=snsapi_base"; // 不调用授权页的方式
$requestUrl = $requestUrl."&state=".$state;
$requestUrl = $requestUrl."#wechat_redirect";
header("Location: $requestUrl"); //返回并直接跳转到拼接完成的接口地址去
exit();
看一个拼接好的地址样例
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxcc70xxxxxxxxxxbbf&redirect_uri=http%3A%2F%2Fwxpay.txxxt.com%2Fjsapi%2FopenIdRedirect.php&response_type=code&scope=snsapi_base&state=1561360134#wechat_redirect
返回值说明:
接口访问成功的话,微信会根据 redirect_uri
回调这样的完整地址
http://wxpay.txxxt.com/jsapi/openIdRedirect.php?code=081vlfXQ11LXM11TiPTQ19n7XQ1vlfXq&state=xxxxxx
刚才准备好了请求的动作,现在要根据返回值接收回调的动作,详见下
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:GET');
header('Content-type: text/html; charset=utf-8');
$code = isset($_GET['code']) ? $_GET['code'] : "";
$state = isset($_GET['state']) ? $_GET['state'] : "";
if($code == ""){
echo("获取失败,人家没给有效的 code");
} else {
echo("获取成功,拿到了 code");
}
处理回调的核心逻辑其实很简单,就是判断 code
的有效性,有值就对了,否则就参照官方文档的错误码检查问题原因