微信JSAPI支付操作需要注意的细节


Posted in Javascript onJanuary 10, 2017

首先介绍一下我在调用微信支付接口使用的是 weixin.senparc SDK,非常方便好用开源的一个微信开发SDK。

weixin.senparc SDK 官网:http://weixin.senparc.com/

先去下载下来Senparc.Weixin SDK。

在调起支付接口之前,需要先要调用统一下单接口,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付。

 微信 JsApi支付 在这个目录下 Senparc.Weixin.MP.Sample.Controllers 找到JsApi支付。

public ActionResult JsApi(string code, string state)
  {
   if (string.IsNullOrEmpty(code))
   {
    return Content("您拒绝了授权!");
   }

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


    //获取产品信息
    var stateData = state.Split('|');
    int productId = 0;
    ProductModel product = null;
    if (int.TryParse(stateData[0], out productId))
    {
     int hc = 0;
     if (int.TryParse(stateData[1], out hc))
     {
      var products = ProductModel.GetFakeProductList();
      product = products.FirstOrDefault(z => z.Id == productId);
      if (product == null || product.GetHashCode() != hc)
      {
       return Content("商品信息不存在,或非法进入!1002");
      }
      ViewData["product"] = product;
     }
    }

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

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

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

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

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

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

    return View();
   }
   catch (Exception ex)
   {
    var msg = ex.Message;
    msg += "<br>" + ex.StackTrace;
    msg += "<br>==Source==<br>" + ex.Source;

    if (ex.InnerException != null)
    {
     msg += "<br>===InnerException===<br>" + ex.InnerException.Message;
    }
    return Content(msg);
   }
  }

先在微信服务后台生成预支付交易单,获得预支付订单号。

先说说在统一下单这里遇到的坑。 

1.在统一下单的时候解析返回结果,一直出现以下问题:您没有JSAPI支付权限

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[您没有JSAPI支付权限]]></return_msg>
</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不匹配这个问题

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[商户号mch_id与appid不匹配]]></return_msg>
</xml>

原因是我拿到的商户号不是这个公众号的。一定要检查是不是这个公众号的商户号。

 3.在统一下单,解析返回来的结果出现 appid and openid not match,appid和openid不匹配。

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[appid and openid not match]]></return_msg>
</xml>

原因是我这个用户的openid 不是这个公众号的 

4.在统一下单,解析返回来的结果出现 CDATA[openid is invalid],openid无效

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[openid is invalid]]></return_msg>
</xml>

原因是,传过去不是有效的opendid。不小心看错了,把用户id 当做openid传过去了。

当统一下单成功,会返回以下格式的参数

<xml>
 <return_code><![CDATA[SUCCESS]]></return_code>
 <return_msg><![CDATA[OK]]></return_msg>
 <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
 <mch_id><![CDATA[10000100]]></mch_id>
 <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
 <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
 <result_code><![CDATA[SUCCESS]]></result_code>
 <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
 <trade_type><![CDATA[APP]]></trade_type>
</xml>

解析获得预支付单号:

string prepayId = res.Element("xml").Element("prepay_id").Value; //获取预支付订单号

给页面对应地参数

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

静态页面js调用:

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 高效运行代码分析
Mar 18 Javascript
js函数的引用, 关于内存的开销
Sep 17 Javascript
JavaScript制作的可折叠弹出式菜单示例
Apr 04 Javascript
jqGrid读取选择的多行的某个属性代码
May 18 Javascript
jquery简单的弹出层浮动层代码
Apr 27 Javascript
jQuery实现带动画效果的多级下拉菜单代码
Sep 08 Javascript
JS日期格式化之javascript Date format
Oct 01 Javascript
vuejs2.0实现一个简单的分页示例
Feb 22 Javascript
微信小程序访问node.js接口服务器搭建教程
Apr 25 Javascript
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
Apr 17 jQuery
postman自定义函数实现 时间函数的思路详解
Apr 17 Javascript
JS代码优化的8点建议
Feb 04 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
Jan 10 #Javascript
ajax实现动态下拉框示例
Jan 10 #Javascript
JavaScript三种绑定事件方式及相互之间的区别分析
Jan 10 #Javascript
详解使用Vue.Js结合Jquery Ajax加载数据的两种方式
Jan 10 #Javascript
JavaScript获取键盘按键的键码(参照表)
Jan 10 #Javascript
详解vue之页面缓存问题(基于2.0)
Jan 10 #Javascript
jQuery验证表单格式的使用方法
Jan 10 #Javascript
You might like
社区(php&amp;&amp;mysql)五
2006/10/09 PHP
PHP中文件缓存转内存缓存的方法
2011/12/06 PHP
第四章 php数学运算
2011/12/30 PHP
PHP开发工具ZendStudio下Xdebug工具使用说明详解
2013/11/11 PHP
ThinkPHP模板判断输出Empty标签用法详解
2014/06/30 PHP
PHP闭包实例解析
2014/09/08 PHP
php将文本文件转换csv输出的方法
2014/12/31 PHP
PHP MVC框架路由学习笔记
2016/03/02 PHP
java模拟PHP的pack和unpack类
2016/04/13 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
jquery sortable的拖动方法示例详解
2014/01/16 Javascript
jQuery中[attribute^=value]选择器用法实例
2014/12/31 Javascript
jQuery实现瀑布流的取巧做法分享
2015/01/12 Javascript
javascript正则表达式使用replace()替换手机号的方法
2015/01/19 Javascript
JavaScript实现的经典文件树菜单效果
2015/09/08 Javascript
Backbone View 之间通信的三种方式
2016/08/09 Javascript
JS实现简单的二元方程计算器功能示例
2017/01/03 Javascript
AngularJS实现的select二级联动下拉菜单功能示例
2017/10/25 Javascript
vue2.0 axios跨域并渲染的问题解决方法
2018/03/08 Javascript
vue 搭建后台系统模块化开发详解
2019/05/01 Javascript
js实现坦克移动小游戏
2019/10/28 Javascript
JavaScript实现刮刮乐效果
2020/11/01 Javascript
Django压缩静态文件的实现方法详析
2018/08/26 Python
Python如何使用k-means方法将列表中相似的句子归类
2019/08/08 Python
python 使用opencv 把视频分割成图片示例
2019/12/12 Python
Python中bisect的使用方法
2019/12/31 Python
Scrapy框架基本命令与settings.py设置
2020/02/06 Python
使用pandas库对csv文件进行筛选保存
2020/05/25 Python
耐克中国官方商城:Nike中国
2018/10/18 全球购物
小学生竞选班干部演讲稿
2014/04/24 职场文书
中秋晚会活动方案
2014/08/31 职场文书
2014年服务员个人工作总结
2014/12/23 职场文书
后勤工作个人总结
2015/02/28 职场文书
2015年八一建军节慰问信
2015/03/23 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
python 解决微分方程的操作(数值解法)
2021/05/26 Python