UDN-企业互联网技术人气社区

板块导航

浏览  : 679
回复  : 2

[原生js] 微信JSAPI支付操作需要注意的细节

[复制链接]
西北的风的头像 楼主
发表于 2017-1-17 14:26:50 | 显示全部楼层 |阅读模式
  这篇文章主要介绍了微信JSAPI支付中所遇到的那些坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  首先介绍一下我在调用微信支付接口使用的是 weixin.senparc SDK,非常方便好用开源的一个微信开发SDK。
  
  weixin.senparc SDK 官网:http://weixin.senparc.com/
  
  先去下载下来Senparc.Weixin SDK。
  
  在调起支付接口之前,需要先要调用统一下单接口,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付。
  
  微信 JsApi支付 在这个目录下 Senparc.Weixin.MP.Sample.Controllers 找到JsApi支付。
 
  1. public ActionResult JsApi(string code, string state)
  2.   {
  3.    if (string.IsNullOrEmpty(code))
  4.    {
  5.     return Content("您拒绝了授权!");
  6.    }

  7.    if (!state.Contains("|"))
  8.    {
  9.     //这里的state其实是会暴露给客户端的,验证能力很弱,这里只是演示一下
  10.     //实际上可以存任何想传递的数据,比如用户ID,并且需要结合例如下面的Session["OAuthAccessToken"]进行验证
  11.     return Content("验证失败!请从正规途径进入!1001");
  12.    }
  13.    try
  14.    {


  15.     //获取产品信息
  16.     var stateData = state.Split('|');
  17.     int productId = 0;
  18.     ProductModel product = null;
  19.     if (int.TryParse(stateData[0], out productId))
  20.     {
  21.      int hc = 0;
  22.      if (int.TryParse(stateData[1], out hc))
  23.      {
  24.       var products = ProductModel.GetFakeProductList();
  25.       product = products.FirstOrDefault(z => z.Id == productId);
  26.       if (product == null || product.GetHashCode() != hc)
  27.       {
  28.        return Content("商品信息不存在,或非法进入!1002");
  29.       }
  30.       ViewData["product"] = product;
  31.      }
  32.     }

  33.     //通过,用code换取access_token
  34.     var openIdResult = OAuthApi.GetAccessToken(TenPayV3Info.AppId, TenPayV3Info.AppSecret, code);
  35.     if (openIdResult.errcode != ReturnCode.请求成功)
  36.     {
  37.      return Content("错误:" + openIdResult.errmsg);
  38.     }

  39.     string sp_billno = Request["order_no"];
  40.     if (string.IsNullOrEmpty(sp_billno))
  41.     {
  42.      //生成订单10位序列号,此处用时间和随机数生成,商户根据自己调整,保证唯一
  43.      sp_billno = string.Format("{0}{1}{2}", TenPayV3Info.MchId, DateTime.Now.ToString("yyyyMMdd"),
  44.       TenPayV3Util.BuildRandomStr(10));
  45.     }
  46.     else
  47.     {
  48.      sp_billno = Request["order_no"];
  49.     }

  50.     var timeStamp = TenPayV3Util.GetTimestamp();
  51.     var nonceStr = TenPayV3Util.GetNoncestr();

  52.     var body = product == null ? "test" : product.Name;
  53.     var price = product == null ? 100 : product.Price * 100;
  54.     var xmlDataInfo = new TenPayV3UnifiedorderRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, body, sp_billno, price, Request.UserHostAddress, TenPayV3Info.TenPayV3Notify, TenPayV3Type.JSAPI, openIdResult.openid, TenPayV3Info.Key, nonceStr);
  55.     var result = TenPayV3.Unifiedorder(xmlDataInfo);//调用统一订单接口

  56.     //JsSdkUiPackage jsPackage = new JsSdkUiPackage(TenPayV3Info.AppId, timeStamp, nonceStr,);
  57.     var package = string.Format("prepay_id={0}", result.prepay_id);

  58.     ViewData["appId"] = TenPayV3Info.AppId;
  59.     ViewData["timeStamp"] = timeStamp;
  60.     ViewData["nonceStr"] = nonceStr;
  61.     ViewData["package"] = package;
  62.     ViewData["paySign"] = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);

  63.     return View();
  64.    }
  65.    catch (Exception ex)
  66.    {
  67.     var msg = ex.Message;
  68.     msg += "<br>" + ex.StackTrace;
  69.     msg += "<br>==Source==<br>" + ex.Source;

  70.     if (ex.InnerException != null)
  71.     {
  72.      msg += "<br>===InnerException===<br>" + ex.InnerException.Message;
  73.     }
  74.     return Content(msg);
  75.    }
  76.   }
复制代码

  先在微信服务后台生成预支付交易单,获得预支付订单号。
  
  先说说在统一下单这里遇到的坑。
  
  1.在统一下单的时候解析返回结果,一直出现以下问题:您没有JSAPI支付权限
  1. <xml>
  2. <return_code><![CDATA[FAIL]]></return_code>
  3. <return_msg><![CDATA[您没有JSAPI支付权限]]></return_msg>
  4. </xml>
复制代码

  1)先看看你的公众号微信支付设置是否正确。
  
  关于如何配置微信支付:可以参考这个 http://jingyan.baidu.com/article/77b8dc7fef360d6174eab690.html
  
  2)检查你的授权目录是否正确,格式要这样,后面记得别漏了一个/   例如:http://test.cn/u/
  
  3)检查需要传过去的账户参数,上公众号还有商户号检查你的账户参数是否正确。我在开发当中就出现,微信公众号商户号,appid 是分别不同两个公众号的,坑啊,找了好久,觉得不对劲,原来是给的配置参数密钥不对。
  
  这里详细说一下对应的参数:
  
  MCHID:商户号(必须配置,开户邮件中可查看),商户申请微信支付后,由微信支付分配的商户收款账号。
  
  APPID:微信开放平台审核通过的应用APPID,appid是微信公众账号或开放平台APP的唯一标识,在公众平台申请公众账号或者在开放平台申请APP账号后,微信会自动分配对应的appid用于标识该应用。可在微信公众平台-->开发者中心查看,商户的微信支付审核通过邮件中也会包含该字段值.
  
  KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置),交易过程生成签名的密钥,仅保留在商户系统和微信支付后台,不会在网络中传播。商户妥善保管该Key,切勿在网络中传输,不能在其他客户端中存储,保证key不会被泄漏。商户可根据邮件提示登录微信商户平台进行设置。也可按一下路径设置:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置.
  
  APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置)
  
  2.在统一下单,解析返回来的结果我出现了商户号mch_id与appid不匹配这个问题
  1. <xml>
  2. <return_code><![CDATA[FAIL]]></return_code>
  3. <return_msg><![CDATA[商户号mch_id与appid不匹配]]></return_msg>
  4. </xml>
复制代码

  原因是我拿到的商户号不是这个公众号的。一定要检查是不是这个公众号的商户号。
  
  3.在统一下单,解析返回来的结果出现 appid and openid not match,appid和openid不匹配。
  1. <xml>
  2. <return_code><![CDATA[FAIL]]></return_code>
  3. <return_msg><![CDATA[appid and openid not match]]></return_msg>
  4. </xml>
复制代码

  原因是我这个用户的openid 不是这个公众号的
  
  4.在统一下单,解析返回来的结果出现 CDATA[openid is invalid],openid无效
  1. <xml>
  2. <return_code><![CDATA[FAIL]]></return_code>
  3. <return_msg><![CDATA[openid is invalid]]></return_msg>
  4. </xml>
复制代码

  原因是,传过去不是有效的opendid。不小心看错了,把用户id 当做openid传过去了。
  
  当统一下单成功,会返回以下格式的参数
  1. <xml>
  2. <return_code><![CDATA[SUCCESS]]></return_code>
  3. <return_msg><![CDATA[OK]]></return_msg>
  4. <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  5. <mch_id><![CDATA[10000100]]></mch_id>
  6. <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
  7. <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
  8. <result_code><![CDATA[SUCCESS]]></result_code>
  9. <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
  10. <trade_type><![CDATA[APP]]></trade_type>
  11. </xml>
复制代码

  解析获得预支付单号:
  
  string prepayId = res.Element("xml").Element("prepay_id").Value; //获取预支付订单号
  
  给页面对应地参数
  1. ViewData["appId"] = TenPayV3Info.AppId;
  2.     ViewData["timeStamp"] = timeStamp;
  3.     ViewData["nonceStr"] = nonceStr;
  4.     ViewData["package"] = package;
  5.     ViewData["paySign"] = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);
复制代码

  静态页面js调用:
  1. wx.chooseWXPay({
  2. timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
  3. nonceStr: '', // 支付签名随机串,不长于 32 位
  4. package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
  5. signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
  6. paySign: '', // 支付签名
  7. success: function (res) {
  8.   if (res.err_msg == "get_brand_wcpay_request:ok") {//支付成功

  9.   } else {
  10.    //支付失败

  11.   }
  12.   // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
  13. }
  14. });
复制代码

  以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
发表于 2017-1-17 14:27:23 | 显示全部楼层
总觉得哪里有点问题啊
使用道具 举报

回复

发表于 2017-1-17 14:27:24 来自手机 | 显示全部楼层
感觉JavaScript很有前途
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部