C#+Hybrid App(Android)实现微信APP支付
之前一直在做Hybrid App(也就是用Android或者IOS的WebView控件嵌入你的H5应用,看起来跟原生应用一样),支付这块有用到第三方的WAP支付,效果还行,就是微信这块收款不能直接跟客户的账户对接,因为WebView允许H5应用利用Javascript呼叫原生应用,所以决定开发Hybrid App下的微信APP支付。
开发微信APP支付,首先要看腾讯给的开发文档。由于新旧接口差异巨大,所以走了不少弯路(大家说微信开发就是一个巨坑也是有道理),但最重要看官方文档,照着他的文档走应该是没错的,只是有些细节不完整。
好,闲话有点多,开始转入正题。微信APP支付大概流程是:服务器端生成预支付ID,然后APP端取得预支付ID后丢给微信SDK去呼叫微信支付。要进行微信APP支付开发,首先得通过微信公众号认证,然后注册开放平台,最后注册商户平台。公众号是基础,开放平台是管理APP信息的,商户平台相当于支付宝,是管理钱的地方。
开发前的准备
微信公众平台:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN
微信开放平台:https://open.weixin.qq.com/
微信商户平台:https://pay.weixin.qq.com/index.php/home/login
开发文档:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_1
公众平台应该是必备的,要申请服务号,每年300块钱。
开放平台是创建应用的地方,生成AppID后面会用到,如下图:
商户平台有两个东西会用到,一个是Partner ID,就是微信支付商户号;一个是Key,就是对商户平台的登录密码进行MD5加密后得到的字串,到API安全>>API密钥>>设置密钥,把这个MD5字串填进去保存就行了,如下图:
1.Android原生应用加入微信SDK
这一步很简单,只要把微信SDK引入你的项目,然后调用就可以了,如下图:
调用代码如下:
@JavascriptInterfacepublic void setWxPay(String appId,String partnerId,String prepayId,String nonceStr,String timeStamp,String packageValue,String sign) {api = WXAPIFactory.createWXAPI(this, appId);api.registerApp(appId);//注册APP到微信Toast.makeText(MainActivity.this, "获取订单中,请稍等...", Toast.LENGTH_SHORT).show(); try{if(appId!="" && prepayId!=""){PayReq req = new PayReq();req.appId= appId;req.partnerId= partnerId;req.prepayId= prepayId;req.nonceStr= nonceStr;req.timeStamp= timeStamp;req.packageValue= packageValue;req.sign= sign;req.extData= "app data";Toast.makeText(MainActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();api.sendReq(req);}else{ Log.d("PAY_GET", "服务器请求错误"); Toast.makeText(MainActivity.this, "服务器请求错误", Toast.LENGTH_SHORT).show();} }catch(Exception e){ Log.e("PAY_GET", "异常:"+e.getMessage()); Toast.makeText(MainActivity.this, "异常:"+e.getMessage(), Toast.LENGTH_SHORT).show(); }}
2.服务器端生成预支付ID(prepay_id),并调起支付接口
这一步是最重要也是最容易出问题的地方,错一个小小的地方也可能导致发起支付失败。
服务器端是用C#写的,因为我的H5应用也是C#写的(有点废话)。当我H5应用里一件商品下单后,先生成一条订单记录,状态还是未支付的,这时候已经有了商品的名称、价格等商品信息。我们用这个商品的信息发送给微信支付,让它先生成一个预支付的订单,这个叫“统一下单”。
这里用到了网上大神的一些代码,原文是:http://www.cnblogs.com/vinsonLu/p/4345041.html
主要代码如下:
/// /// 支付方法 /// private void WxPay() { string appId = "这里填AppID"; string partnerId = "这里填微信支付商户号"; string key = "这里填MD5加密的字串"; string body = txtProductName.Text.Trim(); string orderNumber = DateTime.Now.ToString("yyyyMMddHHmmss"); int price = int.Parse(txtPrict.Text.Trim()); UnifiedOrder order = new UnifiedOrder(); order.appid = appId; order.mch_id = partnerId; order.nonce_str = TenpayUtil.getNoncestr(); order.body = body; order.out_trade_no = orderNumber; order.total_fee = price; //单位是分 order.spbill_create_ip = Page.Request.UserHostAddress; order.notify_url = "http://www.yourdomain.com/notify.aspx"; order.trade_type = "APP"; TenpayUtil tu = new TenpayUtil(); string prepayId = tu.getPrepay_id(order, key); string nonceStr = order.nonce_str; string timeStamp = TenpayUtil.getTimestamp(); string packageValue = "Sign=WXPay"; SortedDictionary sParams = new SortedDictionary(); sParams.Add("appid", appId); sParams.Add("noncestr", nonceStr); sParams.Add("package", packageValue); sParams.Add("partnerid", partnerId); sParams.Add("prepayid", prepayId); sParams.Add("timestamp", timeStamp); string sign = tu.getsign(sParams, key); //调用前台JS RunScript(this, "", "SetWxPay('" + appId + "','" + partnerId + "','" + prepayId + "','" + nonceStr + "','" + timeStamp + "','" + packageValue + "','" + sign + "');"); } /// /// 执行一条JavaScript函数 /// /// WEB窗体页 /// 标示脚本块的唯一键 /// 脚本内容 public static void RunScript(System.Web.UI.Page page, string key, string script) { page.ClientScript.RegisterStartupScript(page.GetType(), key, ""); }
3.获取微信支付结果返回信息
当你支付后,微信会将支付结果以XML的方式返回给你指定的路径,上面写的是http://www.yourdomain.com/notify.aspx,这个地址必须是可以访问的,并且不能带参数。
特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,防止数据泄漏导致出现“假通知”,造成资金损失。
主要代码如下:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string data = ""; try { //接收并读取POST过来的XML文件流 StreamReader reader = new StreamReader(Request.InputStream); String xmlData = reader.ReadToEnd(); data = xmlData; } catch { } if (GetWxKeyValue(data, "return_code") == "SUCCESS") { //这里是支付成功的信息,下面你可以自由发挥了,比如写入数据库,更改状态等 //其他信息请参考https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_7&index=3 } } } private string GetWxKeyValue(string data, string key) { string value = ""; SortedDictionary requestXML = GetInfoFromXml(data); foreach (KeyValuePair k in requestXML) { if (k.Key == key) { value = k.Value; break; } } return value; } /// /// 把XML数据转换为SortedDictionary集合 /// /// /// protected SortedDictionary GetInfoFromXml(string xmlstring) { SortedDictionary sParams = new SortedDictionary(); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlstring); XmlElement root = doc.DocumentElement; int len = root.ChildNodes.Count; for (int i = 0; i < len; i++) { string name = root.ChildNodes[i].Name; if (!sParams.ContainsKey(name)) { sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim()); } } } catch { } return sParams; }
到此,微信支付就可以工作了,至于查询订单、退款的以后有时间再研究。
源码下载:http://pan.baidu.com/s/1mhtW7cG
更多相关文章
- 【BUG修补匠】 Android微信支付返回码-1之坑(首次调用成功第二次
- Android上HDMI介绍(基于高通平台)-- Overlay
- 官宣:微软Cortana或将退出Android/iOS两大平台
- 腾讯云实时音视频终端组件 TRTC SDK,覆盖 iOS、Android、Windows
- Termux 详解—— Android(安卓)平台上完美移植的 Linux 工具集
- Android智能手机被用于僵尸网络?智能移动平台安全问题日渐突显
- 2012 年新推出的 Android(非游戏)应用中,哪些最值得称道?
- Android(安卓)弹无虚发之第一弹:Android(安卓)2.X平台完美兼容Act
- 究竟为什么开发者首选 iOS ?