1.简单H5模块(qrcode ajax jqury js md5 aes)

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta name="viewport"
    5. content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no, viewport-fit=cover" />
    6. <meta charset="UTF-8">
    7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    8. <title>众成鑫富</title>
    9. </head>
    10. <body>
    11. <div id="main">
    12. <header>
    13. 微信支付
    14. </header>
    15. <main>
    16. <div class="iptBox">
    17. <input type="text" placeholder="请输入您的充值号码!" id="ipt">
    18. <div class="info">
    19. <span class="errTip"></span>
    20. </div>
    21. </div>
    22. <div class="pro" id="qrcode" ref="qrcode"></div>
    23. <div class="check">充值价格: <span>10.00</span>元</div>
    24. </main>
    25. <footer>
    26. <button id="payBtn">生成支付码</button>
    27. </footer>
    28. </div>
    29. <script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
    30. <script src="https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.19.0/js/md5.js"></script>
    31. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    32. <script src="https://cdn.bootcdn.net/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
    33. <script>
    34. // 设置全局延迟调用时长
    35. const waitDuration = 500;
    36. // 请求地址baseUrl
    37. const baseUrl = "http://192.168.9.34:8001";
    38. // 设置AES加密key
    39. const aesKey = "wRdSzczXttHFtXyC";
    40. // 设置appSecret
    41. const appSecret = "6cd8132a04df9592bf8fadca6061d939";
    42. // 设置appid(支付)
    43. const payAppId = "9t3f2twrcpl";
    44. // 设置version版本
    45. const version = "v1.0";
    46. // 设置二维码生成链接
    47. var codeUrl;
    48. // appid=23raqkwr9ll
    49. // appsecret=f8d81572105cb719bb1a1ecfd7fed244
    50. // aeskey=eKJTNaCswmaikbZQ
    51. // 获取dom节点,为按钮绑定点击事件(加入节流功能函数)
    52. var payBtn = document.querySelector('#payBtn');
    53. var telPhoneVal = document.querySelector('#ipt');
    54. var errTip = document.querySelector('.errTip');
    55. var qrcodeBox = document.getElementById('qrcode');
    56. let pp = document.createElement('p');
    57. pp.innerHTML = "支付二维码展示窗口";
    58. document.querySelector('#qrcode').appendChild(pp);
    59. // 定义两个缓存值(充值账号)
    60. var firstLen = 0;
    61. var lastLen = 0;
    62. var reg = /^1(3|4|5|7|8)\d{9}$/;
    63. // 支付按钮触发点击事件
    64. payBtn.addEventListener("click", clickFn(clickEvent, waitDuration));
    65. // 节流功能函数,防止用户多次触发
    66. function clickFn(fn, delay) {
    67. let timer;
    68. return function () { // 这里是标签的点击事件调用该匿名函数,所以该匿名函数指向fn的DOM节点
    69. if (timer) {
    70. return;
    71. }
    72. let that = this;
    73. let arg = arguments;
    74. timer = setTimeout(function () {
    75. fn.apply(that, arg);
    76. timer = null;
    77. }, delay)
    78. }
    79. };
    80. // 支付函数,以下为支付业务功能代码
    81. function clickEvent() {
    82. // !!! 再点击支付的时候删除#qrcode下面的所有子节点
    83. if (qrcodeBox.childNodes) {
    84. for (var i = qrcodeBox.childNodes.length - 1; i >= 0; i--) {
    85. qrcodeBox.removeChild(qrcodeBox.childNodes[i]);
    86. }
    87. };
    88. qrcodeBox.style.border="1px solid #007aff";
    89. // 请求之前创建节点告知用户二维码正在加载
    90. let pp = document.createElement('p');
    91. pp.innerHTML = "支付二维码正在生成中...";
    92. document.querySelector('#qrcode').appendChild(pp);
    93. // 设置支付参数
    94. const data = {
    95. openId: Math.random().toString(36).substr(2),
    96. merPayOrderId:Math.random().toString(36).substr(2),
    97. // merPayOrderId: '2423hf2434l3lfsdk',
    98. amount: 1,
    99. desc: "测试支付"
    100. };
    101. // 设置参数加密
    102. var encrypt = CryptoJS.AES.encrypt(JSON.stringify(data), CryptoJS.enc.Utf8.parse(aesKey), {
    103. mode: CryptoJS.mode.ECB,
    104. padding: CryptoJS.pad.Pkcs7
    105. }).toString();
    106. // 设置参数解密
    107. var decrypt = CryptoJS.AES.decrypt(encrypt, CryptoJS.enc.Utf8.parse(aesKey), {
    108. mode: CryptoJS.mode.ECB,
    109. padding: CryptoJS.pad.Pkcs7
    110. }).toString(CryptoJS.enc.Utf8);
    111. // 设置请求参数(获取微信支付二维码)
    112. const postOBj = {
    113. timestamp: new Date().valueOf(),
    114. edata: encrypt,
    115. sign: md5(JSON.stringify(data) + (new Date().valueOf()) + appSecret),
    116. appid: payAppId,
    117. version: version
    118. };
    119. // 原生请求跨域!!!!!!!!!!! this question comes from back-end;
    120. $.ajax({
    121. url: "http://192.168.9.34:8001/api/pay",
    122. type: "POST",
    123. dataType: "json",
    124. headers: {
    125. "content-type": 'application/json'
    126. },
    127. contentType: 'application/json',
    128. data: JSON.stringify(postOBj),
    129. success: function (res) {
    130. console.log(res, '响应数据');
    131. if (res.code == 10) {
    132. setTimeout(() => {
    133. if (qrcodeBox.childNodes) {
    134. for (var i = qrcodeBox.childNodes.length - 1; i >= 0; i--) {
    135. qrcodeBox.removeChild(qrcodeBox.childNodes[i]);
    136. }
    137. };
    138. qrcodeBox.style.border="1px solid transparent";
    139. // new QRCode(document.getElementById("codeBox"), res.data.QrcodeUrl); // 设置要生成二维码的链接(便捷式生成无法设置宽高)
    140. var qrcode = new QRCode('qrcode', {
    141. text: res.data.QrcodeUrl ? res.data.QrcodeUrl : '',
    142. width: 256,
    143. height: 256,
    144. colorDark: '#000000',
    145. colorLight: '#ffffff',
    146. correctLevel: QRCode.CorrectLevel.Q
    147. });
    148. qrcode.makeCode();
    149. }, 1000);
    150. } else {
    151. setTimeout(() => {
    152. if (qrcodeBox.childNodes) {
    153. for (var i = qrcodeBox.childNodes.length - 1; i >= 0; i--) {
    154. qrcodeBox.removeChild(qrcodeBox.childNodes[i]);
    155. }
    156. };
    157. let pp = document.createElement('p');
    158. pp.innerHTML = "支付码生成失败,请重新支付!";
    159. document.querySelector('#qrcode').appendChild(pp);
    160. }, 1000);
    161. }
    162. },
    163. error: function (err) {
    164. console.log(err);
    165. }
    166. });
    167. };
    168. // 手机号验证
    169. telPhoneVal.oninput = function () {
    170. telPhoneVal.value = telPhoneVal.value.substr(0, 13); //只允许输入11位+2个空格
    171. //用户输入满11位开始验证
    172. if (telPhoneVal.value.length == 13) {
    173. //将数据去掉空格后验证
    174. if (!reg.test(telPhoneVal.value.replace(/\s/g, ''))) {
    175. errTip.innerHTML = '*' + ' ' + '您输入的手机账号有误,请重新输入'
    176. } else {
    177. errTip.innerHTML = ''
    178. }
    179. } else {
    180. errTip.innerHTML = ''
    181. }
    182. };
    183. // 手机号四位分割
    184. telPhoneVal.onfocus = function () {
    185. timer = setInterval(function () {
    186. lastLen = telPhoneVal.value.length;
    187. if (lastLen > firstLen) {
    188. firstLen = telPhoneVal.value.length;
    189. if (lastLen === 4 || lastLen === 9) {
    190. var temp1 = telPhoneVal.value.substr(0, telPhoneVal.value.length - 1);
    191. var temp2 = telPhoneVal.value.substr(telPhoneVal.value.length - 1);
    192. telPhoneVal.value = temp1 + ' ' + temp2;
    193. }
    194. } else if (lastLen <= firstLen) {
    195. if (lastLen === 4 || lastLen === 9) {
    196. telPhoneVal.value = telPhoneVal.value.substr(0, telPhoneVal.value.length - 1);
    197. }
    198. firstLen = telPhoneVal.value.length;
    199. }
    200. }, 10); //如果手机出现卡顿,可适当把定时器时间加大
    201. };
    202. </script>
    203. <style>
    204. * {
    205. padding: 0;
    206. margin: 0;
    207. }
    208. body,
    209. html {
    210. width: 100%;
    211. height: 100%;
    212. }
    213. #main {
    214. width: 100%;
    215. height: 100%;
    216. background-color: #f2f2f2;
    217. display: flex;
    218. justify-content: space-between;
    219. flex-wrap: nowrap;
    220. flex-direction: column;
    221. }
    222. header {
    223. height: 30px;
    224. width: 100%;
    225. background-color: #5298e4;
    226. display: flex;
    227. justify-content: center;
    228. align-items: center;
    229. font-size: 16px;
    230. font-family: 'Courier New', Courier, monospace;
    231. color: #fff;
    232. font-weight: bolder;
    233. letter-spacing: 1px;
    234. }
    235. main {
    236. flex: 1;
    237. width: 100%;
    238. height: 100%;
    239. overflow-y: scroll;
    240. background: #fff;
    241. }
    242. .iptBox {
    243. display: flex;
    244. height: 20%;
    245. width: 100%;
    246. flex-direction: column;
    247. justify-content: center;
    248. align-items: center;
    249. padding: 5px 0px;
    250. box-sizing: border-box;
    251. }
    252. .iptBox input {
    253. display: inline;
    254. height: 50px;
    255. width: 90%;
    256. outline: none;
    257. border: none;
    258. font-size: 26px;
    259. font-weight: bolder;
    260. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    261. border-radius: none !important;
    262. }
    263. .info {
    264. width: 90%;
    265. margin: 0 auto;
    266. border-top: 1px solid #87aacf;
    267. height: 40px;
    268. margin-top: 5px;
    269. color: #f55c64;
    270. font-size: 13px;
    271. padding-top: 18px;
    272. }
    273. .pro {
    274. width: 256px;
    275. margin: 0 auto;
    276. margin-top: 15px;
    277. display: flex;
    278. justify-content: center;
    279. align-items: center;
    280. height: 256px;
    281. border: 1px solid #007aff;
    282. }
    283. #qrcode>>>canvas {
    284. width: 250px !important;
    285. height: 250px !important;
    286. }
    287. #qrcode>>>img {
    288. width: 250px !important;
    289. height: 250px !important;
    290. }
    291. #qrcode p {
    292. font-size: 18px;
    293. color: #666;
    294. font-family: '楷体';
    295. font-weight: 600;
    296. }
    297. .check {
    298. padding: 10px 5%;
    299. box-sizing: border-box;
    300. font-size: 16px;
    301. color: #333;
    302. font-family: '楷体';
    303. margin-top: 30px;
    304. }
    305. .check span {
    306. font-size: 22px;
    307. color: #007aff;
    308. }
    309. footer {
    310. width: 100%;
    311. background-color: rgba(255, 255, 255, 0.4);
    312. display: flex;
    313. justify-content: center;
    314. align-items: center;
    315. padding: 15px 0px 24px 0px;
    316. box-sizing: border-box;
    317. }
    318. button {
    319. width: 160px;
    320. line-height: 38px;
    321. text-align: center;
    322. font-weight: bold;
    323. color: #fff;
    324. text-shadow: 1px 1px 1px #333;
    325. border-radius: 5px;
    326. position: relative;
    327. overflow: hidden;
    328. border: 1px solid #007aff;
    329. box-shadow: 0 1px 2px #388ae2 inset, 0 -1px 0 #498fda inset, 0 -2px 3px #b9ecc4 inset;
    330. background: -webkit-linear-gradient(top, #2880dd, #6289b3);
    331. background: -moz-linear-gradient(top, #2b85e6, #2680e0);
    332. background: linear-gradient(top, #3987db, #438ddb);
    333. }
    334. button:hover {
    335. background: -webkit-linear-gradient(top, #40e048, #2fcc7d);
    336. background: -moz-linear-gradient(top, #40e048, #2fcc7d);
    337. background: linear-gradient(top, #40e048, #2fcc7d);
    338. }
    339. input::-webkit-input-placeholder {
    340. /* WebKit browsers*/
    341. color: #ccc;
    342. font-size: 14px;
    343. letter-spacing: 1px;
    344. display: table-cell;
    345. vertical-align: top;
    346. font-style: oblique;
    347. padding-left: 2px;
    348. font-family: '楷体';
    349. }
    350. input:-moz-input-placeholder {
    351. /* Mozilla Firefox 4 to 18*/
    352. color: #ccc;
    353. font-size: 14px;
    354. letter-spacing: 1px;
    355. display: table-cell;
    356. vertical-align: top;
    357. font-style: oblique;
    358. font-family: '楷体';
    359. }
    360. input::-moz-input-placeholder {
    361. /* Mozilla Firefox 19+*/
    362. color: #ccc;
    363. font-size: 14px;
    364. letter-spacing: 1px;
    365. display: table-cell;
    366. vertical-align: top;
    367. font-style: oblique;
    368. font-family: '楷体';
    369. }
    370. input:-ms-input-placeholder {
    371. /* Internet Explorer 10+*/
    372. color: #ccc;
    373. letter-spacing: 1px;
    374. font-size: 14px;
    375. display: table-cell;
    376. vertical-align: top;
    377. font-style: oblique;
    378. font-family: '楷体';
    379. }
    380. </style>
    381. </body>
    382. </html>