前段时间公司的项目需要做微信支付,就想微信支付这种普通的功能,网上应该一堆开发文档,自己 以前也接过微信支付,所以就很自信,着手开始接支付,可是不知道哪里就进坑了,无论如何都调不起APP支付。于是乎,在网上海量的看博客,可是发现好多博客有一种几乎魔力的相似。哎,只能靠微信自带的签名验证工具去验证签名了,可是签名显示正确。尴尬!
微信APP支付,首先需要去微信开放平台去申请一个账号,开通微信支付,开通后,建一个移动应用,把相关的参数填写上去,IOS只需要填写Bundle ID ,Android需要填写的应用签名以及应用包名,对于Android来说,这2个参数一定不能错了,错了下面即使对了,也调不起支付,这个估计大家都知道,应用签名是一个32位的MD5签名,用Android studio 打包一个签名的apk包,安装到你的手机上,在从微信公众号官网上下载一个签名生成工具,获取签名即可,个人觉得这种方式即快又准。
准备工作做的差不多了,先说一下我们需要用到的几个参数,1 APPID 2. mch_id 商户id (这个是微信支付申请成功,微信会给你注册的邮箱发一个商户平台的账号密码) 3.商户平台配置API密钥。推荐一个博客,写的比较详细:https://blog.csdn.net/vroymond/article/details/53574173。
开始我此次写博客的主要说明的地方了,微信APP支付,我是在自己的远程服务器上生成,生成代码如下:
string sendUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
WxPayData data = new WxPayData();
data.SetValue("appid", "wx8888888888888888"); //APPID
data.SetValue("attach", "支付测试"); //商品名称
data.SetValue("body", shopname); //商品描述
data.SetValue("mch_id", "128*******"); //商户ID
data.SetValue("nonce_str", JsApiPay.GenerateNonceStr()); //
data.SetValue("notify_url", "http://wx.com/api/payment/wxapipay/appnotify_url.aspx"); //异步通知url
data.SetValue("out_trade_no", orderno); //商户订单号
data.SetValue("spbill_create_ip", "127.0.0.1"); //终端IP
data.SetValue("total_fee", amount); //订单金额
data.SetValue("trade_type", "APP"); //交易类型,直接写APP就可以了
WxPayData signdata = new WxPayData();
signdata.SetValue("appid", "wx8888888888888888");
signdata.SetValue("body", "APP支付测试");
signdata.SetValue("device_info", "1000");
signdata.SetValue("mch_id", "128*******");
signdata.SetValue("nonce_str", "http://wx.com/api/payment/wxapipay/appnotify_url.aspx");
data.SetValue("sign", data.MakeSign("商户平台配置API密钥")); //商品描述
string xml = data.ToXml(); //转换成XML
var startTime = DateTime.Now; //开始时间
string response = HttpService.Post(xml, sendUrl, false, 6); //发送请求
var endTime = DateTime.Now; //结束时间
int timeCost = (int)((endTime - startTime).TotalMilliseconds); //计算所用时间
WxPayData result = new WxPayData();
result.FromXml(response, "商户平台配置API密钥");
JsApiPay.ReportCostTime(sendUrl, timeCost, result);//测速上报
获取H5调起JS API参数
WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appid", result.GetValue("appid"));
jsApiParam.SetValue("noncestr", JsApiPay.GenerateNonceStr());
jsApiParam.SetValue("package", "Sign=WXPay");
jsApiParam.SetValue("partnerid", result.GetValue("mch_id"));
jsApiParam.SetValue("prepayid", result.GetValue("prepay_id"));
jsApiParam.SetValue("timestamp", JsApiPay.GenerateTimeStamp());
jsApiParam.SetValue("sign", jsApiParam.MakeSign("商户平台配置API密钥"));
string xml2 = jsApiParam.ToXml(); //转换成XML
wxJsApiParam = jsApiParam.ToJson();
return wxJsApiParam.ToString();
上面是生成预支付订单,APP通过服务获取wxJsApiParam ,通过json解析获取相关参数,上面有2个需要注意
1、 jsApiParam.SetValue("prepayid", result.GetValue("prepay_id")); 所有类似的SetValue,key都需要小写,这个就是我签名对,但是没调起支付的原因,用微信的签名验证,也是对的,但是就是调不起来,巨坑。可能还有很多朋友关注这个MakeSignd的方法,如下:
/**
* @生成签名,详见签名生成算法
* @return 签名, sign字段不参加签名
*/
public string MakeSign(string key)
{
//转url格式
string str = ToUrl();
//在string后加入API KEY
str += "&key=" + key;
//MD5加密
var md5 = MD5.Create();
var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
var sb = new StringBuilder();
foreach (byte b in bs)
{
sb.Append(b.ToString("x2"));
}
//所有字符转为大写
return sb.ToString().ToUpper();
}
,然后在APP端用解析后的参数调用如下:
就可以了,此处有一个关键的地方,回调地址 notify_url,这个很关键,这是我写此博客的主要原因之一,个人觉得,微信支付,应该在此处检测是否支付成功,以及支付成功,把支付成功的相关参数传到数据库里。
总结一下,要说明的重点是1、签名拼接字符串时,key都需要小写 . 2、生成预支付订单前的操作放到服务器端实现更好,原因有二,其一是更快捷,其二更安全。3、微信支付后的操作,应该在自己填写的回调界面 notify_url 实现,这个回调应该在自己的服务器相关项目下。