.NET
https://github.com/JeffreySu/WeiXinMPSDK
JAVA
http://git.oschina.net/pyinjava/fastweixin
NodeJS
https://github.com/node-weixin/node-weixin-api
Python
http://git.oschina.net/jeffkit/wechat
微信消息配置
已.NET 为例子,WeiXinMPSDK支持公众号与企业号,实现起来也比较简单
/// <summary>
/// 微信控制器
/// </summary>
public class WeixinController : Controller
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public readonly string token = DbSetting.getAppText("Token");
public readonly string appId = DbSetting.getAppText("AppID");
public readonly string encodingAESKey = DbSetting.getAppText("EncodingAESKey");
/// <summary>
/// 微信验签
/// </summary>
/// <param name="signature"></param>
/// <param name="timestamp"></param>
/// <param name="nonce"></param>
/// <param name="echostr"></param>
/// <returns></returns>
[HttpGet]
public async Task<ActionResult> Index(string signature, string timestamp, string nonce, string echostr)
{
return await Task.Run(() =>
{
if (!CheckSignature.Check(signature, timestamp, nonce, token))
{
return "failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, token) + "。如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。";
}
return echostr;
}).ContinueWith(task => Content(task.Result));
}
/// <summary>
/// 处理微信消息
/// </summary>
/// <param name="postModel">参数</param>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult> Index(PostModel postModel)
{
return await Task.Run<ActionResult>(() =>
{
if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, token))
{
return new WeixinResult("参数错误!");
}
postModel.Token = token;
postModel.EncodingAESKey = encodingAESKey;
postModel.AppId = appId;
var messageHandler = new MpWeixinMessageHandler(Request.InputStream, postModel);
messageHandler.Execute();
return new FixWeixinBugWeixinResult(messageHandler);
}).ContinueWith(task => task.Result);
}
}
消息重载
/// <summary>
/// 处理微信消息
/// </summary>
public class MpWeixinMessageHandler : MessageHandler<MessageContext<IRequestMessageBase, IResponseMessageBase>>
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public readonly string appId = DbSetting.getAppText("AppID");
public readonly string appSecret = DbSetting.getAppText("AppSecret");
/// <summary>
/// 构造函数
/// </summary>
/// <param name="inputStream"></param>
/// <param name="postModel"></param>
public MpWeixinMessageHandler(Stream inputStream, PostModel postModel)
: base(inputStream, postModel)
{
WeixinContext.ExpireMinutes = 5;
}
/// <summary>
/// 默认消息 [没有重写的OnXX方法,将默认返回DefaultResponseMessage中的结果]
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
//ResponseMessageText也可以是News等其他类型
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "这条消息来自DefaultResponseMessage。";
return responseMessage;
}
/// <summary>
/// 关注微信公众号
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_SubscribeRequest(RequestMessageEvent_Subscribe requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
var token = CommonApi.GetToken(appId, appSecret).access_token;
var user = CommonApi.GetUserInfo(token, requestMessage.FromUserName);
responseMessage.Content = "Hi " + user.nickname + " ,感谢您关注XXX!!!";
return responseMessage;
}
/// <summary>
/// 取消关注公众号
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnEvent_UnsubscribeRequest(RequestMessageEvent_Unsubscribe requestMessage)
{
return base.OnEvent_UnsubscribeRequest(requestMessage);
}
/// <summary>
/// 发送文本消息
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = "感谢您关注XXX!!! ";
return responseMessage;
}
}
微信支付签名
#region 创建订单与生成微信支付 JSAPPI 签名
/// <summary>
/// 创建订单与生成微信支付 JSAPPI 签名
/// </summary>
/// <param name="create">订餐参数</param>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult> Create(Create create)
{
try
{
logger.Info("orders create xml: " + create.ToXml());
if (!ModelState.IsValid)
return Json(new { IsError = true, ErrorMsg = "创建订单参数异常!!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
//取购物车缓存
var cart = CacheManger.Cache.Get<CartInfoModel>(create.OpenId);
if (cart.IsNull() || cart.ShopId.IsNullOrEmpty() || cart.OpenID.IsNullOrEmpty() || cart.OpenID != create.OpenId || cart.CartItemList.IsNull() || cart.CartItemList.Count == 0)
return Json(new { IsError = true, ErrorMsg = "创建订单参数异常!!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
//控制库存与订单事物
using (var conn = new SqlConnection(DbSetting.App))
{
await conn.OpenAsync();
var trans = conn.BeginTransaction();
//验证价格及库存[重要]
//创建订单
string subject = @"xxx支付";
string orderNo = WxPayConfig.OutTradeNo;
//!!! 1分钱测试 !!!
decimal total_fee = 0.01m;
var executeNum = await conn.ExecuteAsync(@"INSERT INTO Orders
(
Origin,
ShopId,
OpenId,
Name,
PhoneNo,
[Subject],
OrderNo,
[Status],
TotalFee,
Coupon,
Memo,
CreateTime
)
VALUES
(
@Origin,
@ShopId,
@OpenId,
@Name,
@PhoneNo,
@Subject,
@OrderNo,
@Status,
@TotalFee,
@Coupon,
@Memo,
@CreateTime
)", new
{
Origin = AbpConstants.WEIXIN_ORIGIN,
OpenId = create.OpenId,
ShopId = Guid.Parse(cart.ShopId),
Name = create.UserName,
PhoneNo = create.Phone,
Subject = subject,
OrderNo = orderNo,
Status = "R",
TotalFee = cart.TotalPrice,
Coupon = "0",
Memo = string.Empty,
CreateTime = DateTime.Now
}, trans);
if (executeNum <= 0)
{
trans.Rollback();
return Json(new { IsError = true, ErrorMsg = "创建订单异常!!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
}
foreach (var item in cart.CartItemList.Where(t => t.CartNum != 0))
{
executeNum = conn.Execute(@"INSERT INTO OrderDetail
(
OrderId,
ItemId,
ItemName,
Num,
UnitPrice,
TotalFee
)
VALUES
(
@OrderId,
@ItemId,
@ItemName,
@Num,
@UnitPrice,
@TotalFee
)", new
{
OrderId = orderNo,
ItemId = item.ItemId,
ItemName = item.ItemName,
Num = item.CartNum,
UnitPrice = item.Price,
TotalFee = item.Price * item.CartNum
}, trans);
if (executeNum <= 0)
{
trans.Rollback();
return Json(new { IsError = true, ErrorMsg = "创建订单明细异常!!!", Data = string.Empty }, JsonRequestBehavior.AllowGet);
}
}
//提交事物
trans.Commit();
var wxpay = await Order(WxPayConfig.APPID, create.OpenId, WxPayConfig.MCHID, orderNo, total_fee, WxPayConfig.NonceStr, subject, "没有优惠券", "XXX");
if (wxpay.IsError)
{
return Redirect(DbSetting.getAppText("Domain") + @"/oauth/1");
}
var jsApiDict = new SortedDictionary<string, string>();
jsApiDict.Add("appId", appId);
jsApiDict.Add("timeStamp", WxPayConfig.TimeStamp);
jsApiDict.Add("nonceStr", WxPayConfig.NonceStr);
jsApiDict.Add("package", "prepay_id=" + (wxpay.Data as SortedDictionary<string, string>)["prepay_id"]);
jsApiDict.Add("signType", "MD5");
jsApiDict.Add("paySign", WxPayConfig.GenerateSign(jsApiDict));
return Json(new { IsError = false, ErrorMsg = string.Empty, Data = jsApiDict.ConvertDictionaryToJson() }, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
logger.Info("orders create xml: " + create.ToXml() + " exception message: " + ex.Message);
return Json(new
{
IsError = true,
ErrorMsg = "创建订单异常!!!",
Data = string.Empty
}, JsonRequestBehavior.AllowGet);
}
}
#endregion
#region 微信支付签名
/// <summary>
/// 微信支付签名
/// </summary>
/// <param name="appid">公众账号ID</param>
/// <param name="openid">微信唯一标识</param>
/// <param name="mch_id">