您当前的位置: 首页 > 知识百科 > 微信小程序企业支付怎么开发?

微信小程序企业支付怎么开发?

时间:2023-07-01 14:05 阅读数:20 人阅读 分类:知识百科

  很多公司在开发微信小程序之后都会用到支付功能,那么微信小程序企业支付要怎么弄呢?具体需要注意一些什么内容?今天小编就为大家详细介绍一下。

  当然在开发之前,我们需要有下面这些东西:

  appId

  密钥(小程序界面)

  商户号

  api密钥(商家后台自己设置)

  当然这些是不用我们自己申请的,公司会有人申请好,然后要什么跟这个人说,让他提供就可以了。

  首先来看一下官方给出的业务流程时序图

  这个图很清晰的表达了在小程序支付中的整个流程,每一步要做些什么。

  一个完整的支付,一般情况下都是包含了下面三个主要的点;

  支付(正常是支付平台提供的h5页面让用户操作,主要是输密码)

  通知(用户完成一笔支付了,支付平台要通知商家支付结果,商家收到结果后进行一些相应的处理)

  查询(与第二点有点反过来的意思,商家自己主动去支付平台查询支付的结果,然后根据结果做相应的处理)

  下面就重点来简单实现一下上面说的第一点,支付,也是可以进行下面两步的在大前提。

  支付的简单实现

  小程序的实现

  简单起见,在index.wxml中添加一个输入框和一个button,绑定一下相应的事件,输入框主要是用于输入订单号,按钮用于模拟提交一个订单并发起支付。

  立即支付

  然后在index.js中写上一小段小程序开发代码,主要是处理上面按钮的点击事件。

  Page({

  data: {

  txtOrderCode: ''

  },

  pay: function () {

  var ordercode = this.data.txtOrderCode;

  wx.login({

  success: function (res) {

  if (res.code) {

  wx.request({

  url: '.yourdomain/pay',

  data: {

  code: res.code,//要去换取openid的登录凭证

  ordercode: ordercode

  },

  method: 'GET',

  success: function (res) {

  console.log(res.data)

  wx.requestPayment({

  timeStamp: res.data.timeStamp,

  nonceStr: res.data.nonceStr,

  package: res.data.package,

  signType: 'MD5',

  paySign: res.data.paySign,

  success: function (res) {

  // success

  console.log(res);

  },

  fail: function (res) {

  // fail

  console.log(res);

  },

  complete: function (res) {

  // complete

  console.log(res);

  }

  })

  }

  })

  } else {

  console.log('获取用户登录态失败!' + res.errMsg)

  }

  }

  });

  },

  getOrderCode: function (event) {

  this.setData({

  txtOrderCode: event.detail.value

  });

  }

  })

  可以看到,在这里Catcher先通过wx.login这个API先取到了登录的凭证code,并把这个凭证code做为请求参数用wx.request这个API发起一个网络请求。

  在这个网络请求处理后会返回小程序支付所需要的相关参数。拿到这些参数后,再调用wx.requestPayment这个支付API,此时才算是真正的发起支付。

  至此,小程序这边的事已经做完了,接下来就是要去处理接口那边的事了,其实接口要做的就是返回小程序需要的几个参数。但是要拿到这几个参数还是需要做不少事情的。

  接口的实现

  据悉最新版的Senparc.Weixin.MP已经支付了小程序相关的内容,但是公司用的版本还是比较低

  并且近期也没有打算对这个组件进行升级。所以就从白纸一张开始了。

  用的是mvc,所以这个小程序发起的网络请求会由下面的action的执行,里面的实现,每一步做了什么应该也已经很清晰了。

  public ActionResult Pay(string code, string ordercode)

  {

  var paramter = new Parameters();

  paramter.out_trade_no = ordercode;

  //使用登录凭证 code 获取 session_key 和 openid

  var unifiedorderRes = GetOpenIdAndSessionKey(paramter.appid, paramter.secret, code);

  //反序列化session_key 和 openid成ChangeResponseEntity实体

  var tmp = JsonConvert.DeserializeObject(unifiedorderRes);

  //统一下单的url和参数

  var payUrl = "api.mch.weixin.qq/pay/unifiedorder";

  var param = GetUnifiedOrderParam(tmp.openid, paramter);

  //统一下单后拿到的xml结果

  var payResXML = Helper.DoPost(param, payUrl);

  var payRes = XDocument.Parse(payResXML);

  var root = payRes.Element("xml");

  //序列化相应参数返回给小程序

  var res = GetPayRequestParam(root, paramter.appid, paramter.key);

  return Json(res, JsonRequestBehavior.AllowGet);

  }

  由于只是一个演示的过程,不想这些数据经常以字符串的形式频繁出现在代码中,所以把相关的参数全部都放到了一个名为Parameters的类中(放到配置文件中也是可以的),除了订单号是从小程序传过来的,当然在实际中这是不合理的,毕竟像金额这些东西,不可能每次都是同一个!这点是要注意的。

  下面先来看看这个Parameters类的定义:

  public class Parameters

  {

  public string appid { get { return "申请的appid"; } }

  public string mchid { get { return "申请的商户号"; } }

  public string nonce { get { return Helper.GetNoncestr(); } }

  public string notify_url { get { return "yourdomain/notifyurl"; } }

  public string body { get { return "testpay"; } }

  public string out_trade_no { get; set; }

  public string spbill_create_ip { get { return "IP地址"; } }

  public string total_fee { get { return "1"; } }

  public string trade_type { get { return "JSAPI"; } }

  public string key { get { return "在商家后台设置的密钥"; } }

  public string secret { get { return "在配置小程序时的密钥"; } }

  }

  首先是获取到登录凭证后发起的这个网络请求。这个网络请求是决定了这次支付能否成功的第一步!

  下面要做的是用登录凭证去换我们要的openid。

  ///

  /// 取openid和session_key

  ///

  ///

  ///

  ///

  ///

  private string GetOpenIdAndSessionKey(string appid, string secret, string js_code)

  {

  var url = string.Format("api.weixin.qq/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code"

  , appid,secret,js_code);

  var request = WebRequest.Create(url) as HttpWebRequest;

  var response = request.GetResponse();

  var respStream = response.GetResponseStream();

  var res = string.Empty;

  using (var reader = new StreamReader(respStream, Encoding.UTF8))

  {

  res = reader.ReadToEnd();

  }

  return res;

  }

  要换取openid,就要向微信提供的地址发起一个网络请求,并在URL带上appid,secret和凭证code这三个参数。

  然后就可以拿到一个下面形式的json字符串

  {

  "openid": "OPENID",

  "session_key": "SESSIONKEY"

  }

  拿到之后自然就是要对这个字符串进行json的反序列化,这里用到了json这个包。

  根据时序图,下面要调用统一下单这个接口了。

  上面的代码,在统一下单这一块,又分为下面几个步骤

  处理统一下单的参数(签名和组装xml)

  发起POST请求

  解析请求得到的结果

  参数的处理:

  具体规则参见:pay.weixin.qq/wiki/doc/api/wxa/wxa_api.php?chapter=4_3

  ///

  /// 取统一下单的请求参数

  ///

  ///

  ///

  ///

  private string GetUnifiedOrderParam(string openid, Parameters param)

  {

  //参与统一下单签名的参数,除最后的key外,已经按参数名ASCII码从小到大排序

  var unifiedorderSignParam = string.Format("appid={0}&body={1}&mch_id={2}&nonce_str={3}¬ify_url={4}&openid={5}&out_trade_no={6}&spbill_create_ip={7}&total_fee={8}&trade_type={9}&key={10}"

  , param.appid, param.body, param.mchid, param.nonce, param.notify_url

  , openid, param.out_trade_no, param.spbill_create_ip, param.total_fee, param.trade_type, param.key);

  //MD5

  var unifiedorderSign = Helper.GetMD5(unifiedorderSignParam).ToUpper();

  //构造统一下单的请求参数

  return string.Format(@"

  ", param.appid, param.body, param.mchid, param.nonce, param.notify_url, openid

  , param.out_trade_no, param.spbill_create_ip, param.total_fee, param.trade_type, unifiedorderSign);

  }

  这里要注意一点,由于我们的传的trade_type是JSAPI,所以这里必须是要加上openid进行处理的。

  然后就是解析统一下单返回的XML了,说是解析,其实也就是要拿到我们需要的数据罢了。这里最后会得到一个小程序支付API需要的参数实体。

  ///

  /// 获取返回给小程序的支付参数

  ///

  ///

  ///

  ///

  ///

  private PayRequesEntity GetPayRequestParam(XElement root,string appid,string key)

  {

  //当return_code 和result_code都为SUCCESS时才有我们要的prepay_id

  if (root.Element("return_code").Value == "SUCCESS" && root.Element("result_code").Value == "SUCCESS")

  {

  var package = "prepay_id=" + root.Element("prepay_id").Value;

  var nonceStr = Helper.GetNoncestr();

  var signType = "MD5";

  var timeStamp = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString();

  var paySignParam = string.Format("appId={0}&nonceStr={1}&package={2}&signType={3}&timeStamp={4}&key={5}",

  appid, nonceStr, package, signType, timeStamp, key);

  var paySign = Helper.GetMD5(paySignParam).ToUpper();

  var payEntity = new PayRequesEntity

  {

  package = package,

  nonceStr = nonceStr,

  paySign = paySign,

  signType = signType,

  timeStamp = timeStamp

  };

  return payEntity;

  }

  return new PayRequesEntity();

  }

  支付参数实体对应的内容如下:

  ///

  /// 小程序支付需要的参数

  ///

  public class PayRequesEntity

  {

  ///

  /// 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间

  ///

  public string timeStamp { get; set; }

  ///

  /// 随机字符串,长度为32个字符以下。

  ///

  public string nonceStr { get; set; }

  ///

  /// 统一下单接口返回的 prepay_id 参数值

  ///

  public string package { get; set; }

  ///

  /// 签名算法

  ///

  public string signType { get; set; }

  ///

  /// 签名

  ///

  public string paySign { get; set; }

  }

  需要注意的是,这里的签名操作,一定是要配合appId,这也是Catcher在支付这一块踩的唯一的一个坑,所以提醒一下各位读者,希望能避开这个坑。

  支付,对于企业来说可以说是占据了十分重要的一块,毕竟能收到钱才是重点。那么微信小程序企业支付怎么开发你现在知道了吗?更多相关资料请持续关注微信小程序素材网。

  

  小程序微信支付可以公对私付款功能

  小程序微信支付源码是怎样的呢?

  微信小程序支付功能怎么开发