lrf402788946 4 rokov pred
rodič
commit
6dbca36606
8 zmenil súbory, kde vykonal 135 pridanie a 14 odobranie
  1. 1 0
      .gitignore
  2. 20 0
      app/controller/wxpay.js
  3. 2 0
      app/router.js
  4. 11 8
      app/service/qrcode.js
  5. 1 0
      app/service/util.js
  6. 93 0
      app/service/wxpay.js
  7. 3 5
      config/plugin.js
  8. 4 1
      package.json

+ 1 - 0
.gitignore

@@ -12,3 +12,4 @@ run/
 *.un~
 typings/
 .nyc_output/
+cert/

+ 20 - 0
app/controller/wxpay.js

@@ -0,0 +1,20 @@
+'use strict';
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 微信支付部分
+class WxpayController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.wxpay;
+  }
+  async toAuth() {
+    const res = await this.service.toAuth(this.ctx.query);
+    this.ctx.ok({ data: res });
+  }
+  async cash() {
+    const res = await this.service.cash(this.ctx.query);
+    this.ctx.ok({ data: res });
+  }
+}
+module.exports = CrudController(WxpayController, {});

+ 2 - 0
app/router.js

@@ -13,6 +13,8 @@ module.exports = app => {
   router.post(`${prefix}/login`, controller.login.login);
   // 工具函数
   router.post(`${prefix}/util`, controller.util.utilMethod);
+  router.get(`${prefix}/wxpay/auth`, controller.wxpay.toAuth);
+  router.get(`${prefix}/wxpay/cash`, controller.wxpay.cash);
   require('./router/card')(app); // 办卡
   require('./router/cash')(app); // 提现
   require('./router/record')(app); // 记录

+ 11 - 8
app/service/qrcode.js

@@ -13,18 +13,21 @@ class QrcodeService extends CrudService {
     this.uri = 'http://www.baidu.com/';
   }
 
-  async initQRCode({ id }) {
-    assert(id, '缺少推荐人信息');
-    const user = await this.model.findById(id);
-    if (!user) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '为找到用户信息');
-    const { mobile, name } = user;
+  async initQRCode({ id = 'a' }) {
+    // assert(id, '缺少推荐人信息');
+    // const user = await this.model.findById(id);
+    // if (!user) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '为找到用户信息');
+    // const { mobile, name } = user;
+    const mobile = '13089419810',
+      name = 'liuruifeng';
     const url = `${this.uri}?id=${id}&mobile=${mobile}&name=${name}`;
     // const res = await QRCode.toDataURL(url, {
     //   width: 200,
     // });
-    const qrcode = await QRCode.toString(url, { type: 'png' });
-    const qrimage = `data:image/png;base64${Buffer(qrcode).toString('base64')}`;
-    return qrimage;
+    const qrcode = await QRCode.toFile(url);
+    // const qrcode = await QRCode.toString(url, { type: 'png' });
+    // const qrimage = `data:image/png;base64${Buffer(qrcode).toString('base64')}`;
+    return qrcode;
   }
 }
 

+ 1 - 0
app/service/util.js

@@ -15,6 +15,7 @@ class UtilService extends CrudService {
     this.set = this.ctx.model.Set;// 套餐
   }
   async utilMethod(query, body) {
+    console.log(await this.app.redis.get('5ff575b0a3f2771eb4d03114'));
     // this.initSetSeed();
     // console.log('in function:');
     // const file = await this.ctx.curl('https://vd3.bdstatic.com/mda-kar9n2ip1u508ewq/hd/mda-kar9n2ip1u508ewq.mp4');

+ 93 - 0
app/service/wxpay.js

@@ -0,0 +1,93 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+const random = require('string-random');
+const moment = require('moment');
+const crypto = require('crypto');
+const xml2js = require('xml2js');
+const fs = require('fs');
+// wxpay
+class WxpayService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'wxpay');
+    // this.model = this.ctx.model.Wxpay;
+    this.appInfo = this.app.config.appInfo;
+    this.redis = this.app.redis;
+  }
+
+  async toAuth({ code, id }) {
+    const token = await this.redis.get(id);
+    if (token) return;
+    const url = ({ id, secret }) => `https://api.weixin.qq.com/sns/jscode2session?appid=${id}&secret=${secret}&js_code=${code}&grant_type=authorization_code`;
+    const res = await this.ctx.curl(url(this.appInfo), {
+      method: 'get',
+      dataType: 'json',
+    });
+
+    const info = JSON.stringify(res.data);
+    await this.redis.set(id, info, 'EX', 3600);
+  }
+
+  async cash({ id, name, money }) {
+    const token = await this.redis.get(id);
+    if (!token) throw new BusinessError(ErrorCode.SERVICE_FAULT, '未找到用户的openid,请重新登陆小程序!');
+    const { openid } = JSON.parse(token);
+    if (!this.appInfo) throw new BusinessError(ErrorCode.FILE_FAULT, '未设置小程序相关设置');
+    // check_name:校验真名,暂不校验
+    const object = { amount: money, check_name: 'NO_CHECK', desc: '提现', mch_appid: this.appInfo.id, mchid: this.appInfo.store, nonce_str: random(16), openid, partner_trade_no: `cash${moment().format('YYYYMMDDHHmmss')}${random(12)}`, re_user_name: name };
+    const clientIp = _.get(this.ctx.request, 'header.x-real-ip');
+    if (clientIp) object.spbill_create_ip = clientIp;
+    const sign = this.turnToSign(object);
+    const xml = ` <xml>
+      <mch_appid>${this.appInfo.id}</mch_appid>
+      <mchid>${this.appInfo.store}</mchid>
+      <nonce_str>${object.nonce_str}</nonce_str>
+      <partner_trade_no>${object.partner_trade_no}</partner_trade_no>
+      <openid>${openid}</openid>
+      <check_name>NO_CHECK</check_name>
+      <re_user_name>${name}</re_user_name>
+      <amount>${money}</amount>
+      <desc>提现</desc>
+      ${clientIp ? '<spbill_create_ip></spbill_create_ip>' : ''}
+      <sign>${sign}</sign>
+    </xml>`;
+    const url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
+    const res = await this.ctx.curl(url, {
+      method: 'post',
+      data: xml,
+      dataType: 'xml',
+      key: fs.readFileSync('cert/apiclient_key.pem'),
+      cert: fs.readFileSync('cert/apiclient_cert.pem'),
+    });
+    const data = res.data;
+    const parse = new xml2js.Parser({ trim: true, explicitArray: false, explicitRoot: false });
+    const result = await parse.parseStringPromise(data);
+    // TODO 添加错误记录
+    const { return_code, return_msg, result_code, err_code, err_code_des } = result;
+    // 请求是否成功
+    if (return_code !== 'SUCCESS') throw new BusinessError(ErrorCode.SERVICE_FAULT, `${return_code}:${return_msg}`);
+    // 请求失败具体问题
+    if (result_code === 'FAIL') throw new BusinessError(ErrorCode.SERVICE_FAULT, `${err_code}:${err_code_des}`);
+
+  }
+
+  turnToSign(object) {
+    const _arr = [];
+    for (const key in object) {
+      _arr.push(key + '=' + object[key]);
+    }
+    const str = `${_arr.join('&')}&key=${this.appInfo.storeKey}`;
+    return crypto.createHash('md5').update(str, 'utf8').digest('hex')
+      .toUpperCase();
+
+  }
+
+  NoticeCode(code) {
+    const arr = [ 'NOTENOUGH', 'SYSTEMERROR', 'NAME_MISMATCH', 'SIGN_ERROR', 'FREQ_LIMIT', 'MONEY_LIMIT', 'CA_ERROR', 'V2_ACCOUNT_SIMPLE_BAN', 'PARAM_IS_NOT_UTF8', 'SENDNUM_LIMIT' ];
+    return arr;
+  }
+}
+
+module.exports = WxpayService;

+ 3 - 5
config/plugin.js

@@ -1,9 +1,7 @@
 'use strict';
 
 /** @type Egg.EggPlugin */
-module.exports = {
-  // had enabled by egg
-  // static: {
-  //   enable: true,
-  // }
+exports.redis = {
+  enable: true,
+  package: 'egg-redis',
 };

+ 4 - 1
package.json

@@ -8,12 +8,15 @@
   },
   "dependencies": {
     "egg": "^2.15.1",
+    "egg-redis": "^2.4.0",
     "egg-scripts": "^2.11.0",
     "jsonwebtoken": "^8.5.1",
     "lodash": "^4.17.15",
     "moment": "^2.27.0",
     "naf-framework-mongoose": "^0.6.11",
-    "qrcode": "^1.4.4"
+    "qrcode": "^1.4.4",
+    "string-random": "^0.1.3",
+    "xml2js": "^0.4.23"
   },
   "devDependencies": {
     "autod": "^3.0.1",