前面说过微信支付的APP支付,这篇说说JSAPI的支付。
JSAPI支付只能在微信浏览器里面使用,主要用于公众号里面的H5应用的支付。
开发前的准备
微信公众平台:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN
微信商户平台:https://pay.weixin.qq.com/index.php/home/login
开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
公众号支付开发步骤
1、设置测试目录
在微信公众平台设置,栏目见图7.7。支付测试状态下,设置测试目录,测试人的微信号添加到白名单,发起支付的页面目录必须与设置的精确匹配。并将支付链接发到对应的公众号会话窗口中才能正常发起支付测试。注意正式目录一定不能与测试目录设置成一样,否则支付会出错。
图7.7 微信内网页支付设置栏目入口
2、设置正式支付目录
根据图中栏目顺序进入修改栏目,勾选JSAPI网页支付开通该权限,并配置好支付授权目录,该目录必须是发起支付的页面的精确目录,子目录下无法正常调用支付。具体界面如图7.8所示:
图7.8 微信网页内支付接口授权目录设置
再到开发》接口权限》网页服务》网页账号,填上你的网址。如下图:
商户平台有两个账号,一个是用于APP支付的,一个是用于公众号支付的,这里我们需要用公众号的那个。
商户平台有两个东西会用到,一个是Partner ID,就是微信支付商户号;一个是Key,就是对商户平台的登录密码进行MD5加密后得到的字串,到API安全>>API密钥>>设置密钥,把这个MD5字串填进去保存就行了,如下图:
1.生成openid
JsApiPay jsApiPay = new JsApiPay(this);
//调用【网页授权获取用户信息】接口获取用户的openid和access_token
jsApiPay.GetOpenidAndAccessToken();
ViewState["OpenID"] = jsApiPay.openid;
2.发起支付
前台JS代码:
<script type="text/javascript">
var appId = '<%=appId%>';
var prepayId = '<%=prepayId%>';
var nonceStr = '<%=nonceStr%>';
var timeStamp = '<%=timeStamp%>';
var sign = '<%=sign%>';
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": appId, //公众号名称,由商户传入
"timeStamp": timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": nonceStr, //随机串
"package": "prepay_id=" + prepayId,
"signType" : "MD5", //微信签名方式:
"paySign": sign //微信签名
},
function (res) {
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
switch (res.err_msg)
{
case "get_brand_wcpay_request:ok":
alert("支付成功");
break;
case "get_brand_wcpay_request:cancel":
alert("支付取消");
break;
default:
alert("支付失败");
break;
}
}
);
}
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();
}
</script>
后台CS代码:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["openid"] != null)
{
ViewState["OpenID"] = Request.QueryString["openid"];
WxPay();
}
else
{
Response.Redirect("WxPay.aspx");
}
}
protected void btnPay_Click(object sender, EventArgs e)
{
WxPay();
}
public string appId;
public string prepayId;
public string nonceStr;
public string timeStamp;
public string sign;
/// <summary>
/// 支付方法
/// </summary>
private void WxPay()
{
appId = WxPayConfig.APPID;
string partnerId = WxPayConfig.MCHID;
string key = WxPayConfig.KEY;
string body = txtProductName.Text.Trim();
string orderNumber = DateTime.Now.ToString("yyyyMMddHHmmss");
int price = int.Parse(txtPrict.Text.Trim());
UnifiedOrder order = new UnifiedOrder();
order.appid = appId;
order.mch_id = partnerId;
order.nonce_str = TenpayUtil.getNoncestr();
order.body = body;
order.out_trade_no = orderNumber;
order.total_fee = price; //单位是分
order.spbill_create_ip = Page.Request.UserHostAddress;
order.notify_url = "http://www.yourdomain.com/notify.aspx";
order.trade_type = "JSAPI";
if (ViewState["OpenID"] != null)
{
order.openid = ViewState["OpenID"].ToString(); //JSAPI必须传入openid
}
TenpayUtil tu = new TenpayUtil();
prepayId = tu.getPrepay_id(order, key);
nonceStr = order.nonce_str;
timeStamp = TenpayUtil.getTimestamp();
SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add("appId", appId);
sParams.Add("nonceStr", nonceStr);
sParams.Add("package", "prepay_id=" + prepayId);
sParams.Add("signType", "MD5");
sParams.Add("timeStamp", timeStamp);
sign = tu.getsign(sParams, key);
}
这里要注意的是appId、nonceStr这些字段要大小写正确,否则加密会出错导致支付失败。
3.查询订单状态
这个可以参考前面APP支付
4.后台设置
源码下载:http://pan.baidu.com/s/1jHp1s3c