首先要理解微信支付的流程。需二次握手。
先把订单信息,金额传给微信,微信返回相应信息,再调用微信支付。
详细的查看微信公众号的相关资料
///
/// 新建一个普通订单
///
///
public Entity NewOrder(Entity en)
{
string WeiXinOpenID = en.GetValue("WeiXinOpenID").TryString();
string AddressID = en.GetValue("AddressID").TryString();
string OrderMessage = en.GetValue("OrderMessage").TryString();
int OrderStatus = (int)OrderEnum.OrderStatus.待付款;
string CommodityList = en.GetValue("CommodityList").TryString();
string CouponRecordGuid = en.GetValue("CouponRecordGuid").TryString(); //优惠券
decimal ManorMoney = en.GetValue("ManorMoney").TryDecimal(); //庄园币
string OrderGuid = System.Guid.NewGuid().ToString();
try
{
using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope())
{
#region 支付信息
string PayRecordID = System.Guid.NewGuid().TryString();
int PayStatus = (int)OrderEnum.PayStatus.未支付;
string OrderNum = OrderServiceDA.NewOrder(OrderGuid, WeiXinOpenID, AddressID, OriginalTotalPrice, SaleTotalPrice, OrderMessage, OrderStatus);
//添加支付记录
OrderServiceDA.AddPayRecord(PayRecordID, SaleTotalPrice, WeiXinOpenID, OrderGuid, PayStatus);
decimal WeixinPayMoney = SaleTotalPrice - (ManorMoney + Couponvalue);
if (WeixinPayMoney > 0)
{
int PayType = (int)OrderEnum.PayType.微信支付;
OrderServiceDA.AddPayRecordWeixinDetail(PayRecordID, PayType, WeixinPayMoney, PayStatus);
OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType);
WeixinPayService WeixinPayService = new WeixinPayService();
PaymentData payData = new PaymentData();
payData.SetValue("attach", OrderNum);
payData.SetValue("body", "微信在线支付");
payData.SetValue("out_trade_no", OrderNum);
payData.SetValue("trade_type", "JSAPI");
payData.SetValue("total_fee", (WeixinPayMoney * 100).ToInt32());//付款金额,单位分
payData.SetValue("openid", WeiXinOpenID);
PaymentData returnData = WeixinPayService.UnifiedOrder(payData);
string prepay_id = "";
string SignKey = "";
string TimeStamp = "";
string NonceStr = "";
string returnCode = returnData.GetValue("return_code").ToString();
if (returnCode.ToUpper().Equals("SUCCESS"))
{
#region 获取支付签名
//获取支付ID
prepay_id = returnData.GetValue("prepay_id").ToString();
PaymentData jsApiParam = new PaymentData();
NonceStr = WeixinPayService.GenerateNonceStr();
TimeStamp = WeixinPayService.GenerateTimeStamp();
jsApiParam.SetValue("appId", WeixinPayService.AppId);
jsApiParam.SetValue("timeStamp", TimeStamp);
jsApiParam.SetValue("nonceStr", NonceStr);
jsApiParam.SetValue("package", "prepay_id=" + prepay_id);
jsApiParam.SetValue("signType", "MD5");
SignKey = jsApiParam.MakeSign(WeixinPayService.SignKey);
#endregion
}
else
{
string ErrorMessage = returnData.GetValue("return_msg").ToString();
FaultException exception = new FaultException(ErrorMessage);
throw (exception);
}
//保存信息,用于前端再进行调起支付。
OrderServiceDA.UpdateWeixinPayRecord(PayRecordID, prepay_id, SignKey, TimeStamp, NonceStr);
}
else
{
if (ManorMoney == 0)
{
int PayType = (int)OrderEnum.PayType.优惠券;
OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType);
}
else
{
int PayType = (int)OrderEnum.PayType.庄园币;
OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType);
}
}
#endregion
scope.Complete();
}
}
catch (Exception ex)
{
Entity result = new Entity(new PropertyCollection());
result.AddSimple("Status", -10, typeof(int));
result.AddSimple("StatusText", ex.Message, typeof(string));
return result;
}
Entity resultEntity = new Entity(new PropertyCollection());
resultEntity.AddSimple("Status", 115, typeof(int));
resultEntity.AddSimple("StatusText", "操作成功.", typeof(string));
resultEntity.AddSimple("OrderGuid", OrderGuid, typeof(string));
return resultEntity;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TalentCloud.Common;
using TalentCloud.Base.Utils;
using TalentCloud.Agriculture.Services;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using TalentCloud.Common.Log;
namespace TalentCloud.Agriculture.Weixin.Services
{
public class WeixinPayService
{
///
/// 微信分配的AppId
///
public string AppId = TCConfigManager.GetConfig("WeixinPayAppid").TryToString();
///
/// 公众号的支付密钥appsecret
///
public string AppSecret = TCConfigManager.GetConfig("WeixinPayAppsecret").TryToString();
///
/// 当前用户IP
///
public string Ip = WCFClientInfo.ClientIP;
///
/// 商户号
///
public string MchId = TCConfigManager.GetConfig("MchId").TryToString();
///
/// 签名Key
///
public string SignKey = TCConfigManager.GetConfig("SignKey").TryToString();
//=======【证书路径设置】=====================================
/* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
*/
public string CertPath = TCConfigManager.GetConfig("certPath").TrySafeString();
///
/// 证书密码,windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID
///
public string CertPassword = TCConfigManager.GetConfig("certpsd").TrySafeString();
///
/// 支付结果通知回调url,用于商户接收支付结果
///
public string NOTIFY_URL =TCConfigManager.GetConfig("WebSite").TryToString()+ "/Weixin/PayCallback.aspx";
///
/// 生成随机串,随机串包含字母或数字 @return 随机串
///
///
public string GenerateNonceStr()
{
return Guid.NewGuid().ToString().Replace("-", "");
}
///
/// 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
///
///
public string GenerateTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
///
/// * 统一下单
///* @param WxPaydata inputObj 提交给统一下单API的参数
///* @param int timeOut 超时时间
///* @throws WxPayException
///* @return 成功时返回,其他抛异常
///
public PaymentData UnifiedOrder(PaymentData inputObj, int timeOut = 15)
{
string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//检测必填参数
if (!inputObj.IsSet("out_trade_no"))
{
throw new Exception("缺少统一支付接口必填参数out_trade_no!");
}
else if (!inputObj.IsSet("body"))
{
throw new Exception("缺少统一支付接口必填参数body!");
}
else if (!inputObj.IsSet("total_fee"))
{
throw new Exception("缺少统一支付接口必填参数total_fee!");
}
else if (!inputObj.IsSet("trade_type"))
{
throw new Exception("缺少统一支付接口必填参数trade_type!");
}
//关联参数
if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
{
throw new Exception("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
}
if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
{
throw new Exception("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
}
//异步通知url未设置,则使用配置文件中的url
if (!inputObj.IsSet("notify_url"))
{
inputObj.SetValue("notify_url", NOTIFY_URL);//异步通知url
}
inputObj.SetValue("appid", AppId);//公众账号ID
inputObj.SetValue("mch_id", MchId);//商户号
inputObj.SetValue("spbill_create_ip", Ip);//终端ip
inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
//签名
inputObj.SetValue("sign", inputObj.MakeSign(SignKey));
string xml = inputObj.ToXml();
string response = HttpService.Post(xml, url, false, timeOut, "", "");
PaymentData result = new PaymentData();
result.FromXml(response);
return result;
}
///
/// 申请退款
///
/// 提交给申请退款API的参数
/// 证书路径
/// 证书密码
/// 超时时间
///
public PaymentData Refund(PaymentData inputObj, int timeOut = 6)
{
string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//检测必填参数
if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
{
throw new Exception("退款申请接口中,out_trade_no、transaction_id至少填一个!");
}
else if (!inputObj.IsSet("out_refund_no"))
{
throw new Exception("退款申请接口中,缺少必填参数out_refund_no!");
}
else if (!inputObj.IsSet("total_fee"))
{
throw new Exception("退款申请接口中,缺少必填参数total_fee!");
}
else if (!inputObj.IsSet("refund_fee"))
{
throw new Exception("退款申请接口中,缺少必填参数refund_fee!");
}
else if (!inputObj.IsSet("op_user_id"))
{
throw new Exception("退款申请接口中,缺少必填参数op_user_id!");
}
inputObj.SetValue("appid", AppId);//公众账号ID
inputObj.SetValue("mch_id", MchId);//商户号
inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
inputObj.SetValue("sign", inputObj.MakeSign(SignKey));//签名
string xml = inputObj.ToXml();
string response = HttpService.Post(xml, url, true, timeOut, CertPath, CertPassword);
//将xml格式的结果转换为对象以返回
PaymentData result = new PaymentData();
result.FromXml(response);
return result;
}
///
/// 企业付款接口( 开通条件:
/// 1、商户号已入驻90日
/// 2、商户号有30天连续正常交易
/// 登录微信支付商户平台-产品中心,开通企业付款。)
///
/// 参数
/// 证书路径
/// 证书密码
/// 超时时间
///
public PaymentData Transfers(PaymentData inputObj, int timeOut = 6)
{
string url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
#region 检测必要参数
//检测必填参数
if (!inputObj.IsSet("partner_trade_no") && !inputObj.IsSet("partner_trade_no"))
{
throw new Exception("企业付款接口中,缺少必填参数partner_trade_no!");
}
if (!inputObj.IsSet("openid"))
{
throw new Exception("企业付款接口中,缺少必填参数openid!");
}
if (!inputObj.IsSet("check_name"))
{
throw new Exception("企业付款接口中,缺少必填参数check_name!");
}
else
{
string checkName = inputObj.GetValue("check_name").ToString();
switch (checkName)
{
case "FORCE_CHECK":
case "OPTION_CHECK":
if (!inputObj.IsSet("check_name"))
{
throw new Exception("企业付款接口中,缺少必填参数re_user_name!");
}
break;
default:
break;
}
}
if (!inputObj.IsSet("amount"))
{
throw new Exception("企业付款接口中,缺少必填参数amount!");
}
if (!inputObj.IsSet("desc"))
{
throw new Exception("企业付款接口中,缺少必填参数desc!");
}
if (!inputObj.IsSet("spbill_create_ip"))
{
throw new Exception("企业付款接口中,缺少必填参数spbill_create_ip!");
}
#endregion
#region 添加公共参数
inputObj.SetValue("mch_appid", AppId);//公众账号ID
inputObj.SetValue("mchid", MchId);//商户号
inputObj.SetValue("spbill_create_ip", Ip);//随机字符串
inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
inputObj.SetValue("sign", inputObj.MakeSign(SignKey));//签名
#endregion
string xml = inputObj.ToXml();
var start = DateTime.Now;
string response = HttpService.Post(xml, url, true, timeOut, CertPath, CertPassword);
LogHelper.WriteFileLog("TransfersData", response);
PaymentData result = new PaymentData();
result.FromXml(response);
return result;
}
#region 微信发红发,未事项,签名失败问题,未解决
///
/// 微信红包
///
public class PayWeiXin
{
public string nonce_str { get; set; }
public string sign { get; set; }
public string mch_billno { get; set; }
public string mch_id { get; set; }
public string wxappid { get; set; }
public string nick_name { get; set; }
public string send_name { get; set; }
public string re_openid { get; set; }
public int total_amount { get; set; }
public int min_value { get; set; }
public int max_value { get; set; }
public int total_num { get; set; }
public string wishing { get; set; }
public string client_ip { get; set; }
public string act_id { get; set; }
public string act_name { get; set; }
public string remark { get; set; }
public string logo_imgurl { get; set; }
public string share_content { get; set; }
public string share_url { get; set; }
public string share_imgurl { get; set; }
}
///
/// 调用微信支付接口,发送红包
///
///
///
public string PayRedBag(PaymentData inputObj)
{ 商户号
inputObj.SetValue("mch_id", MchId);
//商户 appid
inputObj.SetValue("wxappid", AppId);
inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
//签名
inputObj.SetValue("sign", inputObj.MakeSign(SignKey));
string xml = inputObj.ToXml();
string result = string.Empty;
try
{
result = PostPage("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", xml);
LogHelper.WriteFileLog("PayRedBagpostData", xml);
LogHelper.WriteFileLog("PayRedBag", result);
}
catch (Exception ex)
{
LogHelper.WriteFileLog("PayRedBagError", ex.Message);
}
return result;
}
///
/// post微信请求
///
///
///
///
public string PostPage(string posturl, string postData)
{
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
byte[] data = encoding.GetBytes(postData);
// 准备请求...
try
{
//CerPath证书路径
string certPath = TCConfigManager.GetConfig("certPath").TrySafeString();
//证书密码
string password = TCConfigManager.GetConfig("certpsd").TrySafeString();
X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, password, X509KeyStorageFlags.MachineKeySet);
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "POST";
request.ContentType = "text/xml";
request.ContentLength = data.Length;
request.ClientCertificates.Add(cert);
outstream = request.GetRequestStream();
outstream.Write(data, 0, data.Length);
outstream.Close();
//发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty;
return content;
}
catch (Exception ex)
{
string err = ex.Message;
return string.Empty;
}
}
///
/// Md5加密
///
///
///
public static String Encrypt(String s)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
bytes = md5.ComputeHash(bytes);
md5.Clear();
string ret = "";
for (int i = 0; i < bytes.Length; i++)
{
ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
}
return ret.PadLeft(32, '0');
}
public string RandomStr(string str, int Length)
{
string result = string.Empty;
Random rd = new Random();
for (int i = 0; i < Length; i++)
{
result += str[rd.Next(str.Length)];
}
return result;
}
#endregion
}
}
//弹出微信支付页面
WeixinJSBridge.invoke('getBrandWCPayRequest',
{
"appId": data.AppID, //公众号名称,由商户传入
"timeStamp": data.TimeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": "prepay_id="+data.prepay_id,
"signType": "MD5", //微信签名方式:
"paySign": data.SignKey //微信签名
},
function (res) {
switch (res.err_msg) {
case "get_brand_wcpay_request:ok":
layer.open({
content: '充值成功',
skin: 'msg',
time: 2 //2秒后自动关闭
});
browserHistory.push('/WeChat/dist/member/wallet/');
break;
case "get_brand_wcpay_request:cancel":
break;
case "get_brand_wcpay_request:fail":
layer.open({
content: '充值失败!',
skin: 'msg',
time: 2 //2秒后自动关闭
});
break;
default:
}
});
public partial class PayCallback : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StreamReader reader = new StreamReader(Request.InputStream, Encoding.UTF8);
string postStr = reader.ReadToEnd();
reader.Close();
XmlDocument doc = new XmlDocument();
doc.LoadXml(postStr);
string ReturnCode = doc.SelectSingleNode("//result_code").InnerText;//获取支付结果代码
StringBuilder xmlStr = new StringBuilder();
LogHelper.WriteFileLog("PayCallback", ReturnCode);
if (ReturnCode.ToUpper().Equals("SUCCESS"))
{
string strOrderNo = doc.SelectSingleNode("//out_trade_no").InnerText;
//获取微信支付流水号
string weChatTransaction_Id = doc.SelectSingleNode("//transaction_id").InnerText;
string WeiXinOpenID = doc.SelectSingleNode("//openid").InnerText;
try
{
//获取订单号
WeiXinService WeiXinService = new WeiXinService();
Entity result= WeiXinService.PayOrder(WeiXinOpenID, strOrderNo, weChatTransaction_Id);
string Status = result.GetValue("Status").ToString();
string StatusText = result.GetValue("StatusText").ToString();
LogHelper.WriteFileLog("Pay", WeiXinOpenID + "," + strOrderNo + "," + weChatTransaction_Id + "," + Status + "," + StatusText);
}
catch (Exception ex)
{
LogHelper.WriteFileLog("PayError", ex.Message + "," + WeiXinOpenID + "," + strOrderNo + "," + weChatTransaction_Id);
//记录错误
throw ex;
}
#region 通知微信后台支付成功
Response.ContentType = "text/xml";
xmlStr.AppendLine("");
xmlStr.AppendFormat(" ");
xmlStr.AppendFormat(" ");
xmlStr.AppendFormat(" ");
#endregion
}
else
{
#region 通知微信后台支付失败
Response.ContentType = "text/xml";
xmlStr.AppendLine("");
xmlStr.AppendFormat(" ");
xmlStr.AppendFormat(" ");
xmlStr.AppendFormat(" ");
#endregion
}
Response.Write(xmlStr.ToString());
}