使用第三方库(Senparc)完成小程序支付

时间:2024-02-23 14:06:28

1.添加第三方库,如下图:

2.支付代码:

/// <summary>
/// 支付
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[Route("Pay")]
public WeixinJsPaySignature Pay(PayRequest model)
{

string timeStamp = "";
string nonceStr = "";
string paySign = "";

string sp_billno = GeneratorHelper.GeneratorOrderNo();
using (var context = new TwoPoleRentContext())
{
var devcie = context.Devices.FirstOrDefault(c => c.DeviceCode == model.DeviceId);
if (devcie == null)
{

return null;
}
var supplier = context.Suppliers.FirstOrDefault(c => c.OpenId == model.OpenId);
var order = new Order()
{
OrderId = Guid.NewGuid(),
OrderCode = sp_billno,
OrderName = Constants.OrderName,
OrderPrice = model.Total,
PayType = PayType.WxPay,
OrderState = OrderState.Pending,
OrderTotalMoney = model.Total,
CreatedOn = DateTime.Now,
SupplierId = supplier.Id,
DeviceId = devcie.Id,
ModifiedOn = DateTime.Now
};
context.Orders.Add(order);
context.SaveChanges();

}

//创建支付应答对象
RequestHandler packageReqHandler = new RequestHandler(null);
//初始化
packageReqHandler.Init();

timeStamp = TenPayV3Util.GetTimestamp();
Logger.DebugFormat("支付timeStamp{0}", timeStamp);
nonceStr = TenPayV3Util.GetNoncestr();

Logger.DebugFormat("支付nonceStr{0}", nonceStr);
var productName = "易考星";

//设置package订单参数
packageReqHandler.SetParameter("appid", Constants.AppID);    //公众账号ID
packageReqHandler.SetParameter("mch_id", Constants.TenPay3MchId);    //商户号
packageReqHandler.SetParameter("nonce_str", nonceStr); //随机字符串
packageReqHandler.SetParameter("body", productName); //商品信息
packageReqHandler.SetParameter("out_trade_no", sp_billno);    //商家订单号
//todo 充数据库配置获取价格
packageReqHandler.SetParameter("total_fee", (model.Total * Constants.WeixinRedPackRatio/1000).ToString());    //商品金额,以分为单位(money * 100).ToString()
packageReqHandler.SetParameter("spbill_create_ip", Request.GetClientIpAddress()); //用户的公网ip,不是商户服务器IP
packageReqHandler.SetParameter("notify_url", string.Format("{0}/Api/WeixinPay/PayNotifyUrl", Constants.WeixinWebsite));    //接收财付通通知的URL
packageReqHandler.SetParameter("trade_type", TenPayV3Type.JSAPI.ToString());    //交易类型
packageReqHandler.SetParameter("openid", model.OpenId); //用户的openId
Logger.DebugFormat("支付OpenId{0}", model.OpenId);
string sign = packageReqHandler.CreateMd5Sign("key", Constants.TenPayV3Key);

Logger.DebugFormat("支付sign{0}", sign);
packageReqHandler.SetParameter("sign", sign); //签名

string data = packageReqHandler.ParseXML();
Logger.DebugFormat("支付data{0}", data);
var resultPay = TenPayV3.Unifiedorder(data);
var res = XDocument.Parse(resultPay);
Logger.DebugFormat("支付result{0}", resultPay);
Logger.DebugFormat("支付res{0}", res);
string prepayId = res.Element("xml").Element("prepay_id").Value;
Logger.DebugFormat("支付prepayId{0}", prepayId);
//设置支付参数
RequestHandler paySignReqHandler = new RequestHandler(null);

paySignReqHandler.SetParameter("appId", Constants.AppID);

paySignReqHandler.SetParameter("timeStamp", timeStamp);
paySignReqHandler.SetParameter("nonceStr", nonceStr);

paySignReqHandler.SetParameter("package", string.Format("prepay_id={0}", prepayId));
paySignReqHandler.SetParameter("signType", "MD5");

paySign = paySignReqHandler.CreateMd5Sign("key", Constants.TenPayV3Key);

var jsmodel = new WeixinJsPaySignature
{
AppId = Constants.AppID,
Timestamp = timeStamp,
NonceStr = nonceStr,
Package = string.Format("prepay_id={0}", prepayId),
PaySign = paySign,
OrderId = sp_billno
};
return jsmodel;
}

 

3.回调:

/// <summary>
/// 支付回调
/// </summary>
/// <returns></returns>
[Route("PayNotifyUrl")]
public HttpResponseMessage PayNotifyUrl()
{
Logger.Debug("PayNotifyUrl");
ResponseHandler resHandler = new ResponseHandler(null);

var _xml = resHandler.ParseXML();
Logger.InfoFormat(_xml);

string result_code = resHandler.GetParameter("result_code");
Logger.DebugFormat("result_code-{0}", result_code);

string fee_type = resHandler.GetParameter("fee_type");
Logger.DebugFormat("fee_type-{0}", fee_type);

string return_code = resHandler.GetParameter("return_code");
Logger.DebugFormat("return_code-{0}", return_code);

string total_fee = resHandler.GetParameter("total_fee");
Logger.DebugFormat("total_fee-{0}", total_fee);

string return_msg = resHandler.GetParameter("return_msg");
Logger.DebugFormat("return_msg-{0}", return_msg);

string mch_id = resHandler.GetParameter("mch_id");
Logger.DebugFormat("mch_id-{0}", mch_id);

string cash_fee = resHandler.GetParameter("cash_fee");
Logger.DebugFormat("cash_fee-{0}", cash_fee);

string openid = resHandler.GetParameter("openid");
Logger.DebugFormat("openid-{0}", openid);

string transaction_id = resHandler.GetParameter("transaction_id");
Logger.DebugFormat("transaction_id-{0}", transaction_id);

string sign = resHandler.GetParameter("sign");
Logger.DebugFormat("sign-{0}", sign);

string bank_type = resHandler.GetParameter("bank_type");
Logger.DebugFormat("bank_type-{0}", bank_type);

string appid = resHandler.GetParameter("appid");
Logger.DebugFormat("appid-{0}", appid);

string time_end = resHandler.GetParameter("time_end");
Logger.DebugFormat("time_end-{0}", time_end);

string trade_type = resHandler.GetParameter("trade_type");
Logger.DebugFormat("trade_type-{0}", trade_type);

string nonce_str = resHandler.GetParameter("nonce_str");
Logger.DebugFormat("nonce_str-{0}", nonce_str);

string is_subscribe = resHandler.GetParameter("is_subscribe");
Logger.DebugFormat("is_subscribe-{0}", is_subscribe);

string out_trade_no = resHandler.GetParameter("out_trade_no");
Logger.DebugFormat("out_trade_no-{0}", out_trade_no);

Logger.DebugFormat("TotalFee:{0},CashFee:{1}", decimal.Parse(total_fee), decimal.Parse(cash_fee));
string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", return_code, return_msg);
try
{
using (var context = new TwoPoleRentContext())
{
var pay = new Pay()
{
//PayId = Guid.NewGuid(),
PayState = PayState.OrderSuccess,
PayType = PayType.WxPay,
ResultCode = result_code,
FeeType = fee_type,
ReturnCode = return_code,
TotalFee = decimal.Parse(total_fee),
MchId = mch_id,
CashFee = decimal.Parse(cash_fee),
TransactionId = transaction_id,
Sign = sign,
BankType = bank_type,
Appid = appid,
TimeEnd = DateTime.Now,
TradeType = trade_type,
NonceStr = nonce_str,
OrderCode = out_trade_no,
CreatedOn = DateTime.Now,
ModifiedOn = DateTime.Now
};
var order = context.Orders.Include("Device").FirstOrDefault(d => d.OrderCode == out_trade_no);
if (order==null||order.PayId != null)
{
return new HttpResponseMessage { Content = new StringContent(xml, Encoding.GetEncoding("UTF-8"), "text/plain") };
}
//更新设备使用情况
var deviceUsage = context.DeviceUsages.FirstOrDefault(c => c.DeviceId == order.DeviceId);

var hours = (double) (order.OrderPrice/order.Device.UnitPrice);
if (deviceUsage==null)
{
deviceUsage=new DeviceUsage
{
DeviceId =order.DeviceId,
StarTime = DateTime.Now,
EndTime = DateTime.Now.AddHours(hours)
};
context.DeviceUsages.Add(deviceUsage);
}
else
{
if (deviceUsage.EndTime>DateTime.Now)
{
deviceUsage.EndTime= deviceUsage.EndTime.AddHours(hours);
}
else
{
deviceUsage.StarTime=DateTime.Now;
deviceUsage.EndTime = DateTime.Now.AddHours(hours);
}
}
order.PayId = pay.Id;
order.PayType = (int)PayType.WxPay;
order.OrderState = OrderState.Paid;
context.Pays.Add(pay);
//教练提成
var divided = context.Divideds.FirstOrDefault(c => c.SupplierId == order.SupplierId);
if (divided==null)
{
Logger.Error(string.Format("设备提成未配置,订单号:{0},设备编号:{1}", out_trade_no, order.SupplierId));
}
else
{
var money=divided.DividedState==DividedState.FixedAmount?divided.FixedAmount:order.OrderPrice*divided.Percentage;
var account = context.Accounts.FirstOrDefault(c => c.Id == order.SupplierId);

if (account==null)
{
account=new Account
{
Id = order.SupplierId,
UserMoney = money,
DepositForzeMoney=0,
DepositLeftMoney=0,
};
context.Accounts.Add(account);
}
else
{
account.UserMoney += money;
}
var accountDetail = new AccountDetail
{
AccountId = account.Id,
UserMoney = money,
FrozenMoney=0,
DetailType = DepositDetailType.DetailCharge,
DetailState = DetailState.DetailSuccess,
OrderSource = out_trade_no,

};
account.AccountDetails.Add(accountDetail);
}

var result = context.SaveChanges() > 0;
Logger.InfoFormat("pay_result:{0}", result);

}
}
catch (Exception ex)
{
Logger.Error(string.Format("支付回调出错,{0}",ex));
}

return new HttpResponseMessage { Content = new StringContent(xml, Encoding.GetEncoding("UTF-8"), "text/plain") };
}

 

5.小程序端代码:

pay: function () {
wx.showLoading({
title: \'正在支付\'
})
app.httpService("weixinPay/Pay",
{
openId: this.data.openid,
Total: this.data.Total,
deviceId: this.data.deviceId
},
function (res) {
console.log(res)
wx.hideLoading()
if (res) {
wx.requestPayment({
\'timeStamp\': res.Timestamp,
\'nonceStr\': res.NonceStr,
\'package\': res.Package,
\'signType\': \'MD5\',
\'paySign\': res.PaySign,
\'success\': function (res) {
wx.showToast({
title: \'支付成功,欢迎使用驾考设备\',
icon: \'none\',
duration: 3000
});
},
\'fail\': function (res) {
wx.showToast({
title: \'支付失败,请重新支付\',
icon: \'none\',
duration: 2000
});
}
})
}
})
},