weixinjsbridgeready.invoke( 'getBrandWCPayRequest'报支付失败

微支付无法实现调用JS支付界面
[问题点数:20分,结帖人itcastwenhao]
微支付无法实现调用JS支付界面
[问题点数:20分,结帖人itcastwenhao]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。Java通过JsApi方式实现微信支付
作者:纵酒挥刀斩人头
字体:[ ] 类型:转载 时间:
本文讲解了Java如何实现JsApi方式的微信支付,代码内容详细,文章思路清晰,需要的朋友可以参考下
要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "wx0ec43b",
//公众号名称,由商户传入
"timeStamp":" ",
//时间戳,自1970年以来的秒数
"nonceStr" : "e61463f8efacccfbbb444", //随机串
"package" : "u802345jgfjsdfgsdg888",
"signType" : "MD5",
//微信签名方式:
"paySign" : "70EABB79628FBCAFADD89" //微信签名
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);
onBridgeReady();
以上传入的参数package,即为prepay_id
下面讲的是获得参数来调用jsapi
我们调用JSAPI时,必须获得用户的openid,(trade_type=JSAPI,openid为必填参数。)
首先定义一个请求的对象:
package com.unstoppedable.
import mon.C
import mon.HttpS
import mon.RandomStringG
import mon.S
import java.lang.reflect.F
import java.util.HashM
import java.util.M
public class UnifiedOrderReqData {
private String mch_
private String device_
private String nonce_
private String out_trade_
private String fee_
private int total_
private String spbill_create_
private String time_
private String time_
private String goods_
private String notify_
private String trade_
private String product_
private String limit_
private UnifiedOrderReqData(UnifiedOrderReqDataBuilder builder) {
this.appid = builder.
this.mch_id = builder.mch_
this.device_info = builder.device_
this.nonce_str = RandomStringGenerator.getRandomStringByLength(32);
this.body = builder.
this.detail = builder.
this.attach = builder.
this.out_trade_no = builder.out_trade_
this.fee_type = builder.fee_
this.total_fee = builder.total_
this.spbill_create_ip = builder.spbill_create_
this.time_start = builder.time_
this.time_expire = builder.time_
this.goods_tag = builder.goods_
this.notify_url = builder.notify_
this.trade_type = builder.trade_
this.product_id = builder.product_
this.limit_pay = builder.limit_
this.openid = builder.
this.sign = Signature.getSign(toMap());
public void setAppid(String appid) {
this.appid =
public void setMch_id(String mch_id) {
this.mch_id = mch_
public void setDevice_info(String device_info) {
this.device_info = device_
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_
public void setSign(String sign) {
this.sign =
public void setBody(String body) {
this.body =
public void setDetail(String detail) {
this.detail =
public void setAttach(String attach) {
this.attach =
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_
public void setFee_type(String fee_type) {
this.fee_type = fee_
public void setTotal_fee(int total_fee) {
this.total_fee = total_
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_
public void setTime_start(String time_start) {
this.time_start = time_
public void setTime_expire(String time_expire) {
this.time_expire = time_
public void setGoods_tag(String goods_tag) {
this.goods_tag = goods_
public void setNotify_url(String notify_url) {
this.notify_url = notify_
public void setTrade_type(String trade_type) {
this.trade_type = trade_
public void setProduct_id(String product_id) {
this.product_id = product_
public void setLimit_pay(String limit_pay) {
this.limit_pay = limit_
public void setOpenid(String openid) {
this.openid =
public Map&String, Object& toMap() {
Map&String, Object& map = new HashMap&String, Object&();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
obj = field.get(this);
if (obj != null) {
map.put(field.getName(), obj);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
public static class UnifiedOrderReqDataBuilder {
private String mch_
private String device_
private String out_trade_
private String fee_
private int total_
private String spbill_create_
private String time_
private String time_
private String goods_
private String notify_
private String trade_
private String product_
private String limit_
public UnifiedOrderReqDataBuilder(String appid, String mch_id, String body, String out_trade_no, Integer total_fee,
String spbill_create_ip, String notify_url, String trade_type) {
if (appid == null) {
throw new IllegalArgumentException("传入参数appid不能为null");
if (mch_id == null) {
throw new IllegalArgumentException("传入参数mch_id不能为null");
if (body == null) {
throw new IllegalArgumentException("传入参数body不能为null");
if (out_trade_no == null) {
throw new IllegalArgumentException("传入参数out_trade_no不能为null");
if (total_fee == null) {
throw new IllegalArgumentException("传入参数total_fee不能为null");
if (spbill_create_ip == null) {
throw new IllegalArgumentException("传入参数spbill_create_ip不能为null");
if (notify_url == null) {
throw new IllegalArgumentException("传入参数notify_url不能为null");
if (trade_type == null) {
throw new IllegalArgumentException("传入参数trade_type不能为null");
this.appid =
this.mch_id = mch_
this.body =
this.out_trade_no = out_trade_
this.total_fee = total_
this.spbill_create_ip = spbill_create_
this.notify_url = notify_
this.trade_type = trade_
public UnifiedOrderReqDataBuilder setDevice_info(String device_info) {
this.device_info = device_
public UnifiedOrderReqDataBuilder setDetail(String detail) {
this.detail =
public UnifiedOrderReqDataBuilder setAttach(String attach) {
this.attach =
public UnifiedOrderReqDataBuilder setFee_type(String fee_type) {
this.fee_type = fee_
public UnifiedOrderReqDataBuilder setTime_start(String time_start) {
this.time_start = time_
public UnifiedOrderReqDataBuilder setTime_expire(String time_expire) {
this.time_expire = time_
public UnifiedOrderReqDataBuilder setGoods_tag(String goods_tag) {
this.goods_tag = goods_
public UnifiedOrderReqDataBuilder setProduct_id(String product_id) {
this.product_id = product_
public UnifiedOrderReqDataBuilder setLimit_pay(String limit_pay) {
this.limit_pay = limit_
public UnifiedOrderReqDataBuilder setOpenid(String openid) {
this.openid =
public UnifiedOrderReqData build() {
if("JSAPI".equals(this.trade_type) && this.openid == null) {
throw new IllegalArgumentException("当传入trade_type为JSAPI时,openid为必填参数");
if("NATIVE".equals(this.trade_type) && this.product_id == null) {
throw new IllegalArgumentException("当传入trade_type为NATIVE时,product_id为必填参数");
return new UnifiedOrderReqData(this);
因为有些参数为必填,有些参数为选填。而且sign要等所有参数传入之后才能计算的出,所以这里用了builder模式。关于builder模式。
我们选用httpclient进行网络传输。
import com.thoughtworks.xstream.XS
import com.thoughtworks.xstream.io.xml.DomD
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameC
import mons.logging.L
import mons.logging.LogF
import org.apache.http.HttpE
import org.apache.http.HttpR
import org.apache.http.client.ClientProtocolE
import org.apache.http.client.ResponseH
import org.apache.http.client.config.RequestC
import org.apache.http.client.methods.HttpG
import org.apache.http.client.methods.HttpP
import org.apache.http.conn.ConnectTimeoutE
import org.apache.http.conn.ConnectionPoolTimeoutE
import org.apache.http.conn.ssl.SSLConnectionSocketF
import org.apache.http.conn.ssl.SSLC
import org.apache.http.entity.StringE
import org.apache.http.impl.client.CloseableHttpC
import org.apache.http.impl.client.HttpC
import org.apache.http.util.EntityU
import javax.net.ssl.SSLC
import java.io.F
import java.io.FileInputS
import java.io.IOE
import java.net.SocketTimeoutE
import java.security.KeyS
* Created by hupeng on .
public class HttpService {
private static Log logger = LogFactory.getLog(HttpService.class);
private static CloseableHttpClient httpClient = buildHttpClient();
//连接超时时间,默认10秒
private static int socketTimeout = 5000;
//传输超时时间,默认30秒
private static int connectTimeout = 5000;
private static int requestTimeout = 5000;
public static CloseableHttpClient buildHttpClient() {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(Configure.getCertLocalPath()));//加载本地的证书进行https加密传输
keyStore.load(instream, Configure.getCertPassword().toCharArray());//设置证书密码
} finally {
instream.close();
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray())
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(requestTimeout)
.setSocketTimeout(socketTimeout).build();
httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(sslsf)
return httpC
} catch (Exception e) {
throw new RuntimeException("error create httpclient......", e);
public static String doGet(String requestUrl) throws Exception {
HttpGet httpget = new HttpGet(requestUrl);
logger.debug("Executing request " + httpget.getRequestLine());
// Create a custom response handler
ResponseHandler&String& responseHandler = new ResponseHandler&String&() {
public String handleResponse(
final HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status &= 200 && status & 300) {
HttpEntity entity = response.getEntity();
return entity != null ? EntityUtils.toString(entity) :
throw new ClientProtocolException("Unexpected response status: " + status);
return httpClient.execute(httpget, responseHandler);
} finally {
httpget.releaseConnection();
public static String doPost(String url, Object object2Xml) {
String result =
HttpPost httpPost = new HttpPost(url);
//解决XStream对出现双下划线的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
//将要提交给API的数据对象转换成XML格式数据Post给API
String postDataXML = xStreamForRequestPostData.toXML(object2Xml);
("API,POST过去的数据是:");
(postDataXML);
//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
//设置请求器的配置
("executing request" + httpPost.getRequestLine());
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (ConnectionPoolTimeoutException e) {
logger.error("http get throw ConnectionPoolTimeoutException(wait time out)", e);
} catch (ConnectTimeoutException e) {
logger.error("http get throw ConnectTimeoutException", e);
} catch (SocketTimeoutException e) {
logger.error("http get throw SocketTimeoutException", e);
} catch (Exception e) {
logger.error("http get throw Exception", e);
} finally {
httpPost.abort();
然后是我们的总入口:
package com.unstoppedable.
import mon.C
import mon.HttpS
import mon.XMLP
import com.unstoppedable.protocol.UnifiedOrderReqD
import org.xml.sax.SAXE
import javax.xml.parsers.ParserConfigurationE
import java.io.IOE
import java.util.M
* Created by hupeng on .
public class WxPayApi {
public static Map&String,Object& UnifiedOrder(UnifiedOrderReqData reqData) throws IOException, SAXException, ParserConfigurationException {
String res = HttpService.doPost(Configure.UNIFIED_ORDER_API, reqData);
return XMLParser.getMapFromXML(res);
public static void main(String[] args) throws Exception {
UnifiedOrderReqData reqData = new UnifiedOrderReqData.UnifiedOrderReqDataBuilder("appid", "mch_id", "body", "out_trade_no", 1, "spbill_create_ip", "notify_url", "JSAPI").setOpenid("openid").build();
System.out.println(UnifiedOrder(reqData));
返回的xml为:
&return_code&&![CDATA[SUCCESS]]&&/return_code&
&return_msg&&![CDATA[OK]]&&/return_msg&
&appid&&![CDATA[wx0ec43b]]&&/appid&
&mch_id&&![CDATA[]]&&/mch_id&
&nonce_str&&![CDATA[IITRi8Iabbblz1Jc]]&&/nonce_str&
&sign&&![CDATA[EB8ED0CED72F]]&&/sign&
&result_code&&![CDATA[SUCCESS]]&&/result_code&
&prepay_id&&![CDATA[wx507cbf6ffd8b]]&&/prepay_id&
&trade_type&&![CDATA[JSAPI]]&&/trade_type&
return_code 和result_code都为SUCCESS的时候会返回我们需要的prepay_id。。。,然后在jsapi中使用他就可以了。。
以上就是本文的全部内容,希望对大家的学习有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具微信支付详解 - 微信公众平台开发:微信公众号开发平台教程,技术文摘 - 红黑联盟
微信支付详解
1.为什么会有两种JS方法可以发起微信支付?
当你登陆微信公众号之后,左边有两个菜单栏,一个是微信支付,一个是开发者中心。
在开发者中心中,有一个微信JS-SDK说明文档。
在此说明文档中,有一个发起微信支付的请求API
wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入''
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数
在微信支付菜单栏中,有一个使用教程。里面有一个使用JS API发起支付请求的小菜单。
进入之后,里面一个公众号支付的菜单栏。在里面,有一个H5调起支付API的页面。
它里面发起一个支付的代码是:
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
&appId& : &wx0ec43b&,
//公众号名称,由商户传入
&timeStamp&:& &,
//时间戳,自1970年以来的秒数
&nonceStr& : &e61463f8efacccfbbb444&, //随机串
&package& : &prepay_id=u802345jgfjsdfgsdg888&,
&signType& : &MD5&,
//微信签名方式:
&paySign& : &70EABB79628FBCAFADD89& //微信签名
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);
onBridgeReady();
为什么JS有两种方法可以调起微信支付呢?
我的理解:第一种方法是为了跟其他js API接口统一(里面可以调用很多微信的功能)而提供的。
第二种方法仅仅是针对微信支付这个功能提供的。
也就是说,按照这两种方法来进行微信支付,都是可以的,但是两种方法调用的方式和提供的参数不一样。
2.微信支付有v2和v3版本的区别?
这种区别,是相对于getBrandWCPayRequest方法发起的微信支付。
当你登陆微信公众平台,点击微信支付。如果看到有技术升级的菜单栏,就证明你现在使用的是v2版本,如果你进行技术升级,那么,就会升级到v3版本。
v2版本和v3版本的发起微信支付的方式不一样,因此,如果你之前使用了v2版本进行了微信支付的开发,那么你技术升级到v3版本后,就不能使用原来的v2版本的调用方式了,也就意味着,你的代码需要改动。当然,你不升级的话,是没有问题的。
v3版本比v2版本多了一些功能,比如:红包,券等。
v2版本发起微信支付的方法:
WeixinJSBridge.invoke('getBrandWCPayRequest',{
&appId& : getAppId(), //公众号ID
&timeStamp& : getTimeStamp(), //时间戳,当前系统的时间,具体格式,请看API
&nonceStr& : getNonceStr(), //随机串,具体格式请看API
&package& : getPackage(),//扩展包
&signType& : &SHA1&, //微信签名方式:sha1
&paySign& : getSign() //微信签名
},function(res){
if(res.err_msg == &get_brand_wcpay_request:ok& ) {}
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
//因此微信团队建议,当收到ok返回时,向商户后台询问是否收到交易成功的通知,若收到通知,前端展示交易成功的界面;若此时未收到通知,商户后台主动调用查询订单接口,查询订单的当前状态,并反馈给前端展示相应的界面。
v3版本发起微信支付的方法跟v2的一样,只是参数不一样。
其中,package的值,v3是通过统一接口调用获取到的。
signType,v3使用的是md5方式。
由于微信支付开发教程,已经按照v3版本的方式给出了,所以v2版本,我们就不说了,接下来,我们详细讲解v3版本的开发方式。
3.v3版本开发步骤
想要在前端发起微信支付,就必须有appId,timeStamp,nonceStr,package,signType,paySign这六个参数。
其中,appid,signType已经直接给出了。
timestamp和noncestr,可以根据文档给出的规则算出来。
package是统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***。
所以,我们先来看下如何获得此prepay_id。
我们先去看统一下单接口:
此接口的调用,是通过服务端的代码进行调用的,也就是你的应用服务器,这里我们假设你使用的是java代码。
URL地址:https://api.mch./pay/unifiedorder
请求参数(只考虑必填的)
appid,mch_id,nonce_str,body,out_trade_no,total_fee,notify_url,trade_type,这几个参数,我们可以直接获得。
spbill_create_ip(终端IP)和sign(签名)我们需要采取方式获得。
获取用户的ip地址,前端可以通过以下方式获取,然后传给后台。后台也可以自己获取(对java不熟)。
&script src=&/cityjson?ie=utf-8&&&/script&
var returnCitySN = {&cip&: &210.21.236.135&, &cid&: &440300&, &cname&: &广东省深圳市&};
最后,只剩下sign了。
我们进入到签名算法文档。大家认真仔细的查看此文档,因为此签名算法会使用几次。
此文档中有一个例子,大家按照此例子把自己要请求的参数按照字典序组装起来,最后拼接API秘钥。此秘钥是在商户平台中,账户设置,API安全中自己设置的,此秘钥只能放在服务器端,也就是java代码中,不能进行传输。之前的v2版本,就是放在前端(js代码中的),不安全。
最后,用java代码中的md5方法进行,加密完之后,转化成大写,就得到sign了。
最后,通过java代码,把这些参数组成xml文件发给微信服务器(https://api.mch./pay/unifiedorder)。
如果返回成功,就会得到以下这种形式的数据:
&return_code&&![CDATA[SUCCESS]]&&/return_code&
&return_msg&&![CDATA[OK]]&&/return_msg&
&appid&&![CDATA[wx0ec43b]]&&/appid&
&mch_id&&![CDATA[]]&&/mch_id&
&nonce_str&&![CDATA[IITRi8Iabbblz1Jc]]&&/nonce_str&
&sign&&![CDATA[EB8ED0CED72F]]&&/sign&
&result_code&&![CDATA[SUCCESS]]&&/result_code&
&prepay_id&&![CDATA[wx507cbf6ffd8b]]&&/prepay_id&
&trade_type&&![CDATA[JSAPI]]&&/trade_type&
java代码解析后,把prepay_id返回给前端。
这时,前端要发起微信支付,就只差paySign了。
此paySign,也必须按照签名算法来得到。这里,我们同样在java代码中,按照调起微信支付getBrandWCPayRequest方法的请求参数进行签名算法操作。
这里需要对appId,timeStamp,nonceStr,package,signType这5个请求参数进行组装,然后拼接商户平台秘钥,md5加密,转换成大写,最后返回给前端。
这时,前端就可以调用此接口了。
上面的图,我们省略第二步。
4.按照统一接口实现v3版本的微信支付。
在微信js-sdk中,有详细的说明:所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
这里的参数,我们只有signature不知道。
生成signature之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket&。
参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):../15/54ce45d8d30b6bfe95bc627.
用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api./cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
按照获取access token的文档,我们可以获得
{&access_token&:&ACCESS_TOKEN&,&expires_in&:7200}
此文档很容易看懂,AppID和AppSecret在公众平台可获取。
紧接着第二步,就可以获得:
&errcode&:0,
&errmsg&:&ok&,
&ticket&:&bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA&,
&expires_in&:7200
里面的ticket就是jsapi_ticket。
最后,按照下面的签名算法得到signature。
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2&)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=
url=http://mp.?params=value
步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2&)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&tamp=&url=http://mp.?params=value
步骤2. 对string1进行sha1签名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
签名用的url必须是调用JS接口页面的完整URL。
出于安全考虑,开发者必须在服务器端实现签名的逻辑。
如出现invalid signature 等错误详见附录5常见错误及解决办法。
配置完成之后,我们就可以在下面的函数中调用微信支付接口了。
wx.ready(function(){
  wx.chooseWXPay({
  timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
  nonceStr: '', // 支付签名随机串,不长于 32 位
  package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
  signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
  paySign: '', // 支付签名
  success: function (res) {
  // 支付成功后的回调函数
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
然后,这里的支付签名paySign和package按照前面的方式得来就行了。
总结:如果仅仅是实现微信支付这样的功能,还是参考第三项。因为第四项多了一步,v2版本已经淘汰。
如果需要实现微信支付和其他微信功能,那么参考第四项。
里面的坑很多:记住,参数名的大小写要一致,不管是前端还是后台,在签名时,只要大小写不一致,就会出错。

我要回帖

更多关于 weixinjsbridge api 的文章

 

随机推荐