㈠ 微信支付商户签名错误
官方文档内容如下:
备注:prepay_id 通过微信支付统一下单接口拿到,paySign 采用统一的微信支付 Sign 签名生成方版法,注意这里 appId 也要参权与签名,appId 与 config 中传入的 appId 一致,即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。
其实根本不是这么回事,完全是扯犊子,参与签名的参数根本不不上面列出的,
实际的签名字符串应该是:"appId="+appId+"&nonceStr="+noncestr + "&package=prepay_id="+prepay_id+"&signType=MD5&timeStamp="+timestamp+"&key="+key
这里的key是微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
这里设置的密钥。
腾讯他娘的狗屎文档,写得真他娘烂。
㈡ 微信开发者 jssdk怎么使用
、先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
2、页面引入JS:http://res.wx.qq.com/open/js/jweixin-1.0.0.js
3、所有需要使用JS-SDK的页面必须先注入配置信息
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
4、签名算法
生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
㈢ 怎么使用微信JSSDK的自定义分享功能
登录你的微信平台,点击“公众号设置”。
2
点击“功能设置”,然后点击“设置”。
3
设置JS接口安全域名。这里填写的是一级域名,不带www和http。最多可以设置三个域名。设置完后点击确定。(多说一句,相比以前的分享没有任何域名限制,这里设置安全域名,目的是为了当发现此公众平台发现诱导分享行为时,可以根据此域名追溯到所有分享出去的链接,以及通过这些链接增加的粉丝。这样,微信就可以牢牢控制了你的微信平台,一旦发现违规,让分享链接失效,删除掉诱导行为增加的粉丝,是瞬间就可以完成的。因此,微信平台的开发者,一定要合理来使用分享功能,不要因小失大。等到你的微信平台被封,估计哭都来不及)
4
在开发者中心中获取你的AppID和AppSecret,接下来在获取令牌时,需要这两个信息。
5
获取令牌。在服务器端完成,代码如下:
function wx_get_token() {
$token = S('access_token');
if (!$token) {
$res = file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' .'你的AppID'.'&secret=' .'你的AppSecret');
$res = json_decode($res, true);
$token = $res['access_token'];
// 注意:这里需要将获取到的token缓存起来(或写到数据库中)
// 不能频繁的访问https://api.weixin.qq.com/cgi-bin/token,每日有次数限制
// 通过此接口返回的token的有效期目前为2小时。令牌失效后,JS-SDK也就不能用了。
// 因此,这里将token值缓存1小时,比2小时小。缓存失效后,再从接口获取新的token,这样
// 就可以避免token失效。
// S()是ThinkPhp的缓存函数,如果使用的是不ThinkPhp框架,可以使用你的缓存函数,或使用数据库来保存。
S('access_token', $token, 3600);
}
return $token;
}
注意:返回的access_token长度至少要留够512字节。接口返回值:
{"access_token":"ACCESS_TOKEN","expires_in":7200}
{"access_token":"vdlThyTfyB0N5eMoi3n_aMFMKPuwkE0MgyGf_0h0fpzL8p_-0kVHY33BykRC0YXZZZ-WdxEic4","expires_in":7200}
6
获取jsapi的ticket。jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。
function wx_get_jsapi_ticket(){
$ticket = "";
do{
$ticket = S('wx_ticket');
if (!empty($ticket)) {
break;
}
$token = S('access_token');
if (empty($token)){
wx_get_token();
}
$token = S('access_token');
if (empty($token)) {
logErr("get access token error.");
break;
}
$url2 = sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi",
$token);
$res = file_get_contents($url2);
$res = json_decode($res, true);
$ticket = $res['ticket'];
// 注意:这里需要将获取到的ticket缓存起来(或写到数据库中)
// ticket和token一样,不能频繁的访问接口来获取,在每次获取后,我们把它保存起来。
S('wx_ticket', $ticket, 3600);
}while(0);
return $ticket;
}
接口返回值:
{"errcode":0,"errmsg":"ok","ticket":"-I98-_YWtOQg","expires_in":7200}
7
签名,将jsapi_ticket、noncestr、timestamp、分享的url按字母顺序连接起来,进行sha1签名。
noncestr是你设置的任意字符串。
timestamp为时间戳。
$timestamp = time();
$wxnonceStr = "任意字符串";
$wxticket = wx_get_jsapi_ticket();
$wxOri = sprintf("jsapi_ticket=%s&noncestr=%s×tamp=%s&url=%s",
$wxticket, $wxnonceStr, $timestamp,
'要分享的url(从http开始,如果有参数,包含参数)'
);
$wxSha1 = sha1($wxOri);
END
步骤2 添加JS代码
生成签名后,就可以使用js代码了。在你的html中,进行如下设置即可。
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script type="text/javascript">
// 微信配置
wx.config({
debug: false,
appId: "你的AppID",
timestamp: '上一步生成的时间戳',
nonceStr: '上一步中的字符串',
signature: '上一步生成的签名',
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 功能列表,我们要使用JS-SDK的什么功能
});
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在 页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready 函数中。
wx.ready(function(){
// 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
wx.onMenuShareTimeline({
title: '分享标题', // 分享标题
link:"分享的url,以http或https开头",
imgUrl: "分享图标的url,以http或https开头" // 分享图标
});
// 获取“分享给朋友”按钮点击状态及自定义分享内容接口
wx.onMenuShareAppMessage({
title: '分享标题', // 分享标题
desc: "分享描述", // 分享描述
link:"分享的url,以http或https开头",
imgUrl: "分享图标的url,以http或https开头", // 分享图标
type: 'link', // 分享类型,music、video或link,不填默认为link
});
});
</script>
㈣ 小程序webview(H5)调用JSSDK功能指北
最核心的一个概念 :
小程序 的webview(H5页面)中调用jssdk中的功能(比如获取位置信息),需要有一个和小程序申请主体一致的 公众号 账号,在公众号里去配置相关的jssdk信息.
1 小程序账号
因为webview不支持个人类型,所以需要申请一个企业法人及个体工商户类型的小程序账号
2 公众号账号
要求小程序和公众号的账号对应的主体信息必须一致,有两种途径达到此目的:
先申请公众号账号,然后通过公众号的快速生成小程序功能,生成步骤1的小程序账号,这样这两个自然满足同主体资格
登录微信公众号平台,点击小程序管理-添加-快速注册并认证小程序:
用和申请小程序账号完全一致的主体信息去申请公众号(主体类型,主体名称,主体证件号),也能保证两个账号的主体资格一致(目前没有小程序快速生成公众号账号的功能..)
3 域名绑定
这里需要两个账号都配置一下:
业务域名
首先webview指向一个外部网页链接(我们的H5页面)
<web-view src="https://abc.xxx.com.cn/cc/index.html"></web-view>
这个地址要满足:
已经通过ICP备案域名
https协议
不支持自定义端口
不支持ip地址
不支持短链域名
那么首先要在 小程序 中的'开发'-'开发设置'的'业务域名'中,将https://abc.xxx.com.cn配置进去:
JS接口安全域名
在上述h5页面中,因为要调用jssdk的js文件:
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
因此要在公众号设置”的“功能设置”里填写“JS接口安全域名”
注意 :以上两个配置地址时,都需要将配置时提供的一个文本文件按照要求上传到H5页面所在服务器并确保能被访问,用于腾讯验证服务器,否则是无法提交相关信息的
4 应用
jssdk提供了很多功能,但是webview中,只支持部分接口,自行查看web-view,这里以获取位置信息为例:
通过config接口注入权限验证配置
所有需要使用JSSDK的页面必须先注入配置信息,否则将无法调用:
wx.config({
appId: '', // 必填,公众号的appid,注意不是小程序的appid
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
debug: true, // 选填,开启调试模式,调用的所有api的返回值会在客户端alert出来。
jsApiList: ['getLocation'] // 必填,需要使用的JS接口列表,这里为获取位置信息
});
以上参数除了最后两个,建议在后台服务中存储和计算,具体需参考jssdk,主要思路:
利用公众号的 appid 和 secret 去获取 access_token
利用 access_token 去获取 ticket
利用ticket和自行生成的( timestamp , nonceStr ,当前页面的 地址 )计算出最终的 签名
执行getLocation
以上步骤执行成功后,方可执行wx.getLocation:
var success=true
// 之所以这里有个success变量,是因为发现wx.error触发也会调用wx.ready(如果有个wx.success就好了)
//但其实这并不完美,因为还发现有时候wx.ready先执行,然后触发了wx.error ........
wx.ready(function(){
if(success){
wx.getLocation({
type: 'wgs84',
success(res) {
// res为坐标位置信息
},
fail(e) {
// 获取失败
}
})
}
// config信息验证后会执行ready方法
});
wx.error(function(res){
success=false
// config信息验证失败会执行error函数
});
吐槽:
wx.config有时候成功,有时候说签名失败
wx.ready代表配置验证完毕了,不代表验证成功了,那他的意义在于什么
reference:
jssdk: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
web-view: https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html
㈤ 关于微信支付遇到的哪些坑
最近在研究微信支付,感觉在微信里面买东西,直接微信支付还是蛮方便的,没有支付宝那么麻烦,刷刷朋友圈,顺便就买点东西,生活是如此的惬意,心想微信的这个支付肯定可以做到很牛逼,因为“钱景”无限啊!于是,我开始了这个噩梦般的旅程。
开通和审核
微信支付和支付宝商家平台一样,都是要审核资质的,支付宝个人认证可以使用担保支付,虽然需要用户确认收货之后才能收到资金,但是好歹也是能用的。微信直接不让个人使用支付。只有企业以上级别的服务号才能申请。
开通&认证
支付宝注册企业账号,进行企业认证,我总共就花了10分钟,包括公司资质审核,打款到公账确认公账等步骤。效率高到简直无法想象。 微信支付需要已经认证过的服务号才能开通支付。提交完资质,等待审核,花了5个工作日的时间才告诉我资质审核过了,对,没错,是5个工作日,中间隔了一个周末,微信称2-7个工作日认证完成,还是实现诺言了。
开通支付
支付宝需要签约服务,这里我签约的是即时到帐的,花了2天时间。 微信开通认证之后,登陆商户平台配置一下就可以开干了,这点从速度方面比支付宝强点,因为它把支付用途啥的都放到第一步的认证里面了,而支付宝是放在后面的签约服务里面进行审核的。
这些步骤完成之后,就可以开始开发了。虽然如此,从整体进度上面,支付宝还是略胜微信一筹的。
开发
根据文档接入支付宝和微信的支付平台
文档&DEMO
支付宝我就没看文档,因为之前有做过,已经大体了解了。直接下了个DEMO改改就完成了。 微信的文档,恩,在微信公众平台有一份,在商户平台又有另外一份,而且内容还不一样。。。 我主要需要在公众号里面支付,所以选择了微信的JSAPI。在公众平台里面,关于JS支付的只有一小段。如下:
wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数
}
});
备注:prepay_id 通过微信支付统一下单接口拿到,paySign 采用统一的微信支付 Sign 签名生成方法,注意这里 appId 也要参与签名,appId 与 config 中传入的 appId 一致,即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。
微信支付统一下单接口文档:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1
微信支付签名算法:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3
微信支付开发教程:https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN
看完方法,有点晕,在看完下面给出的三个链接里面的内容,更晕了。然后又在商户平台找到一份文档。
传送门
这里给了比较详细的资料,也给出了js示例:
注:JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":" 1395712654", //时间戳,自1970年以来的秒数
"nonceStr" : "", //随机串
"package" : "prepay_id=u802345jgfjsdfgsdg888",
"signType" : "MD5", //微信签名方式:
"paySign" : "" //微信签名
},
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();
}
恩,于是我结合了文档和找到的demo,结合这一段内容开始测试,结果发现,完全没反应。是的,在我的iPhone上面是没有反应的,也许哪里出了问题,一直搞不出反应。 然后我想到了前面还有一种chooseWXPay,搜索了一下,这是新版接口的方法。结合下面的文档参数的计算,成功了。结果是这样的
wx.chooseWXPay({
appId: '{{ $jsParameters['appId'] }}',
timestamp: '{{ $jsParameters['timeStamp'] }}', // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '{{ $jsParameters['nonceStr'] }}', // 支付签名随机串,不长于 32 位
package: '{{ $jsParameters['package'] }}', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: '{{ $jsParameters['signType'] }}', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '{{ $jsParameters['paySign'] }}', // 支付签名
success: function (res) {
if(res.errMsg == "chooseWXPay:ok" ) {
//支付成功
}else{
alert(res.errMsg);
}
},
cancel:function(res){
//支付取消
}
});
这里的$jsParameters是在后台使用微信支付的DEMO里面提供的class生成的。
include_once("WxPayPubHelper.php");
...
public function getParameters(Order $order)
{
$jsApi = new JsApi_pub();
$unifiedOrder = new UnifiedOrder_pub();
//$unifiedOrder->setParameter("detail", $this->order->proct->brief_desc);//商品描述
$unifiedOrder->setParameter("body", $order->proct->name);//商品描述
$unifiedOrder->setParameter("out_trade_no", $order->order_number);//商户订单号
$unifiedOrder->setParameter("total_fee", $order->price * 100);//总金额,腾讯默认支付金额单位为【分】
$unifiedOrder->setParameter("notify_url", WxPayConf_pub::NOTIFY_URL);//通知地址
$unifiedOrder->setParameter("trade_type", "JSAPI");//交易类型
//非必填参数,商户可根据实际情况选填
$unifiedOrder->setParameter("openid", Auth::user()->wx_openid);//商品ID
$unifiedOrder->setParameter("proct_id", $order->proct->id);//商品ID
$prepay_id = $unifiedOrder->getPrepayId();
$jsApi->setPrepayId($prepay_id);
return $jsApi->getParameters();
}
我描述你一脸啊,明显第一个是用户openid
还有这个
支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
你很难搞清楚啥时候改用大写,啥时候该用小写。
还有这个
备注:prepay_id 通过微信支付统一下单接口拿到,paySign 采用统一的微信支付 Sign 签名生成方法,注意这里 appId 也要参与签名,appId 与 config 中传入的 appId 一致,即最后参与签名的参数有appId, timeStamp, nonceStr, package, signType。
就是在调用chooseWXPay的时候,你要自己加上appId,注意,I是大写。否则采用JSAPI方式的时候会提示出错。
还有这个
注:JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}
老版的接口里面是这样描述返回结果的。但是在新版里面变了,是变了,但是满世界找不到变成啥样了。只能自己打出来测试,结果变成如下
success: function (res) {
if(res.errMsg == "chooseWXPay:ok" ) {
//支付成功
...
新版接口里面取消是没有反应的,因为只有success回调。没有任何一个地方说了如何监听用户取消支付。只能自己猜,结果,我果然猜对了。
success: function (res) {
if(res.errMsg == "chooseWXPay:ok" ) {
//支付成功
}else{
alert(res.errMsg);
}
},
cancel:function(res){
//支付取消
}
你以为是res.errMsg == "chooseWXPay:cancel"吗?骚年,你还是太年轻。
设置坑
1、要设置好安全支付目录。这个啥意思?
1、所有使用JS API方式发起支付请求的链接地址,都必须在支付授权目录之下;
2、最多设置3个支付授权目录, 且域名必须通过ICP备案;
3、头部要包含http或https,须细化到二级或三级目录,以左斜杠“/”结尾。
修改会影响线上交易,距正式生效有十分钟左右延迟,建议你避开交易高峰时间修改
就是说,你将要调用JSAPI的那个页面的链接要在这个目录之下才可以。否则,会弹出提示说你的目录没权限。比如你调用JSAPI的页面地址为
http://www.xx.oo/pay/order/1
那么你要把安全目录设置为
http://www.xx.oo/pay/order/
这样设置之后,如果你在如下地址调用,则会报错
http://www.xx.oo/pay/newOrder/1
你可以设置多个支付目录,如果需要的话。
2、设置回调地址,这个不解释。
3、设置警告地址,不解释。
4、商户平台里面设置密钥,在登录了商户平台之后,位于账户设置-API安全里面,先装数字证书,然后设置密钥,32位字符串。设置完了,自己记下来,没错,要自己记下来,因为没法再查看了。
㈥ 微信朋友圈JSSDK分享自定义图片文字
1、在微信公众号添加安全域名(制作的H5页面的主域名);
测试阶段,本人是通过修改hosts文件,将对应域名解析为127.0.0.1 ; 然后将电脑和手机连接至同个局域网下。修改手机代理为电脑在局域网内的IP地址;这样手机就能正常进行测试;
2、引入jssdk script src='http://res.wx.qq.com/open/js/jweixin-1.0.0.js'
3、配置jssdk,成功后方可使用相关功能,方式如下
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'XX', // 必填,公众号的唯一标识
timestamp: XX, // 必填,生成签名的时间戳
nonceStr: xx, // 必填,生成签名的随机串
signature: xx, // 必填,签名,见附录1
jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
第一次接触时看到网上的文章在此对signature没有过多的说明,这里我自己大概说一下,此参数是通过获取公众号的id及secret获取 access _token,然后通过 access _token获取jsapi_ticket,然后通过时间戳,随机串,当前页面url,通过sha1加密生成;(这里做下说明,此步骤由后台处理后返回给前端即可);
刚接触的时候领导认为纯前端可实现,这。。。确实可以实现,这里就不做过多说明了;至于要后端处理的原因大致为两点1、公众号id和secret在前端实现不安全 2、 access _token和jsapi_ticket每日有请求次数的限制,过期时间两小时,所以需要后台在服务器缓存,每两小时获取一次;
4、wx.config配置正确即可通过wx.ready来调用相应功能
wx.ready(function() {
wx.onMenuShareTimeline({ //分享朋友圈
title: 'X', // 分享标题
link: window.location.href, // 分享链接
imgUrl: url, // 分享图标
success: function() {
// 用户确认分享后执行的回调函数
console.log('分享成功了哟哟哟')
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
});
wx.onMenuShareAppMessage({ // 好友分享
title: '', // 分享标题
desc: '', // 分享描述
link: window.location.href, // 分享链接
imgUrl: '', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
总结:其实对于前端要处理的很少,只要从后台获取signature签名,调用方法即可实现;具体可看官方文档;首次接触的小伙伴不要被吓到,就是如此简单;