1,下载盛派代码
https://github.com/JeffreySu/WeiXinMPSDK
2,使用OAuth2.0 方式 获取 Openid
a,获取 微信公众号里配置的 回调url (url 中会带有我们所需要的code)
///
/// 获取验证地址
///
/// 公众号的唯一标识
/// 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
/// 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
/// 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
/// 返回类型,请填写code(或保留默认)
/// 加上后可以解决40029-invalid code的问题(测试中)
///
public static string GetAuthorizeUrl(string appId, string redirectUrl, string state, OAuthScope scope, string responseType = "code", bool addConnectRedirect = true)
{
var url =
string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}{5}#wechat_redirect",
appId.AsUrlData(), redirectUrl.AsUrlData(), responseType.AsUrlData(), scope.ToString("g").AsUrlData(), state.AsUrlData(),
addConnectRedirect ? "&connect_redirect=1" : "");
/* 这一步发送之后,客户会得到授权页面,无论同意或拒绝,都会返回redirectUrl页面。
* 如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。这里的code用于换取access_token(和通用接口的access_token不通用)
* 若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
*/
return url;
}
(注:scope 枚举值是snsapi_userinfo弹出授权页面,snsapi_base 不弹出授权页面。 redirectUrl 是用户在公众号后台设置的回调页面的地址。 盛派SDK代码在 Senparc.Weixin.MP.AdvancedAPIs.OAuthApi.GetAuthorizeUrl)
b,在你设置的回调页面中获取 code( 如:string code=request["code"])通过code 获得 微信 回传的信息 从中获取 openid 并将 openid存在session中 (此操作一般在回调页面中)
///
/// 获取AccessToken
///
/// 公众号的唯一标识
/// 公众号的appsecret
/// code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
/// 填写为authorization_code(请保持默认参数)
///
public static OAuthAccessTokenResult GetAccessToken(string appId, string secret, string code, string grantType = "authorization_code")
{
var url =
string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type={3}",
appId.AsUrlData(), secret.AsUrlData(), code.AsUrlData(), grantType.AsUrlData());
return CommonJsonSend.Send
}
(注 盛派SDK代码在 Senparc.Weixin.MP.AdvancedAPIs.GetAccessToken 得到一个 回传信息的数据对象 OAuthAccessTokenResult 里面有 openid 和 Token)
3,填充数据向微信发送支付请求
var timeStamp = TenPayV3Util.GetTimestamp();
var nonceStr = TenPayV3Util.GetNoncestr();
var body = product == null ? "test" : product.Name;
var price = product == null ? 100 : (int)product.Price * 100;
var xmlDataInfo = new TenPayV3UnifiedorderRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, body, sp_billno, price, Request.UserHostAddress, TenPayV3Info.TenPayV3Notify, TenPayV3Type.JSAPI, openIdResult.openid, TenPayV3Info.Key, nonceStr);
var result = TenPayV3.Unifiedorder(xmlDataInfo);//调用统一订单接口
(注:因为采用的是 TenPayV3Type.JSAPI 方式进行支付所以openid 必填)
4,前端js 调用 微信支付
a,为js 提供数据
var package = string.Format("prepay_id={0}", result.prepay_id); 回传数据中获取签名包
ViewData["appId"] = TenPayV3Info.AppId;
ViewData["timeStamp"] = timeStamp;
ViewData["nonceStr"] = nonceStr;
ViewData["package"] = package;
ViewData["paySign"] = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);
ViewData["paySign"] 是对js 进行重新签名
b, js 发起支付
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
//公众号支付
jQuery('a#getBrandWCPayRequest').click(function (e) {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": "@ViewData["appId"]", //公众号名称,由商户传入
"timeStamp": "@ViewData["timeStamp"]", //时间戳
"nonceStr": "@ViewData["nonceStr"]", //随机串
"package": "@Html.Raw(ViewData["package"])",//扩展包
"signType": "MD5", //微信签名方式:MD5
"paySign": "@ViewData["paySign"]" //微信签名
}, function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
}
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
//因此微信团队建议,当收到ok返回时,向商户后台询问是否收到交易成功的通知,若收到通知,前端展示交易成功的界面;若此时未收到通知,商户后台主动调用查询订单接口,查询订单的当前状态,并反馈给前端展示相应的界面。
});
});
WeixinJSBridge.log('yo~ ready.');
}, false);
5,完成支付后 在你的回调页面中处理你的后台业务 (此处是微信自动你的回调页面)
ResponseHandler resHandler = new ResponseHandler(null);
string return_code = resHandler.GetParameter("return_code");
string return_msg = resHandler.GetParameter("return_msg");
string res = null;
resHandler.SetKey(TenPayV3Info.Key);
//验证请求是否从微信发过来(安全)
if (resHandler.IsTenpaySign())
{
res = "success";
//正确的订单处理
}
else
{
res = "wrong";
//错误的订单处理
}