纯前端JS实现微信H5支付(微信外浏览器)

 

H5支付文档 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

1.发送请求所需要的参数

/* 
微信后台 设置的key
怎么拿到key https://jingyan.baidu.com/article/c1465413f093870bfcfc4c82.html
*/
let key = "ORM1NEK98XXXXXX3JJAITO6EB14W274ZH";
/* 支付必要参数  */
let h5Obj = {
  appid: "wxddxx8xx48c19xxxsdsbdcb", //appid
  body: "xx-商品", //商品描述
  mch_id: "1579347061", //商户号
  nonce_str: randomString(), //随机字符串,不长于32位。
  notify_url: "https://www.baidu.com/", //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
  out_trade_no: randomString(), // 订单号
  spbill_create_ip: ip, //用户的ip地址 本地不影响 127.0.0.1
  total_fee: total, //价格
  trade_type: "MWEB", // h5为MWEB 固定
  scene_info: '{"h5_info":{"type":"Wap","wap_url":"支付的域名www.baidu.com","wap_name":"订单"}}', // 信息
};

2.用户IP地址获取

// 这里使用的是souhu的 发送GET请求到 保存IP即可
let url = 'https://pv.sohu.com/cityjson?ie=utf-8'

3.如何进行sign签名?

// 1排序(ASCII)
let reStr = sortStr(h5Obj, false, key);
// 2 签名方法 获取签名
let sign = nodeMd5(reStr).toUpperCase();
// 3设置要发送的xml参数;sign放在后面
let formData = `<xml>
     <appid>${h5Obj.appid}</appid>
     <body>${h5Obj.body}</body>
     <mch_id>${h5Obj.mch_id}</mch_id>
     <nonce_str>${h5Obj.nonce_str}</nonce_str>
     <notify_url>${h5Obj.notify_url}</notify_url>
     <out_trade_no>${h5Obj.out_trade_no}</out_trade_no>
     <spbill_create_ip>${h5Obj.spbill_create_ip}</spbill_create_ip>
     <total_fee>${h5Obj.total_fee}</total_fee>
     <trade_type>${h5Obj.trade_type}</trade_type>
     <scene_info>${h5Obj.scene_info}</scene_info>
     <sign>${sign}</sign>
     </xml>`;
    return {
      h5Obj,
      formData,
    };

  (1).排序方法(根据ASCII进行)

/* 这里放一个通用方法 字节小程序也可以使用 */
/* params为排序对象 , ttKey是字节小程序key ,h5Key微信h5key */
const sortStr = (params, ttKey, h5Key) => {
  const paramKeys = Object.keys(params).sort();
  let signStr = "";
  paramKeys.forEach((key) => {
    let value = params[key];
    // 空值,risk_info, sign 不参与签名
    if (!value || ["risk_info", "sign"].indexOf(key) >= 0) {
      return;
    }
    if (signStr.length > 0) {
      signStr += "&";
    }
    if (typeof value === "object") {
      value = JSON.stringify(value);
    }
    signStr += key + "=" + value;
  });
  if (ttKey) {
    signStr += `${ttKey}`;
    return signStr;
  }
  if (h5Key) {
    signStr += "&key=" + h5Key;
    return signStr;
  }
};
export default sortStr;

(2)签名方法node版(如果不能使用 后面有js版)

const crypto = require("crypto");
const createSign = (signStr) => {
  const md5 = crypto.createHash("md5");
  const sign = md5.update(signStr).digest("hex");
  return sign;
};
export default createSign;

(3)随机字符方法

/* 随机字符串32 */
function randomString() {
  /* 去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 */
  let chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
  let maxPos = chars.length;
  let pwd = "";
  for (let i = 0; i < 32; i++) {
    pwd += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return pwd;
}
export default randomString;

4.封装支付方法 (vue可用)

//  ASCII 码排序
import sortStr from "../MD5/sortStr/sortStr";
// md5 加密
// import wxMD5 from "../MD5/md5";
import nodeMd5 from "../MD5/nodeMd5";
// 32位随机串
import randomString from "../randomString/randomString";

let h5PayFn = {
  /* 下单 */
   h5Pay(total = 100, ip = "127.0.0.1") {
     // ...h5obj
   }
}
export default h5PayFn;
// 微信h5支付
import h5PayFn from "./H5pay";
Vue.prototype.$utils = {
  ...h5PayFn,
};

5.使用

/* 这里使用的是 flyio 不要忘记ip地址  */ 
let { h5Obj, formData } = this.$utils.h5Pay(100, this.ip);
// 生成的订单号
let out = h5Obj.out_trade_no;
// 下单
this.$utils.flypost("https://api.mch.weixin.qq.com/pay/unifiedorder", formData)
   .then((res) => {
          console.log(res);
// 得到最后结果
mweb_url 进行跳转即可
   }).catch()

6.常见报错

https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4

1.商家存在未配置的参数,请联系商家解决

一般是因为微信后台未配置支付的域名 , 这个一定要注意 ,有的可能一个微信绑定多个商户号! ,要确保配置正确

 jsMD5排序

https://www.cnblogs.com/ZeroShiro/p/13305803.html

仅供参考

posted @ 2020-07-15 15:22  ZeroShiro  阅读(860)  评论(0编辑  收藏  举报