You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

326 lines
15 KiB
C#

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.Serialization;
using System.IO;
using System.Text;
using System.Net;
using System.Web.Security;
using LitJson;
using HuizhongLibrary.Log;
namespace WxPayAPI
{
public class JsApiPay
{
/// <summary>
/// 保存页面对象因为要在类的方法中使用Page的Request对象
/// </summary>
private Page page {get;set;}
/// <summary>
/// openid用于调用统一下单接口
/// </summary>
public string openid { get; set; }
/// <summary>
/// access_token用于获取收货地址js函数入口参数
/// </summary>
public string access_token { get; set; }
/// <summary>
/// 商品金额,用于统一下单
/// </summary>
public int total_fee { get; set; }
/// <summary>
/// 统一下单接口返回结果
/// </summary>
public WxPayData unifiedOrderResult { get; set; }
public JsApiPay(Page page)
{
this.page = page;
}
/**
*
* 网页授权获取用户基本信息的全部过程
* 详情请参看网页授权获取用户基本信息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"];
ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", this.GetType().ToString(), "Get code : " + code);
//Log.Debug(this.GetType().ToString(), "Get code : " + code);
GetOpenidAndAccessTokenFromCode(code);
}
else
{
//构造网页授权获取code的URL
string host = page.Request.Url.Host;
string path = page.Request.Path;
string Query="";
if (!string.IsNullOrEmpty(page.Request.QueryString["MoneyNum"]))
Query = "?ordercode=" + page.Request.QueryString["ordercode"] + "&MoneyNum=" + page.Request.QueryString["MoneyNum"];
else
if (!string.IsNullOrEmpty(page.Request.QueryString["ItemNo"]))
Query = "?ItemNo=" + page.Request.QueryString["ItemNo"] + "&PayNum=" + page.Request.QueryString["PayNum"];
else if (!string.IsNullOrEmpty(page.Request.QueryString["PayNum"]))
Query = "?CompanyId=" + page.Request.QueryString["CompanyId"] + "&PayNum=" + page.Request.QueryString["PayNum"] + "&UserId=" + page.Request.QueryString["UserId"] + "&AppType=" + page.Request.QueryString["AppType"] + "&UserName=" + page.Request.QueryString["UserName"] + "&ReaName=" + page.Request.QueryString["ReaName"];
ErrorFollow.TraceWrite("Query", "", page.Request.QueryString["MoneyNum"]);
ErrorFollow.TraceWrite("Query2", "", Query);
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", path);
string redirect_uri = HttpUtility.UrlEncode("http://" + host + path + Query);
ErrorFollow.TraceWrite("redirect_uri", "redirect_uri:", redirect_uri);
WxPayData data = new WxPayData();
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "APPID:", WxPayConfig.APPID);
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", WxPayConfig.APPID);
data.SetValue("appid", WxPayConfig.APPID);
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)
{
ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", ex.Message);
}
}
}
public void GetOpenidAndAccessTokenOrder()
{
if (!string.IsNullOrEmpty(page.Request.QueryString["code"]))
{
//获取code码以获取openid和access_token
string code = page.Request.QueryString["code"];
ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", this.GetType().ToString(), "Get code : " + code);
//Log.Debug(this.GetType().ToString(), "Get code : " + code);
GetOpenidAndAccessTokenFromCode(code);
}
else
{
//构造网页授权获取code的URL
string host = page.Request.Url.Host;
string path = page.Request.Path;
string Query = "";
if (!string.IsNullOrEmpty(page.Request.QueryString["out_trade_no"]))
Query = "?CompanyId=" + page.Request.QueryString["CompanyId"] + "&Amount=" + page.Request.QueryString["Amount"] + "&AppType=" + page.Request.QueryString["AppType"] + "&out_trade_no=" + page.Request.QueryString["out_trade_no"];
ErrorFollow.TraceWrite("Query", "", page.Request.QueryString["MoneyNum"]);
ErrorFollow.TraceWrite("Query2", "", Query);
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", path);
string redirect_uri = HttpUtility.UrlEncode("http://" + host + path + Query);
ErrorFollow.TraceWrite("redirect_uri", "redirect_uri:", redirect_uri);
WxPayData data = new WxPayData();
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "APPID:", WxPayConfig.APPID);
// ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", WxPayConfig.APPID);
data.SetValue("appid", WxPayConfig.APPID);
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)
{
ErrorFollow.TraceWrite("GetOpenidAndAccessTokenFromCode", "redirect_uri:", ex.Message);
}
}
}
/**
*
* 通过code换取网页授权access_token和openid的返回数据正确时返回的JSON数据包如下
* {
* "access_token":"ACCESS_TOKEN",
* "expires_in":7200,
* "refresh_token":"REFRESH_TOKEN",
* "openid":"OPENID",
* "scope":"SCOPE",
* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
* }
* 其中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 out_trade_no)
{
//统一下单
WxPayData data = new WxPayData();
data.SetValue("body", "平台服务");
data.SetValue("attach", "平台服务");
data.SetValue("out_trade_no", out_trade_no);//WxPayApi.GenerateOutTradeNo()
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", "平台服务");
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时的输入参数格式如下
* {
* "appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入
* "timeStamp":" 1395712654", //时间戳自1970年以来的秒数
* "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串
* "package" : "prepay_id=u802345jgfjsdfgsdg888",
* "signType" : "MD5", //微信签名方式:
* "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
* }
* @return string 微信浏览器调起JSAPI时的输入参数json格式可以直接做参数用
* 更详细的说明请参考网页端调起支付APIhttp://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;
}
/**
*
* 获取收货地址js函数入口参数,详情请参考收货地址共享接口http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_9
* @return string 共享收货地址js函数需要的参数json格式可以直接做参数使用
*/
public string GetEditAddressParameters()
{
string parameter = "";
try
{
string host = page.Request.Url.Host;
string path = page.Request.Path;
string queryString = page.Request.Url.Query;
//这个地方要注意参与签名的是网页授权获取用户信息时微信后台回传的完整url
//string url = "http://wx.huizsoft.com" + path + queryString;
string url = "http://" + host + path + queryString;
//构造需要用SHA1算法加密的数据
WxPayData signData = new WxPayData();
signData.SetValue("appid",WxPayConfig.APPID);
signData.SetValue("url", url);
signData.SetValue("timestamp",WxPayApi.GenerateTimeStamp());
signData.SetValue("noncestr",WxPayApi.GenerateNonceStr());
signData.SetValue("accesstoken",access_token);
string param = signData.ToUrl();
Log.Debug(this.GetType().ToString(), "SHA1 encrypt param : " + param);
//SHA1加密
string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1");
Log.Debug(this.GetType().ToString(), "SHA1 encrypt result : " + addrSign);
//获取收货地址js函数入口参数
WxPayData afterData = new WxPayData();
afterData.SetValue("appId",WxPayConfig.APPID);
afterData.SetValue("scope","jsapi_address");
afterData.SetValue("signType","sha1");
afterData.SetValue("addrSign",addrSign);
afterData.SetValue("timeStamp",signData.GetValue("timestamp"));
afterData.SetValue("nonceStr",signData.GetValue("noncestr"));
//转为json格式
parameter = afterData.ToJson();
Log.Debug(this.GetType().ToString(), "Get EditAddressParam : " + parameter);
}
catch (Exception ex)
{
Log.Error(this.GetType().ToString(), ex.ToString());
throw new WxPayException(ex.ToString());
}
return parameter;
}
}
}