您的位置:首页 > 编程语言 > ASP

微信支付(公众号支付)ASP.NET

2017-08-01 11:22 316 查看
微信公众号支付官方文档

目录:

步骤1

步骤2

步骤3

步骤4

步骤5

步骤6

步骤7

交互细节

官方流程图

简单流程图

代码
商品选择页面 Productaspx

支付页面 PayPage

场景介绍

商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程。

步骤(1):

商户下发图文消息或者通过自定义菜单吸引用户点击进入商户网页(商户网页下单)。


步骤(2):

进入商户网页,用户选择购买,完成选购流程(请求微信支付)。




步骤(3):

调起微信支付控件,用户开始输入支付密码。


步骤(4):

密码验证通过,支付成功。商户后台得到支付成功的通知。




步骤(5):

返回商户页面,显示购买成功。该页面由商户自定义。


步骤(6):

微信支付公众号下发支付凭证。


步骤(7):

商户公众号下发消息,提示发货成功。该步骤可选。




注意:商户也可以把商品网页的链接生成二维码,用户扫一扫打开后即可完成购买支付。

交互细节:

以下是支付场景的交互细节,请认真阅读,设计商户页面的逻辑:

(1)用户打开商户网页选购商品,发起支付,在网页通过JavaScript调用getBrandWCPayRequest接口,发起微信支付请求,用户进入支付流程。

(2)用户成功支付点击完成按钮后,商户的前端会收到JavaScript的返回值。商户可直接跳转到支付成功的静态页面进行展示。

(3)商户后台收到来自微信开放平台的支付成功回调通知,标志该笔订单支付成功。

注:(2)和(3)的触发不保证遵循严格的时序。JS API返回值作为触发商户网页跳转的标志,但商户后台应该只在收到微信后台的支付成功回调通知后,才做真正的支付成功的处理。

官方流程图



简单流程图:

Created with Raphaël 2.1.0开始用户打开公众号内的链接选择购买产品触发按钮发起支付进行一次AJAX请求,将数据提交到后台提交成功?转到支付页面支付页面通过JavaScript调用getBrandWCPayRequest接口,发起支付,用户输入支付密码支付成功?密码验证通过,提示支付成功。点击完成按钮,商户前端getBrandWCPayRequest接口的回调函数内会收到支付成功返回参数因为微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。所以我们进行一次AJAX请求一般处理程序,使用微信订单号,调用查询订单接口,保证此订单真正交易成功真正成功?转到自定义成功提示页面咨询微信官方不通过,微信自身提示密码错误yesnoyesnoyesno

代码:

商品选择页面 Product.aspx

function checkForm() {
var d = document, n, c, validn, validc, obj = {}, mobile = /^1[3|4|5|8|7][0-9]\d{4,8}$/;
n = d.getElementById('tbcarnum').value;
c = d.getElementById('tbcontact').value;
validn = d.getElementById('validnum');
validc = d.getElementById('validcon');
if (n === '') { validn.innerHTML = '必填'; return false; }
else { validn.innerHTML = ''; }
if (c === '') { validc.innerHTML = '必填'; return false; }
else { validc.innerHTML = ''; }
if (c.length != 11 || !mobile.test(c)) {
validc.innerHTML = '联系方式格式不正确'; return false;
}
else { validc.innerHTML = ''; }
//go
obj.num = n;
obj.con = c;
obj.type = document.getElementById('hid').value;
//创建订单
$.post("ashx/CreateOrder.ashx", obj, function (data) {
var json = JSON.parse(data);
if (json.code === 200) {//成功则转到支付页面
location.href = "paypage.aspx";
} else {
alert('提交失败');
}
});
}


支付页面 PayPage

网页授权获取过程

微信网页授权

以下代码DEMO 内是有的,在此我只是做了略微修改

SDK与DEMO下载

实例化 JsApiPay 类,需要一个 web 窗体作为参数。

PayPage.cs

public string jsapiparms = "";
public string wxorder = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
JsApiPay payObj = new JsApiPay(this);
// 网页授权获取
payObj.GetOpenidAndAccessToken();
//统一下单
WxPayData order = payObj.GetUnifiedOrderResult();
//微信商户订单号
wxorder = payObj.wx_ordernum;
//jsapi支付所需的参数
jsapiparms = payObj.GetJsApiParameters();
}
}


PayPage.aspx

<script type="text/javascript">
function onBridgeReady() {
WeixinJSBridge.invoke('getBrandWCPayRequest', <%=jsapiparms %>, function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
<!--调起查询订单接口,查询订单是否真正交易成功-->
$.post('ashx/CheckOrderStatus.ashx',{onum:'<%=wxorder %>'},function(data){
var json=JSON.parse(data);
if(json.code===200){
document.getElementById('status').innerHTML=json.res;
}else{
alert(json.res);
}
// 转到自定义成功页面
window.location.href=json.url;
});
}     // 使用以上方式判断前端返回,微信团队郑重提示: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();
}
</script>


第一步:利用url跳转获取code

/**
*
* 网页授权获取用户基本信息的全部过程
* 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* 第一步:利用url跳转获取code
* 第二步:利用code去获取openid和access_token
*
*/
public void GetOpenidAndAccessToken()
{
if (!string.IsNullOrEmpty(page.Request.QueryString["code"]))
{
//获取code码,以获取openid和access_token
string code = page.Request.QueryString["code"];
Log.Debug(this.GetType().ToString(), "Get code : " + code);
// 利用code去获取openid和access_token
GetOpenidAndAccessTokenFromCode(code);
}
else
{
//构造网页授权获取code的URL
string host = page.Request.Url.Host;
string path = page.Request.Path;
string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
WxPayData data = new WxPayData();
data.SetValue("appid", WxPayConfig.APPID);
Log.Info("redirect_url:", redirect_uri);
data.SetValue("redirect_uri", redirect_uri);
data.SetValue("response_type", "code");
data.SetValue("scope", "snsapi_base");
data.SetValue("state", "STATE" + "#wechat_redirect");
string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url);
try
{
//触发微信返回code码
page.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常
}
catch (System.Threading.ThreadAbortException ex)
{
}
}
}


第二步:利用code去获取openid和access_token

/**
*
* 通过code换取网页授权access_token和openid的返回数据,正确时返回的JSON数据包如下:
* {
*  "access_token":"ACCESS_TOKEN",
*  "expires_in":7200,
*  "refresh_token":"REFRESH_TOKEN",
*  "openid":"OPENID",
*  "scope":"SCOPE",
*  "unionid": "xxxxxxxxxxxxxxxxxxxxxxxxx"
* }
* 其中access_token可用于获取共享收货地址
* openid是微信支付jsapi支付接口统一下单时必须的参数
* 更详细的说明请参考网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* @失败时抛异常WxPayException
*/
public void GetOpenidAndAccessTokenFromCode(string code)
{
try
{
//构造获取openid及access_token的url
WxPayData data = new WxPayData();
data.SetValue("appid", WxPayConfig.APPID);
data.SetValue("secret", WxPayConfig.APPSECRET);
data.SetValue("code", code);
data.SetValue("grant_type", "authorization_code");
string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl();

//请求url以获取数据
string result = HttpService.Get(url);

Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result);

//保存access_token,用于收货地址获取
JsonData jd = JsonMapper.ToObject(result);
access_token = (string)jd["access_token"];

//获取用户openid
openid = (string)jd["openid"];

Log.Debug(this.GetType().ToString(), "Get openid : " + openid);
Log.Debug(this.GetType().ToString(), "Get access_token : " + access_token);
}
catch (Exception ex)
{
Log.Error(this.GetType().ToString(), ex.ToString());
throw new WxPayException(ex.ToString());
}
}


第三步:调用统一下单接口

/**
* 调用统一下单,获得下单结果
* @return 统一下单结果
* @失败时抛异常WxPayException
*/
public WxPayData GetUnifiedOrderResult(string proname)
{
//统一下单
WxPayData data = new WxPayData();
data.SetValue("body", proname);
data.SetValue("attach", proname);
string order = WxPayApi.GenerateOutTradeNo();
data.SetValue("out_trade_no", order);
//自定义属性,保存微信订单号
wx_ordernum = order;
Log.Info("order", order);

data.SetValue("total_fee", total_fee);
data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
data.SetValue("goods_tag", proname);
data.SetValue("trade_type", "JSAPI");
data.SetValue("openid", openid);

WxPayData result = WxPayApi.UnifiedOrder(data);
if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
{
Log.Error(this.GetType().ToString(), "UnifiedOrder response error!");
throw new WxPayException("UnifiedOrder response error!");
}

unifiedOrderResult = result;
return result;
}


第四步:从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数

/**
*
* 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数,
* 微信浏览器调起JSAPI时的输入参数格式如下:
* {
*   "appId" : "wxxxxxxxxxxxxxxxxxx",     //公众号名称,由商户传入
*   "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数
*   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串
*   "package" : "prepay_id=xxxxxxxxxxxxxxxxxxxx",
*   "signType" : "MD5",         //微信签名方式:
*   "paySign" : "xxxxxxxxxxxxxxxxxxxxx" //微信签名
* }
* @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用
* 更详细的说明请参考网页端调起支付API:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
*
*/
public string GetJsApiParameters()
{
Log.Debug(this.GetType().ToString(), "JsApiPay::GetJsApiParam is processing...");

WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
jsApiParam.SetValue("signType", "MD5");
jsApiParam.SetValue("paySign", jsApiParam.MakeSign());

string parameters = jsApiParam.ToJson();

Log.Debug(this.GetType().ToString(), "Get jsApiParam : " + parameters);
return parameters;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息