Преглед изворни кода

Merge branch 'master' into feature/1359-BonusTravelCarHouse

kevin_zhangl пре 3 година
родитељ
комит
d712ad1d1f
100 измењених фајлова са 3521 додато и 472 уклоњено
  1. 3 3
      backendApi/config/menu.php
  2. 1 0
      backendApi/config/urlManagerRules.php
  3. 13 0
      backendApi/modules/v1/controllers/ShopController.php
  4. 1 1
      backendApi/modules/v1/controllers/UserController.php
  5. 2 2
      backendApi/modules/v1/models/lists/bonus/PerfOrderList.php
  6. 1 1
      backendApi/modules/v1/models/lists/bonus/TraceDownQyList.php
  7. 1 0
      backendApi/modules/v1/models/lists/finance/RechargeList.php
  8. 2 2
      backendApi/modules/v1/models/lists/shop/DecOrderList.php
  9. 2 2
      backendApi/modules/v1/models/lists/shop/GoodsList.php
  10. 1 1
      backendApi/modules/v1/models/lists/shop/OrderDecList.php
  11. 1 0
      backendApi/modules/v1/models/lists/shop/OrderList.php
  12. 1 1
      backendApi/modules/v1/models/lists/shop/OrderShopList.php
  13. 1 1
      backendApi/modules/v1/models/lists/shop/OrderStandardList.php
  14. 2 2
      backendApi/modules/v1/models/lists/shop/PackageList.php
  15. 5 5
      backendEle/src/components/DecListTable.vue
  16. 12 12
      backendEle/src/router/index.js
  17. 13 13
      backendEle/src/views/bonus/perf.vue
  18. 2 2
      backendEle/src/views/config/dec-level.vue
  19. 1 1
      backendEle/src/views/config/emp-level-edit.vue
  20. 1 1
      backendEle/src/views/config/emp-level.vue
  21. 1 1
      backendEle/src/views/reconsume/change-audit-add.vue
  22. 3 3
      backendEle/src/views/reconsume/change-audit-list.vue
  23. 2 2
      backendEle/src/views/reconsume/deduct-audit-add.vue
  24. 1 1
      backendEle/src/views/report/dec-table.vue
  25. 1 1
      backendEle/src/views/shop/goods-add.vue
  26. 1 1
      backendEle/src/views/shop/index.vue
  27. 24 1
      backendEle/src/views/shop/order-list.vue
  28. 2 2
      backendEle/src/views/shop/package-add.vue
  29. 1 1
      backendEle/src/views/shop/package.vue
  30. 3 3
      backendEle/src/views/user/re-consume-audit-add.vue
  31. 2 2
      backendEle/src/views/user/re-consume-audit-list.vue
  32. 2 2
      backendEle/src/views/user/re-consume-list.vue
  33. 22 0
      common/config/main.php
  34. 9 1
      common/config/params.php
  35. 99 0
      common/helpers/PayStack.php
  36. 1 1
      common/helpers/Validator.php
  37. 10 0
      common/helpers/user/Info.php
  38. 131 0
      common/models/ApproachOrder.php
  39. 75 0
      common/models/ApproachOrderGoods.php
  40. 1 1
      common/models/DeclarationPackage.php
  41. 5 3
      common/models/Order.php
  42. 2 2
      common/models/OrderDec.php
  43. 5 3
      common/models/OrderGoods.php
  44. 2 2
      common/models/OrderGoodsDec.php
  45. 2 2
      common/models/OrderGoodsShop.php
  46. 1 1
      common/models/OrderStandard.php
  47. 2 2
      common/models/OrderStandardGoods.php
  48. 1 1
      common/models/PerfOrder.php
  49. 8 2
      common/models/ReceiveAddress.php
  50. 44 1
      common/models/Recharge.php
  51. 5 2
      common/models/Region.php
  52. 13 3
      common/models/ShopGoods.php
  53. 7 3
      common/models/User.php
  54. 500 0
      common/models/forms/ApproachOrderForm.php
  55. 1 1
      common/models/forms/DecPackageForm.php
  56. 2 2
      common/models/forms/ExcelOrderDecForm.php
  57. 2 2
      common/models/forms/ExcelOrderShopForm.php
  58. 85 22
      common/models/forms/OrderForm.php
  59. 16 11
      common/models/forms/ReceiveAddressForm.php
  60. 21 8
      common/models/forms/RechargeForm.php
  61. 1 1
      common/models/forms/ShopGoodsForm.php
  62. 7 3
      common/models/forms/UserForm.php
  63. 3 1
      composer.json
  64. 2 2
      frontendApi/config/menu.php
  65. 3 0
      frontendApi/config/urlManagerRules.php
  66. 3 3
      frontendApi/modules/v1/controllers/BonusController.php
  67. 5 3
      frontendApi/modules/v1/controllers/ConfigController.php
  68. 2 2
      frontendApi/modules/v1/controllers/FinanceController.php
  69. 54 5
      frontendApi/modules/v1/controllers/ShopController.php
  70. 2 1
      frontendEle/package.json
  71. 5 5
      frontendEle/src/components/DecListTable.vue
  72. 1 0
      frontendEle/src/utils/network.js
  73. 12 1
      frontendEle/src/utils/userInfo.js
  74. 34 13
      frontendEle/src/views/config/receive-address-edit.vue
  75. 4 4
      frontendEle/src/views/config/receive-address-list.vue
  76. 13 13
      frontendEle/src/views/finance/perf.vue
  77. 80 89
      frontendEle/src/views/finance/recharge-add.vue
  78. 36 24
      frontendEle/src/views/finance/recharge.vue
  79. 1 1
      frontendEle/src/views/shop/dec-order-list.vue
  80. 1 1
      frontendEle/src/views/shop/index.vue
  81. 9 13
      frontendEle/src/views/shop/order-list.vue
  82. 291 133
      frontendEle/src/views/shop/order.vue
  83. 2 2
      frontendEle/src/views/shop/reconsume-order.vue
  84. 2 2
      frontendEle/src/views/shop/reconsume.vue
  85. 3 3
      frontendEle/src/views/user/dec.vue
  86. 6 1
      frontendEle/src/views/user/index.vue
  87. 8 0
      vendor/matscode/paystack/.gitignore
  88. 674 0
      vendor/matscode/paystack/LICENSE
  89. 137 0
      vendor/matscode/paystack/README.md
  90. 19 0
      vendor/matscode/paystack/composer.json
  91. 152 0
      vendor/matscode/paystack/src/Base.php
  92. 247 0
      vendor/matscode/paystack/src/CURL.php
  93. 287 0
      vendor/matscode/paystack/src/Transaction.php
  94. 44 0
      vendor/matscode/paystack/src/Utility/Debug.php
  95. 24 0
      vendor/matscode/paystack/src/Utility/Http.php
  96. 55 0
      vendor/matscode/paystack/src/Utility/Text.php
  97. 48 0
      vendor/matscode/paystack/test/callback.php
  98. 45 0
      vendor/matscode/paystack/test/index.php
  99. 6 0
      vendor/nategood/httpful/.gitignore
  100. 12 0
      vendor/nategood/httpful/.travis.yml

+ 3 - 3
backendApi/config/menu.php

@@ -205,8 +205,8 @@ return [
 //            ['name'=>'车房养老奖流水导出', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-cf-export', 'routePath'=>'bonus/flow-cf-export', 'show'=>0,],
 //            ['name'=>'领袖分红奖流水', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-lx', 'routePath'=>'bonus/flow-lx', 'show'=>1,],
 //            ['name'=>'领袖分红奖流水导出', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-lx-export', 'routePath'=>'bonus/flow-lx-export', 'show'=>0,],
-            ['name'=>'复消积分流水', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-rp', 'routePath'=>'bonus/flow-rp', 'show'=>1,],
-            ['name'=>'复消积分流水导出', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-rp-export', 'routePath'=>'bonus/flow-rp-export', 'show'=>0,],
+//            ['name'=>'复消积分流水', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-rp', 'routePath'=>'bonus/flow-rp', 'show'=>1,],
+//            ['name'=>'复消积分流水导出', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-rp-export', 'routePath'=>'bonus/flow-rp-export', 'show'=>0,],
             ['name'=>'兑换积分流水', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-exchange', 'routePath'=>'bonus/flow-exchange', 'show'=>1,],
             ['name'=>'兑换积分流水导出', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-exchange-export', 'routePath'=>'bonus/flow-exchange-export', 'show'=>0,],
             ['name'=>'会员余额流水', 'class'=>'', 'icon'=>'', 'controller'=>'bonus', 'action'=>'flow-balance', 'routePath'=>'bonus/flow-balance', 'show'=>1,],
@@ -468,7 +468,7 @@ return [
             ['name'=>'奖金基本配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'bonus', 'routePath'=>'config/bonus', 'show'=>0,],
 //            ['name'=>'区域/复销奖配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'bonus-dec-level', 'routePath'=>'config/bonus-dec-level', 'show'=>0,],
 //            ['name'=>'育成/车房/养老配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'bonus-emp-level', 'routePath'=>'config/bonus-emp-level', 'show'=>0,],
-            ['name'=>'期数配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'period', 'routePath'=>'config/period', 'show'=>1,],
+//            ['name'=>'期数配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'period', 'routePath'=>'config/period', 'show'=>1,],
 //            ['name'=>'会员注册类型配置', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'reg-type', 'routePath'=>'config/reg-type', 'show'=>1,],
 //            ['name'=>'会员注册类型编辑', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'reg-type-edit', 'routePath'=>'config/reg-type-edit', 'show'=>0,],
 //            ['name'=>'维护注册协议', 'class'=>'', 'icon'=>'', 'controller'=>'config', 'action'=>'pact-edit', 'routePath'=>'config/pact-edit', 'show'=>0,],

+ 1 - 0
backendApi/config/urlManagerRules.php

@@ -53,6 +53,7 @@ return [
             'GET order-list' => 'order-list',
             'GET order-list-export' => 'order-list-export',
             'POST order-delivery' => 'order-delivery',
+            'POST order-refund' => 'order-refund',
             'GET order-shop-list' => 'order-shop-list',
             'GET order-dec-list' => 'order-dec-list',
             'POST import-order-shop-to-excel-table' => 'import-order-shop-to-excel-table',

+ 13 - 0
backendApi/modules/v1/controllers/ShopController.php

@@ -704,4 +704,17 @@ class ShopController extends BaseController {
         }
         return static::notice('导出开始,请到文件管理-导出文件查看');
     }
+
+    /**
+     * 管理员订单退款
+     * @return mixed
+     * @throws \yii\web\HttpException
+     */
+    public function actionOrderRefund()
+    {
+        if(\Yii::$app->request->isPost) {
+            return parent::edit(OrderForm::class, '退款成功', 'adminRefund', ['adminRefund']);
+        }
+        return static::notice('非法请求', 400);
+    }
 }

+ 1 - 1
backendApi/modules/v1/controllers/UserController.php

@@ -1081,7 +1081,7 @@ class UserController extends BaseController
         $allNation = Yii::$app->params['nation'];
         // 所有开户行
         $allOpenBank = OpenBank::findAllAsArray('STATUS=1');
-        if (!$userName = Info::generateUserName('KD')) {
+        if (!$userName = Info::generateUserName('NG')) {
             return static::notice('会员编号生成失败', 400);
         }
         return static::notice(['allDecRole' => $allDecRole, 'allNation' => $allNation, 'allOpenBank' => $allOpenBank, 'userName' => $userName]);

+ 2 - 2
backendApi/modules/v1/models/lists/bonus/PerfOrderList.php

@@ -122,7 +122,7 @@ class PerfOrderList extends \common\libs\dataList\DataList implements DataListIn
                     ],
                 ],
                 'PV' => [
-                    'header' => '报单PV',
+                    'header' => '报单BV',
                     'headerOther' => [
                         'width' => '150',
                     ],
@@ -179,7 +179,7 @@ class PerfOrderList extends \common\libs\dataList\DataList implements DataListIn
                 'REAL_NAME'=> ['isUserTable'=> false, 'name'=> '会员姓名'],
                 'LAST_REC_USER_NAME'=> ['isUserTable'=> false, 'name'=> '结算时开拓者编号'],
                 'LAST_REC_REAL_NAME'=> ['isUserTable'=> false, 'name'=> '结算时开拓者姓名'],
-                'PV'=> ['isUserTable'=> false, 'name'=> '报单PV'],
+                'PV'=> ['isUserTable'=> false, 'name'=> '报单BV'],
                 'DEC_AMOUNT'=> ['isUserTable'=> false, 'name'=> '报单金额'],
                 'DEC_SN'=> ['isUserTable'=> false, 'name'=> '报单编号'],
                 'CREATED_AT'=> ['isUserTable'=> true, 'name'=> '创建时间', 'other'=> 'date'],

+ 1 - 1
backendApi/modules/v1/models/lists/bonus/TraceDownQyList.php

@@ -147,7 +147,7 @@ class TraceDownQyList extends \common\libs\dataList\DataList implements DataList
                     ],
                 ],
                 'PV' => [
-                    'header' => '报单PV',
+                    'header' => '报单BV',
                     'value' => function($row) {
                         return (new Price([
                             'value' => $row['PV'],

+ 1 - 0
backendApi/modules/v1/models/lists/finance/RechargeList.php

@@ -123,6 +123,7 @@ class RechargeList extends \common\libs\dataList\DataList implements DataListInt
                 'SN' => ['isUserTable' => false, 'name' => '充值记录流水号'],
                 'USER_NAME' => ['isUserTable' => false, 'name' => '会员编号'],
                 'AUDIT_STATUS' => ['isUserTable' => false, 'name' => '审核状态', 'other' => 'select', 'selectData' => [['id' =>0, 'name' => '待审核'], ['id' => 1, 'name' => '已上传凭证'], ['id' => 2, 'name' => '已审核']]],
+                'RECHARGE_STATUS' => ['isUserTable' => false, 'name' => '充值状态', 'other' => 'select', 'selectData' => [['id' =>0, 'name' => 'New'], ['id' => 1, 'name' => 'Processing'], ['id' => 2, 'name' => 'Success']]],
                 'BANK_NO' => ['isUserTable' => false, 'name' => '汇款账号'],
                 'AMOUNT' => ['isUserTable' => false, 'name' => '充值金额'],
                 'CREATED_AT' => ['isUserTable' => false, 'name' => '申请时间', 'other' => 'date'],

+ 2 - 2
backendApi/modules/v1/models/lists/shop/DecOrderList.php

@@ -114,7 +114,7 @@ class DecOrderList extends \common\libs\dataList\DataList implements DataListInt
                     },
                 ],
                 'DEC_PV' => [
-                    'header' => '报单PV',
+                    'header' => '报单BV',
                     'headerOther' => [
                         'width' => '150',
                     ],
@@ -242,7 +242,7 @@ class DecOrderList extends \common\libs\dataList\DataList implements DataListInt
                 'MOBILE'=> ['name'=> '会员手机号'],
                 'DEC_LV_NAME'=> ['name'=> '会员级别', 'other'=> 'decLevel'],
                 'DEC_AMOUNT'=> ['name'=> '报单金额'],
-                'DEC_PV'=> ['name'=> '报单报单PV'],
+                'DEC_PV'=> ['name'=> '报单报单BV'],
                 'PERIOD_NUM'=> ['name'=> '期数'],
                 'REC_USER_NAME'=> ['name'=> '报单时开拓者'],
                 'CREATED_AT'=> ['name'=> '创建时间', 'other'=> 'date'],

+ 2 - 2
backendApi/modules/v1/models/lists/shop/GoodsList.php

@@ -118,7 +118,7 @@ class GoodsList extends \common\libs\dataList\DataList implements DataListInterf
                     },
                 ],
                 'PRICE_PV' => [
-                    'header' => '销售PV',
+                    'header' => '销售BV',
                     'headerOther' => [
                         'width' => '150',
                     ],
@@ -175,7 +175,7 @@ class GoodsList extends \common\libs\dataList\DataList implements DataListInterf
                 'GOODS_NO'=> ['name'=> '商品编号'],
 //                'SELL_TYPE'=> ['name'=> '复消购买方式', 'other'=> 'select', 'selectData'=> [['id'=> 1, 'name'=> '余额购买'],['id'=> 2, 'name'=> '积分购买']]],
                 'SELL_PRICE'=> ['name'=> '销售价格'],
-                'PRICE_PV'=> ['name'=> '销售PV'],
+                'PRICE_PV'=> ['name'=> '销售BV'],
                 'CATEGORY_TYPE' => ['name' => '商品分类', 'other'=> 'select', 'selectData'=> ShopGoods::CATEGORY_TYPE],
             ];
         }

+ 1 - 1
backendApi/modules/v1/models/lists/shop/OrderDecList.php

@@ -121,7 +121,7 @@ class OrderDecList extends \common\libs\dataList\DataList implements DataListInt
                     ],
                 ],
                 'PAY_PV' => [
-                    'header' => '支付PV',
+                    'header' => '支付BV',
                     'headerOther' => [
                         'width' => '150',
                     ],

+ 1 - 0
backendApi/modules/v1/models/lists/shop/OrderList.php

@@ -201,6 +201,7 @@ class OrderList extends \common\libs\dataList\DataList implements DataListInterf
                     },
                     'headerOther' => ['width' => '190'],
                 ],
+                'PAY_TYPE' => null,
                 'REAL_PRICE' => [
                     'header' => '商品单价',
                     'headerOther' => [

+ 1 - 1
backendApi/modules/v1/models/lists/shop/OrderShopList.php

@@ -131,7 +131,7 @@ class OrderShopList extends \common\libs\dataList\DataList implements DataListIn
                     ],
                 ],
                 'PAY_PV' => [
-                    'header' => '支付PV',
+                    'header' => '支付BV',
                     'headerOther' => [
                         'width' => '150',
                     ],

+ 1 - 1
backendApi/modules/v1/models/lists/shop/OrderStandardList.php

@@ -132,7 +132,7 @@ class OrderStandardList extends \common\libs\dataList\DataList implements DataLi
                     ],
                 ],
                 'PAY_PV' => [
-                    'header' => '支付PV',
+                    'header' => '支付BV',
                     'headerOther' => [
                         'width' => '150',
                     ],

+ 2 - 2
backendApi/modules/v1/models/lists/shop/PackageList.php

@@ -69,7 +69,7 @@ class PackageList extends \common\libs\dataList\DataList implements DataListInte
                     },
                 ],
                 'PV' => [
-                    'header' => '套餐PV',
+                    'header' => '套餐BV',
                     'headerOther' => [
                         'width' => '150',
                     ],
@@ -120,7 +120,7 @@ class PackageList extends \common\libs\dataList\DataList implements DataListInte
                 'LEVEL_NAME'=> ['name'=> '所属报单级别', 'other'=> 'decLevel'],
                 'PACKAGE_NAME'=> ['name'=> '套餐名称'],
                 'AMOUNT'=> ['name'=> '套餐金额'],
-                'PV'=> ['name'=> '套餐PV'],
+                'PV'=> ['name'=> '套餐BV'],
                 'STATUS'=> ['name'=> '状态', 'other'=> 'select', 'selectData'=> [['id'=> 1, 'name'=> '已上架'],['id'=> 0, 'name'=> '已下架']]],
             ];
         }

+ 5 - 5
backendEle/src/components/DecListTable.vue

@@ -10,19 +10,19 @@
       </el-table-column>
       <el-table-column label="报单金额" prop="DEC_AMOUNT" v-if="type!=='OR'"></el-table-column>
       <el-table-column label="订货单金额" prop="ORDER_AMOUNT" v-if="type==='OR'"></el-table-column>
-      <el-table-column label="报单PV" prop="DEC_PV" v-if="type!=='OR'"></el-table-column>
-      <el-table-column label="订货单PV" prop="ORDER_PV" v-if="type==='OR'"></el-table-column>
+      <el-table-column label="报单BV" prop="DEC_PV" v-if="type!=='OR'"></el-table-column>
+      <el-table-column label="订货单BV" prop="ORDER_PV" v-if="type==='OR'"></el-table-column>
       <el-table-column label="支付钱包">
         <template slot-scope="scope">
           {{paidType[scope.row.PAID_WALLET].title}}<br>
         </template>
       </el-table-column>
-      <el-table-column label="返利PV" v-if="type==='OR'">
+      <el-table-column label="返利BV" v-if="type==='OR'">
         <template slot-scope="scope">
           {{scope.row.FL_PV}}<br>
         </template>
       </el-table-column>
-      <el-table-column label="补贴PV" v-if="type==='OR'">
+      <el-table-column label="补贴BV" v-if="type==='OR'">
         <template slot-scope="scope">
           {{scope.row.BT_PV}}<br>
         </template>
@@ -86,4 +86,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 12 - 12
backendEle/src/router/index.js

@@ -742,18 +742,18 @@ export const constantRouterMap = [
           ],
         },
       },
-      {
-        path: '/bonus/flow-rp',
-        component: _import('bonus/flow-rp'),
-        name: 'bonus_flow-rp',
-        meta: {
-          title: '复消积分流水',
-          breadcrumb: [
-            {title: '首页', path: '/dashboard/index'},
-            {title: '奖金管理', path: '/bonus/period'},
-          ],
-        },
-      },
+      // {
+      //   path: '/bonus/flow-rp',
+      //   component: _import('bonus/flow-rp'),
+      //   name: 'bonus_flow-rp',
+      //   meta: {
+      //     title: '复消积分流水',
+      //     breadcrumb: [
+      //       {title: '首页', path: '/dashboard/index'},
+      //       {title: '奖金管理', path: '/bonus/period'},
+      //     ],
+      //   },
+      // },
       {
         path: '/bonus/flow-lx',
         component: _import('bonus/flow-lx'),

+ 13 - 13
backendEle/src/views/bonus/perf.vue

@@ -15,40 +15,40 @@
           <template slot-scope="scope">
             <el-form label-position="left" inline class="demo-table-expand">
               <el-form-item label="个人首购">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_ZC)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_ZC)}}BV</span>
               </el-form-item>
               <el-form-item label="个人增购">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_ZG)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_ZG)}}BV</span>
               </el-form-item>
               <el-form-item label="个人零售">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_LS)}}BV</span>
               </el-form-item>
               <el-form-item label="个人复销">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_FX)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_FX)}}BV</span>
               </el-form-item>
               <el-form-item label="左区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_1L_ZC) + Number.parseFloat(scope.row.PV_1L_ZG) + Number.parseFloat(scope.row.PV_1L_LS) + Number.parseFloat(scope.row.PV_1L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_1L_ZC) + Number.parseFloat(scope.row.PV_1L_ZG) + Number.parseFloat(scope.row.PV_1L_LS) + Number.parseFloat(scope.row.PV_1L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="中区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_2L_ZC) + Number.parseFloat(scope.row.PV_2L_ZG) + Number.parseFloat(scope.row.PV_2L_LS) + Number.parseFloat(scope.row.PV_2L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_2L_ZC) + Number.parseFloat(scope.row.PV_2L_ZG) + Number.parseFloat(scope.row.PV_2L_LS) + Number.parseFloat(scope.row.PV_2L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="右区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_3L_ZC) + Number.parseFloat(scope.row.PV_3L_ZG) + Number.parseFloat(scope.row.PV_3L_LS) + Number.parseFloat(scope.row.PV_3L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_3L_ZC) + Number.parseFloat(scope.row.PV_3L_ZG) + Number.parseFloat(scope.row.PV_3L_LS) + Number.parseFloat(scope.row.PV_3L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="零售区业绩">
-                <span>{{tool.formatPrice(scope.row.PV_PERSON_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PERSON_LS)}}BV</span>
               </el-form-item>
               <el-form-item label="上期左区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_1L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_1L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期中区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_2L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_2L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期右区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_3L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_3L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期零售区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_LS)}}BV</span>
               </el-form-item>
             </el-form>
           </template>
@@ -135,4 +135,4 @@ export default {
     margin-right: 0;
     margin-bottom: 0;
   }
-</style>
+</style>

+ 2 - 2
backendEle/src/views/config/dec-level.vue

@@ -8,7 +8,7 @@
             <el-tag type="warning" size="small" class="no-border">{{scope.row.LEVEL_NAME}}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="PERF" label="所需业绩(PV)">
+        <el-table-column prop="PERF" label="所需业绩(BV)">
           <template slot-scope="scope">
             <el-tag type="danger" size="small" class="no-border">{{scope.row.PERF}}</el-tag>
           </template>
@@ -140,4 +140,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 1 - 1
backendEle/src/views/config/emp-level-edit.vue

@@ -25,7 +25,7 @@
           <el-input v-model="form.sort"></el-input>
         </el-form-item>
         </div>
-        <el-form-item label="其他部门PV" v-show="otherPerfShow">
+        <el-form-item label="其他部门BV" v-show="otherPerfShow">
           <el-input v-model="form.otherDepartPerf"></el-input>
         </el-form-item>
         <el-form-item label="图标类型 ">

+ 1 - 1
backendEle/src/views/config/emp-level.vue

@@ -11,7 +11,7 @@
         <el-table-column label="等级要求" width="400">
           <template slot-scope="scope">
             <span v-show="scope.row.LOCATION_NUM>0">有 {{scope.row.LOCATION_NUM}} 个部门(及以上)</span>
-            <span v-show="scope.row.OTHER_DEPART_PERF>0">去最大部门,其他部门累计大于等于 {{scope.row.OTHER_DEPART_PERF}} PV</span>
+            <span v-show="scope.row.OTHER_DEPART_PERF>0">去最大部门,其他部门累计大于等于 {{scope.row.OTHER_DEPART_PERF}} BV</span>
             <span v-show="scope.row.MIN_EMPLOY_LEVEL !== null && scope.row.MIN_EMPLOY_NUM>0">,各{{scope.row.MIN_EMPLOY_NUM}}个 {{scope.row.MIN_EMPLOY_LEVEL_NAME}} </span>
             <span v-show="scope.row.SORT==='8'">,任意部门1个高级总监</span>
           </template>

+ 1 - 1
backendEle/src/views/reconsume/change-audit-add.vue

@@ -17,7 +17,7 @@
         <el-form-item :label="form.type === 0 ? '调整积分' : '调整月数'">
           <el-input v-model="form.changeAmount"></el-input>
           <template>
-            <el-tag v-if="form.type === 0" type="success">可用余额:{{balance.unusedPV}}PV</el-tag>
+            <el-tag v-if="form.type === 0" type="success">可用余额:{{balance.unusedPV}}BV</el-tag>
             <el-tag v-if="form.type === 1" type="success">可用月数:{{balance.unusedMonth}}</el-tag>
           </template>
         </el-form-item>

+ 3 - 3
backendEle/src/views/reconsume/change-audit-list.vue

@@ -79,7 +79,7 @@
           <el-form-item label="调整积分" v-if="form.type==='0'">
             <el-input v-model="form.changePv"></el-input>
             <template>
-              <el-tag type="success">可用余额:{{form.balance.unusedPV}}PV</el-tag>
+              <el-tag type="success">可用余额:{{form.balance.unusedPV}}BV</el-tag>
             </template>
           </el-form-item>
           <el-form-item label="调整月数" v-if="form.type==='1'">
@@ -119,7 +119,7 @@
           <el-form-item label="调整积分" v-if="form.type==='0'">
             <el-input v-model="form.changePv"></el-input>
             <template>
-              <el-tag type="success">可用余额:{{form.balance.unusedPV}}PV</el-tag>
+              <el-tag type="success">可用余额:{{form.balance.unusedPV}}BV</el-tag>
             </template>
           </el-form-item>
           <el-form-item label="调整月数" v-if="form.type==='1'">
@@ -398,4 +398,4 @@
 
 <style scoped>
 
-</style>
+</style>

+ 2 - 2
backendEle/src/views/reconsume/deduct-audit-add.vue

@@ -25,10 +25,10 @@
             <el-option v-for="(item, key) in allMonth" :key="key" :label="item.title" :value="item.value" :disabled="item.disabled"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="可用PV" v-show="unusedPV!==null">
+        <el-form-item label="可用BV" v-show="unusedPV!==null">
           <el-input :value="unusedPV" :disabled="true"></el-input>
         </el-form-item>
-        <el-form-item label="补扣PV" v-show="deductPv!==null">
+        <el-form-item label="补扣BV" v-show="deductPv!==null">
           <el-input :value="deductPv" :disabled="true"></el-input>
         </el-form-item>
         <el-form-item label="备注" v-if="false">

+ 1 - 1
backendEle/src/views/report/dec-table.vue

@@ -31,7 +31,7 @@
           {{tool.formatPrice(scope.row.DEC_AMOUNT)}}
         </template>
       </el-table-column>
-      <el-table-column label="报单PV">
+      <el-table-column label="报单BV">
         <template slot-scope="scope">
           {{tool.formatPrice(scope.row.DEC_PV)}}
         </template>

+ 1 - 1
backendEle/src/views/shop/goods-add.vue

@@ -38,7 +38,7 @@
                 <el-form-item label="销售价格">
                     <el-input v-model="form.sellPrice"></el-input>
                 </el-form-item>
-                <el-form-item label="价格PV" v-show="pvDisabled">
+                <el-form-item label="价格BV" v-show="pvDisabled">
                     <el-input v-model="form.pricePv"></el-input>
                 </el-form-item>
                 <!-- <el-form-item label="兑换积分">

+ 1 - 1
backendEle/src/views/shop/index.vue

@@ -102,7 +102,7 @@
                     <el-form-item label="销售价格" p>
                         <el-input v-model="form.sellPrice"></el-input>
                     </el-form-item>
-                    <el-form-item label="价格PV" v-show="pvDisabled">
+                    <el-form-item label="价格BV" v-show="pvDisabled">
                         <el-input v-model="form.pricePv"></el-input>
                     </el-form-item>
                     <el-form-item label="兑换积分" v-show="false">

+ 24 - 1
backendEle/src/views/shop/order-list.vue

@@ -27,6 +27,7 @@
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item command="edit" @click.native="handleEdit(scope.row)" v-if="permission.hasPermission(`shop/edit`)">编辑订单</el-dropdown-item>
                 <el-dropdown-item command="delivery" @click.native="handleShowDeliveryDialog(scope.row)" v-if="permission.hasPermission(`shop/order-delivery`) && scope.row['STATUS'] === '1' && scope.row['DELIVERY_STATUS'] === '0' ">发货</el-dropdown-item>
+                <el-dropdown-item command="refund" @click.native="handleRefund(scope.row.SN)" v-if="permission.hasPermission(`shop/order-delivery`) && scope.row['PAY_TYPE'] === 'pay_stack' && scope.row['STATUS'] === '1' && scope.row['DELIVERY_STATUS'] === '0' ">退款</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
           </template>
@@ -192,7 +193,29 @@
         }).catch(response => {
           this.dialogDeliveryVisible = false
         })
-      }
+      },
+        // 退款
+        handleRefund(orderSn) {
+            this.$confirm(`确定要将此订单退款吗?`, '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                return network.postData(`shop/order-refund`, { sn: orderSn.value })
+            }).then(response => {
+                this.$message({
+                    message: response,
+                    type: 'success'
+                })
+
+                this.getData(this.currentPage, this.pageSize)
+            }).catch(response => {
+                this.$message({
+                    message: response,
+                    type: 'error'
+                })
+            })
+        },
     }
   }
 

+ 2 - 2
backendEle/src/views/shop/package-add.vue

@@ -12,7 +12,7 @@
                 <el-form-item label="套餐金额">
                     <el-input v-model="form.amount"></el-input>
                 </el-form-item>
-                <el-form-item label="套餐PV">
+                <el-form-item label="套餐BV">
                     <el-input v-model="form.amountPv"></el-input>
                 </el-form-item>
                 <el-form-item label="报单级别ID">
@@ -107,4 +107,4 @@
 
 <style scoped>
 
-</style>
+</style>

+ 1 - 1
backendEle/src/views/shop/package.vue

@@ -58,7 +58,7 @@
                 <el-form-item label="套餐金额">
                     <el-input v-model="form.amount"></el-input>
                 </el-form-item>
-                <el-form-item label="套餐PV">
+                <el-form-item label="套餐BV">
                     <el-input v-model="form.amountPv"></el-input>
                 </el-form-item>
                 <el-form-item label="报单级别ID">

+ 3 - 3
backendEle/src/views/user/re-consume-audit-add.vue

@@ -7,14 +7,14 @@
         </el-form-item>
         <el-form-item label="调整类型">
           <el-select v-model="form.type" placeholder="调整类型">
-            <el-option label="调整余额PV" :value="0"></el-option>
+            <el-option label="调整余额BV" :value="0"></el-option>
             <el-option label="调整剩余月数" :value="1"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item :label="form.type === 0 ? '调整额度' : '调整月数'">
           <el-input v-model="form.changeAmount"></el-input>
           <template>
-            <el-tag v-if="form.type === 0" type="success">可用余额:{{balance.unusedPV}}PV</el-tag>
+            <el-tag v-if="form.type === 0" type="success">可用余额:{{balance.unusedPV}}BV</el-tag>
             <el-tag v-if="form.type === 1" type="success">可用月数:{{balance.unusedMonth}}</el-tag>
           </template>
 
@@ -89,4 +89,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 2 - 2
backendEle/src/views/user/re-consume-audit-list.vue

@@ -6,7 +6,7 @@
         <el-table-column type="selection" width="55"></el-table-column>
         <el-table-column label="会员编号" prop="USER_NAME" width="150"></el-table-column>
         <el-table-column label="会员姓名" prop="REAL_NAME"></el-table-column>
-        <el-table-column label="变动PV">
+        <el-table-column label="变动BV">
           <template slot-scope="scope">
             <span>{{scope.row.CHANGE_PV}}</span>
           </template>
@@ -138,4 +138,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 2 - 2
backendEle/src/views/user/re-consume-list.vue

@@ -16,7 +16,7 @@
             <span>{{baseInfo.empLevels[scope.row.EMP_LV].LEVEL_NAME}}</span>
           </template>
         </el-table-column>
-        <el-table-column label="复销未用PV">
+        <el-table-column label="复销未用BV">
           <template slot-scope="scope">
             <span>{{scope.row.UNUSED_PV}}</span>
           </template>
@@ -119,4 +119,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 22 - 0
common/config/main.php

@@ -49,6 +49,28 @@ return [
         'swooleAsyncTimer' => [
             'class' => 'common\components\SwooleAsyncTimer',
         ],
+        // payStack配置
+        'Paystack' => [
+            'class'         => 'smladeoye\paystack\Paystack',
+            'environment'   => 'test',
+            'testPublicKey' => 'pk_test_2eed10135c4a958c5073795b22854ded9d1a6c55',
+            'testSecretKey' => 'sk_test_5ece72377432376f5cf6bb5c468395a650220309',
+            'livePublicKey' => '',
+            'liveSecretKey' => '',
+        ],
+        // 配置SQL语句输出
+        'log' => [
+            'traceLevel' => YII_DEBUG ? 3 : 0,
+            'targets' => [
+                [
+                    'class' => 'yii\log\FileTarget',
+                    'levels' => ['error', 'warning', 'info'],
+                    'categories' => ['yii\db\*', 'app\models\*'],
+                    'logFile' => '@runtime/logs/sql.log',
+                ],
+                'db' => [ 'class' => 'yii\log\FileTarget'],
+            ],
+        ],
     ],
     'controllerMap' => [
         'swoole_server' => [

+ 9 - 1
common/config/params.php

@@ -9,7 +9,7 @@ return [
     'frontAccessTokenExpiresIn' => 3000 * 60,
     'frontRefreshTokenExpiresIn' => 3000 * 60 * 60,
     'user.passwordResetTokenExpire' => 3600,
-    'operationTimeOut' => 15 * 60,     // 这里设置的15分钟超时
+    'operationTimeOut' => 60 * 60 * 24,     // 这里设置的15分钟超时
     'pageSize' => 20,
     'http' => [
         'shopApi' => [
@@ -317,6 +317,14 @@ return [
             'value' => 6,
             'label' => '订单删除'
         ],
+        '7' => [
+            'value' => 7,
+            'label' => '订单退款'
+        ],
+        'refund' => [
+            'value' => 7,
+            'label' => '订单退款'
+        ],
     ],
     'exportModule' => [
         'shop' => ['label' => '商城管理', 'value'=>'shop'],

+ 99 - 0
common/helpers/PayStack.php

@@ -0,0 +1,99 @@
+<?php
+
+namespace common\helpers;
+
+class PayStack
+{
+    /**
+     *
+     */
+    public static function transactionInit($currency, $amount, $email){
+        $secretKey = \Yii::$app->Paystack->testSecretKey;
+        $url = "https://api.paystack.co/transaction/initialize";
+        $fields = [
+            'email' => $email,
+            'amount' => $amount * 100
+        ];
+        $fields_string = http_build_query($fields);
+        //open connection
+        $ch = curl_init();
+
+        //set the url, number of POST vars, POST data
+        curl_setopt($ch,CURLOPT_URL, $url);
+        curl_setopt($ch,CURLOPT_POST, true);
+        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+            "Authorization: Bearer {$secretKey}",
+            "Cache-Control: no-cache",
+        ));
+        //So that curl_exec returns the contents of the cURL; rather than echoing it
+        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
+        //execute post
+        $result = curl_exec($ch);
+        $result =  json_decode($result, true);
+        return [
+            'status'    => $result['status'],
+            'message'   => $result['message'],
+            'data'      => $result['data'],
+        ];
+    }
+    /**
+     * 交易支付.
+     * @param $ref
+     * @return array
+     */
+    public static function transactionVerify($ref): array
+    {
+        $payStack = \Yii::$app->Paystack;
+        $transaction = $payStack->transaction()->setRequestOptions($ref);
+        $transaction->verify();
+
+        return [
+            'status'    => $transaction->status,
+            'message'   => $transaction->message,
+            'data'      => $transaction->data,
+        ];
+    }
+
+    /**
+     * 交易退款.
+     * @param string $transaction
+     * @param int $amount
+     */
+    public static function transactionRefund(string $reference, int $amount)
+    {
+        $secretKey = \Yii::$app->Paystack->testSecretKey;
+
+        $url = "https://api.paystack.co/refund";
+        $fields = [
+            'transaction' => $reference,
+            'amount'      => $amount,
+        ];
+        $fields_string = http_build_query($fields);
+        //open connection
+        $ch = curl_init();
+
+        //set the url, number of POST vars, POST data
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+            "Authorization: Bearer {$secretKey}",
+            "Cache-Control: no-cache",
+        ));
+
+        //So that curl_exec returns the contents of the cURL; rather than echoing it
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+        //execute post
+        $response = curl_exec($ch);
+        $response = json_decode($response, true);
+
+        return [
+            'status'    => $response['status'],
+            'message'   => $response['message'],
+            'data'      => $response['data'],
+        ];
+    }
+
+}

+ 1 - 1
common/helpers/Validator.php

@@ -26,7 +26,7 @@ class Validator extends \yii\validators\Validator {
         'chDate'	    =>	["#^\d{4}([/-])([0][0-9]|[1][0-2])\\1([0-2][0-9]|[3][0-1])$#", '必须为日期格式'],
         'chMonth'       =>  ["#^\d{4}([/-])([0][0-9]|[1][0-2]|[0-9])$#", '必须为年月格式'],
         'phone'			=>	["#^\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}$#", '必须为电话格式'],
-        'mobile'        =>	["|^1[2-9]\d{9}$|", '格式输入不正确'],
+        'mobile'        =>	["|^0[7-9]\d{9}$|", '格式输入不正确'],
         'alpha'         =>  ["|^[a-zA-Z]+$|", '必须为英文字母格式'],
         'zh'            =>  ['/^[\x{4e00}-\x{9fa5}]+$/u', '必须为中文'],
         'price'         =>  ["/^[0-9]+([.]{1}[0-9]{1,2})?$/", '必须为金额格式'],

+ 10 - 0
common/helpers/user/Info.php

@@ -63,6 +63,16 @@ class Info {
         return $user ? $user['REAL_NAME'] : null;
     }
 
+    /**
+     * 获取会员邮箱通过ID
+     * @param $userId
+     * @return null
+     */
+    public static function getUserEmailByUserId($userId) {
+        $user = User::findOneAsArray('ID=:ID AND DELETED=0', [':ID' => $userId], 'EMAIL');
+        return $user ? $user['EMAIL'] : null;
+    }
+
     /**
      * 获取手机号通过ID
      * @param $userId

+ 131 - 0
common/models/ApproachOrder.php

@@ -0,0 +1,131 @@
+<?php
+
+namespace common\models;
+
+use Yii;
+
+/**
+ * This is the model class for table "{{%ORDER}}".
+ *
+ * @property string $ID
+ * @property string $SN 订单号
+ * @property string $DEC_SN 报单编号
+ * @property string $USER_ID 用户ID
+ * @property string $USER_NAME 会员编号
+ * @property string $ORDER_TYPE 订货类型
+ * @property string $ORDER_AMOUNT 订单总价格
+ * @property string $PV 订货PV
+ * @property string $PAY_AMOUNT 支付价格
+ * @property string $PAY_PV 实付PV
+ * @property int $PAY_AT 支付时间
+ * @property string $PAY_TYPE 支付方式
+ * @property string $FREIGHT 运费
+ * @property string $PAY_FREIGHT 实付运费金额
+ * @property int $DELIVERY_STATUS 发货状态
+ * @property int $DELIVERY_PERIOD 发货期数
+ * @property int $DELIVERY_AT 发货时间
+ * @property string $EXPRESS_COMPANY 快递公司
+ * @property string $ORDER_TRACK_NO 快递单号
+ * @property int $EXPRESS_TYPE 发货方式
+ * @property string $FRONT_REMARK 前台备注
+ * @property string $REMARK 后台备注
+ * @property int $PERIOD_NUM 期数
+ * @property int $STATUS 订单状态
+ * @property string $CONSIGNEE 收货人
+ * @property string $MOBILE 收货人手机
+ * @property string $TEL 固定电话
+ * @property int $PROVINCE 省份名称
+ * @property int $CITY 城市名称
+ * @property int $COUNTY 县区
+ * @property string $ADDRESS 详细地址
+ * @property string $P_CALC_MONTH 分区日期
+ * @property int $CREATED_AT 订单创建时间
+ * @property string $CREATE_USER 订单创建人
+ * @property int $UPDATED_AT 修改时间
+ * @property string $UPDATER 修改人
+ * @property int $IS_DELETE 是否删除
+ * @property int $DELETED_AT 删除时间
+ * @property int $WAREHOUSE 发货仓
+ * @property string $EMAIL 邮箱
+ */
+class ApproachOrder extends \common\components\ActiveRecord
+{
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return '{{%APPROACH_ORDER}}';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['USER_ID', 'USER_NAME', 'ORDER_TYPE', 'CREATE_USER', 'EMAIL'], 'required'],
+            [['ORDER_AMOUNT', 'PV', 'PAY_AMOUNT', 'PAY_PV', 'FREIGHT', 'PAY_FREIGHT'], 'number'],
+            [['PAY_AT', 'DELIVERY_STATUS', 'DELIVERY_PERIOD', 'DELIVERY_AT', 'EXPRESS_TYPE', 'PERIOD_NUM', 'STATUS', 'PROVINCE', 'CITY', 'COUNTY', 'CREATED_AT', 'UPDATED_AT', 'IS_DELETE', 'DELETED_AT'], 'integer'],
+            [['ID','SN', 'DEC_SN', 'USER_ID', 'ORDER_TRACK_NO','PAY_TYPE'], 'string', 'max' => 32],
+            [['USER_NAME', 'TEL', 'CREATE_USER', 'UPDATER', 'WAREHOUSE'], 'string', 'max' => 16],
+            [['ORDER_TYPE'], 'string', 'max' => 12],
+            [['EXPRESS_COMPANY'], 'string', 'max' => 128],
+            [['FRONT_REMARK'], 'string', 'max' => 1000],
+            [['REMARK'], 'string', 'max' => 4000],
+            [['CONSIGNEE'], 'string', 'max' => 120],
+            [['MOBILE'], 'string', 'max' => 11],
+            [['ADDRESS'], 'string', 'max' => 255],
+            [['SN'], 'unique'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'SN' => '订单号',
+            'DEC_SN' => '报单编号',
+            'USER_ID' => '用户ID',
+            'USER_NAME' => '会员编号',
+            'ORDER_TYPE' => '订货类型',
+            'ORDER_AMOUNT' => '订单总价格',
+            'PV' => '订货BV',
+            'PAY_AMOUNT' => '支付价格',
+            'PAY_PV' => '实付BV',
+            'PAY_AT' => '支付时间',
+            'PAY_TYPE' => '支付方式',
+            'FREIGHT' => '运费',
+            'PAY_FREIGHT' => '实付运费金额',
+            'DELIVERY_STATUS' => '发货状态',
+            'DELIVERY_PERIOD' => '发货期数',
+            'DELIVERY_AT' => '发货时间',
+            'EXPRESS_COMPANY' => '快递公司',
+            'ORDER_TRACK_NO' => '快递单号',
+            'EXPRESS_TYPE' => '发货方式',
+            'FRONT_REMARK' => '前台备注',
+            'REMARK' => '后台备注',
+            'PERIOD_NUM' => '期数',
+            'STATUS' => '订单状态',
+            'CONSIGNEE' => '收货人',
+            'MOBILE' => '收货人手机',
+            'TEL' => '固定电话',
+            'PROVINCE' => '省份名称',
+            'CITY' => '城市名称',
+            'COUNTY' => '县区',
+            'ADDRESS' => '详细地址',
+            'P_CALC_MONTH' => '分区日期',
+            'CREATED_AT' => '订单创建时间',
+            'CREATE_USER' => '订单创建人',
+            'UPDATED_AT' => '修改时间',
+            'UPDATER' => '修改人',
+            'IS_DELETE' => '是否删除',
+            'DELETED_AT' => '删除时间',
+            'WAREHOUSE' => '发货仓',
+            'EMAIL' => 'Email'
+        ];
+    }
+}

+ 75 - 0
common/models/ApproachOrderGoods.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace common\models;
+
+use Yii;
+
+/**
+ * This is the model class for table "{{%ORDER_GOODS}}".
+ *
+ * @property string $ID
+ * @property string $ORDER_SN 订单ID
+ * @property string $GOODS_ID 商品ID
+ * @property string $GOODS_TITLE 商品名称
+ * @property string $PRICE 价格
+ * @property string $REAL_PRICE 实际价格
+ * @property string $PV 订货PV
+ * @property string $REAL_PV 实际PV
+ * @property string $POINT 兑换积分
+ * @property string $SKU_CODE 商品编码
+ * @property int $BUY_NUMS 购买数量
+ * @property string $P_CALC_MONTH 分区日期
+ * @property int CATEGORY_TYPE 商品分类
+ * @property int PAY_TYPE 支付方式
+ * @property string $EMAIL Email
+ */
+class ApproachOrderGoods extends \common\components\ActiveRecord
+{
+    /**
+     * {@inheritdoc}
+     */
+    public static function tableName()
+    {
+        return '{{%APPROACH_ORDER_GOODS}}';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function rules()
+    {
+        return [
+            [['ORDER_SN', 'GOODS_ID', 'GOODS_TITLE', 'SKU_CODE', 'CATEGORY_TYPE', 'PAY_TYPE', 'EMAIL'], 'required'],
+            [['PRICE', 'REAL_PRICE', 'PV', 'REAL_PV', 'POINT', 'CATEGORY_TYPE', 'PAY_TYPE'], 'number'],
+            [['BUY_NUMS'], 'integer'],
+            [['ID', 'ORDER_SN', 'GOODS_ID'], 'string', 'max' => 32],
+            [['GOODS_TITLE'], 'string', 'max' => 255],
+            [['SKU_CODE'], 'string', 'max' => 16],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'ORDER_SN' => '订单ID',
+            'GOODS_ID' => '商品ID',
+            'GOODS_TITLE' => '商品名称',
+            'PRICE' => '价格',
+            'REAL_PRICE' => '实际价格',
+            'PV' => '订货BV',
+            'REAL_PV' => '实际BV',
+            'POINT' => '兑换积分',
+            'SKU_CODE' => '商品编码',
+            'BUY_NUMS' => '购买数量',
+            'P_CALC_MONTH' => '分区日期',
+            'CATEGORY_TYPE' => '商品分类',
+            'PAY_TYPE' => '支付方式',
+            'EMAIL' => 'Email'
+        ];
+    }
+}

+ 1 - 1
common/models/DeclarationPackage.php

@@ -62,7 +62,7 @@ class DeclarationPackage extends \common\components\ActiveRecord
             'PACKAGE_NO' => '套餐编号',
             'LEVEL_ID' => '所属报单级别ID',
             'AMOUNT' => '套餐金额',
-            'PV' => '套餐PV',
+            'PV' => '套餐BV',
             'PACKAGE_CONTENT' => '套餐内容',
             'CREATED_AT' => '创建时间',
             'CREATE_ADMIN' => '创建人',

+ 5 - 3
common/models/Order.php

@@ -46,6 +46,7 @@ use Yii;
  * @property int $IS_DELETE 是否删除
  * @property int $DELETED_AT 删除时间
  * @property int $WAREHOUSE 发货仓
+ * @property string $EMAIL 邮箱
  */
 class Order extends \common\components\ActiveRecord
 {
@@ -63,7 +64,7 @@ class Order extends \common\components\ActiveRecord
     public function rules()
     {
         return [
-            [['USER_ID', 'USER_NAME', 'ORDER_TYPE', 'CREATE_USER'], 'required'],
+            [['USER_ID', 'USER_NAME', 'ORDER_TYPE', 'CREATE_USER', 'EMAIL'], 'required'],
             [['ORDER_AMOUNT', 'PV', 'PAY_AMOUNT', 'PAY_PV', 'FREIGHT', 'PAY_FREIGHT'], 'number'],
             [['PAY_AT', 'DELIVERY_STATUS', 'DELIVERY_PERIOD', 'DELIVERY_AT', 'EXPRESS_TYPE', 'PERIOD_NUM', 'STATUS', 'PROVINCE', 'CITY', 'COUNTY', 'CREATED_AT', 'UPDATED_AT', 'IS_DELETE', 'DELETED_AT'], 'integer'],
             [['ID','SN', 'DEC_SN', 'USER_ID', 'ORDER_TRACK_NO','PAY_TYPE'], 'string', 'max' => 32],
@@ -92,9 +93,9 @@ class Order extends \common\components\ActiveRecord
             'USER_NAME' => '会员编号',
             'ORDER_TYPE' => '订货类型',
             'ORDER_AMOUNT' => '订单总价格',
-            'PV' => '订货PV',
+            'PV' => '订货BV',
             'PAY_AMOUNT' => '支付价格',
-            'PAY_PV' => '实付PV',
+            'PAY_PV' => '实付BV',
             'PAY_AT' => '支付时间',
             'PAY_TYPE' => '支付方式',
             'FREIGHT' => '运费',
@@ -124,6 +125,7 @@ class Order extends \common\components\ActiveRecord
             'IS_DELETE' => '是否删除',
             'DELETED_AT' => '删除时间',
             'WAREHOUSE' => '发货仓',
+            'EMAIL' => 'Email'
         ];
     }
 }

+ 2 - 2
common/models/OrderDec.php

@@ -93,9 +93,9 @@ class OrderDec extends \common\components\ActiveRecord
             'USER_NAME' => '会员编号',
             'ORDER_TYPE' => '订货类型',
             'ORDER_AMOUNT' => '订单总价格',
-            'PV' => '订货PV',
+            'PV' => '订货BV',
             'PAY_AMOUNT' => '支付价格',
-            'PAY_PV' => '实付PV',
+            'PAY_PV' => '实付BV',
             'PAY_AT' => '支付时间',
             'PAY_TYPE' => '支付方式',
             'FREIGHT' => '运费',

+ 5 - 3
common/models/OrderGoods.php

@@ -21,6 +21,7 @@ use Yii;
  * @property string $P_CALC_MONTH 分区日期
  * @property int CATEGORY_TYPE 商品分类
  * @property int PAY_TYPE 支付方式
+ * @property string $EMAIL Email
  */
 class OrderGoods extends \common\components\ActiveRecord
 {
@@ -38,7 +39,7 @@ class OrderGoods extends \common\components\ActiveRecord
     public function rules()
     {
         return [
-            [['ORDER_SN', 'GOODS_ID', 'GOODS_TITLE', 'SKU_CODE', 'CATEGORY_TYPE', 'PAY_TYPE'], 'required'],
+            [['ORDER_SN', 'GOODS_ID', 'GOODS_TITLE', 'SKU_CODE', 'CATEGORY_TYPE', 'PAY_TYPE', 'EMAIL'], 'required'],
             [['PRICE', 'REAL_PRICE', 'PV', 'REAL_PV', 'POINT', 'CATEGORY_TYPE', 'PAY_TYPE'], 'number'],
             [['BUY_NUMS'], 'integer'],
             [['ID', 'ORDER_SN', 'GOODS_ID'], 'string', 'max' => 32],
@@ -60,14 +61,15 @@ class OrderGoods extends \common\components\ActiveRecord
             'GOODS_TITLE' => '商品名称',
             'PRICE' => '价格',
             'REAL_PRICE' => '实际价格',
-            'PV' => '订货PV',
-            'REAL_PV' => '实际PV',
+            'PV' => '订货BV',
+            'REAL_PV' => '实际BV',
             'POINT' => '兑换积分',
             'SKU_CODE' => '商品编码',
             'BUY_NUMS' => '购买数量',
             'P_CALC_MONTH' => '分区日期',
             'CATEGORY_TYPE' => '商品分类',
             'PAY_TYPE' => '支付方式',
+            'EMAIL' => 'Email'
         ];
     }
 }

+ 2 - 2
common/models/OrderGoodsDec.php

@@ -58,8 +58,8 @@ class OrderGoodsDec extends \common\components\ActiveRecord
             'GOODS_TITLE' => '商品名称',
             'PRICE' => '价格',
             'REAL_PRICE' => '实际价格',
-            'PV' => '订货PV',
-            'REAL_PV' => '实际PV',
+            'PV' => '订货BV',
+            'REAL_PV' => '实际BV',
             'POINT' => '兑换积分',
             'PERIOD_NUM' => '期数',
             'ORDER_DAY' => '日期',

+ 2 - 2
common/models/OrderGoodsShop.php

@@ -57,8 +57,8 @@ class OrderGoodsShop extends \common\components\ActiveRecord
             'GOODS_TITLE' => '商品名称',
             'PRICE' => '价格',
             'REAL_PRICE' => '实际价格',
-            'PV' => '订货PV',
-            'REAL_PV' => '实际PV',
+            'PV' => '订货BV',
+            'REAL_PV' => '实际BV',
             'POINT' => '兑换积分',
             'PERIOD_NUM' => '期数',
             'SKU_CODE' => '商品编码',

+ 1 - 1
common/models/OrderStandard.php

@@ -94,7 +94,7 @@ class OrderStandard extends \common\components\ActiveRecord
             'ORDER_AMOUNT' => 'Order  Amount',
             'PV' => 'Pv',
             'PAY_AMOUNT' => 'Pay  Amount',
-            'PAY_PV' => 'Pay  Pv',
+            'PAY_PV' => 'Pay  Bv',
             'PAY_AT' => 'Pay  At',
             'FREIGHT' => 'Freight',
             'PAY_FREIGHT' => 'Pay  Freight',

+ 2 - 2
common/models/OrderStandardGoods.php

@@ -58,8 +58,8 @@ class OrderStandardGoods extends \common\components\ActiveRecord
             'GOODS_TITLE' => 'Goods  Title',
             'PRICE' => 'Price',
             'REAL_PRICE' => 'Real  Price',
-            'PV' => 'Pv',
-            'REAL_PV' => 'Real  Pv',
+            'PV' => 'Bv',
+            'REAL_PV' => 'Real  Bv',
             'SKU_CODE' => 'Sku  Code',
             'BUY_NUMS' => 'Buy  Nums',
             'POINT' => 'Point',

+ 1 - 1
common/models/PerfOrder.php

@@ -92,7 +92,7 @@ class PerfOrder extends \common\components\ActiveRecord
             'LAST_STATUS' => '结算时状态',
             'LAST_REC_USER_NAME' => '结算时开拓者编号',
             'LAST_REC_REAL_NAME' => '结算时开拓者姓名',
-            'PV' => '业绩单PV',
+            'PV' => '业绩单BV',
             'DEC_AMOUNT' => '报单金额',
             'LAST_SUB_COM_ID' => '结算时所属分公司',
             'LAST_PROVINCE' => '结算时省份',

+ 8 - 2
common/models/ReceiveAddress.php

@@ -15,6 +15,8 @@ use Yii;
  * @property int $PROVINCE 省份名称
  * @property int $CITY 城市名称
  * @property int $COUNTY 县区名称
+ * @property string $LGA_NAME Lga
+ * @property string $CITY_NAME City
  * @property string $ADDRESS 详细地址
  * @property int $IS_DEFAULT 是否默认
  * @property int $CREATED_AT 创建时间
@@ -37,13 +39,15 @@ class ReceiveAddress extends \common\components\ActiveRecord
     public function rules()
     {
         return [
-            [['USER_ID', 'USER_NAME', 'CONSIGNEE', 'MOBILE', 'PROVINCE', 'CITY', 'COUNTY', 'ADDRESS'], 'required'],
-            [['PROVINCE', 'CITY', 'COUNTY', 'IS_DEFAULT', 'CREATED_AT', 'UPDATED_AT'], 'integer'],
+            [['USER_ID', 'USER_NAME', 'CONSIGNEE', 'MOBILE', 'PROVINCE', 'LGA_NAME', 'CITY_NAME', 'ADDRESS'], 'required'],
+            [['PROVINCE', 'IS_DEFAULT', 'CREATED_AT', 'UPDATED_AT'], 'integer'],
             [['ID', 'USER_ID'], 'string', 'max' => 32],
             [['USER_NAME'], 'string', 'max' => 16],
             [['CONSIGNEE'], 'string', 'max' => 120],
             [['MOBILE'], 'string', 'max' => 11],
             [['ADDRESS'], 'string', 'max' => 255],
+            [['LGA_NAME'], 'string', 'max' => 50],
+            [['CITY_NAME'], 'string', 'max' => 50],
             [['UPDATER'], 'string', 'max' => 10],
             [['ID'], 'unique'],
         ];
@@ -63,6 +67,8 @@ class ReceiveAddress extends \common\components\ActiveRecord
             'PROVINCE' => '省份名称',
             'CITY' => '城市名称',
             'COUNTY' => '县区名称',
+            'LGA_NAME' => 'Lga Name',
+            'CITY_NAME' => 'City Name',
             'ADDRESS' => '详细地址',
             'IS_DEFAULT' => '是否默认',
             'CREATED_AT' => '创建时间',

+ 44 - 1
common/models/Recharge.php

@@ -15,7 +15,10 @@ use Yii;
  * @property int $RECHARGE_PERIOD_NUM 充值期数
  * @property int $RECHARGE_YEAR 充值年份
  * @property int $RECHARGE_MONTH 充值月份
+ * @property string $CURRENCY 货币(尼日利亚默认NGN)
  * @property string $AMOUNT 充值金额
+ * @property string $RECHARGE_ORDER_ID PS订单号
+ * @property int $RECHARGE_STATUS 充值状态
  * @property string $REAL_NAME 会员姓名
  * @property string $OPEN_BANK 开户行
  * @property string $BANK_ADDRESS 开户支行
@@ -42,6 +45,11 @@ class Recharge extends \common\components\ActiveRecord {
     const STATUS_AUDITED = 2;       // 已审核
     const STATUS_REFUSED = 3;       // 已拒绝
 
+    const STATUS_NEW = 0;
+    const STATUS_PROCESSING = 1;
+    const STATUS_SUCCESS = 2;
+    const STATUS_REJECT = 3;
+
     const STATUS_NAME = [
         self::STATUS_APPLIED => '待审核',
         self::STATUS_PROVED => '已上传凭证',
@@ -49,6 +57,12 @@ class Recharge extends \common\components\ActiveRecord {
         self::STATUS_REFUSED => '已拒绝',
     ];
 
+    const RECHARGE_STATUS_NAME = [
+        self::STATUS_NEW => 'NEW',
+        self::STATUS_PROCESSING => 'PROCESSING',
+        self::STATUS_SUCCESS => 'SUCCESS',
+        self::STATUS_REJECT => 'FAILED',
+    ];
     /**
      * @inheritdoc
      */
@@ -85,6 +99,7 @@ class Recharge extends \common\components\ActiveRecord {
             'RECHARGE_PERIOD_NUM' => '充值期数',
             'RECHARGE_YEAR' => '充值年份',
             'RECHARGE_MONTH' => '充值月份',
+            'CURRENCY' => '货币',
             'AMOUNT' => '充值金额',
             'REAL_NAME' => '会员姓名',
             'OPEN_BANK' => '汇款银行',
@@ -187,5 +202,33 @@ class Recharge extends \common\components\ActiveRecord {
         $total = self::find()->where('AUDIT_STATUS=:AUDIT_STATUS', [':AUDIT_STATUS' => $type])->sum('AMOUNT');
         return $total ? $total : '0.00';
     }
-
+    /**
+     *
+     */
+    public static function sendToPaystack(){
+        $url = "https://api.paystack.co/transaction/initialize";
+        $am = random_int(100, 4000);
+        $fields = [
+            'email' => "fl@bd.com",
+            'amount' => $am
+        ];
+        $fields_string = http_build_query($fields);
+        //open connection
+        $ch = curl_init();
+        $sk = 'sk_test_1d16378c8be9efabc71b05754190b9c3f6999402'; //taisino
+        //$sk = 'sk_test_5ece72377432376f5cf6bb5c468395a650220309'; //elken
+        //set the url, number of POST vars, POST data
+        curl_setopt($ch,CURLOPT_URL, $url);
+        curl_setopt($ch,CURLOPT_POST, true);
+        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+            "Authorization: Bearer $sk",
+            "Cache-Control: no-cache",
+        ));
+        //So that curl_exec returns the contents of the cURL; rather than echoing it
+        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
+        //execute post
+        //$result = curl_exec($ch);
+        echo $result;
+    }
 }

+ 5 - 2
common/models/Region.php

@@ -70,6 +70,7 @@ class Region extends \common\components\ActiveRecord
      * @return string
      */
     public static function getCnName($regionCode){
+//        self::updateToCache();
         $allData = self::getFromCache();
         return $allData[$regionCode]['REGION_NAME'] ?? '';
     }
@@ -115,8 +116,10 @@ class Region extends \common\components\ActiveRecord
     public static function getWarehouseByCode($regionCode){
         //'540000','710000','810000','820000'
         $ZoningArr = [
-            '01'=>['110000','120000','130000','370000','140000','210000','310000','320000','330000','340000','410000','150000','220000','230000','500000','510000','610000','620000','640000','630000','650000'],
-            '02'=>['440000','350000','360000','420000','430000','450000','460000','520000','530000']
+            '01'=>['10100','10200','10300','10400','10500','10600','10700','10800','10900',
+                '11000','11100','11200','11300','11400','11500','11600','11700','11800',
+                '11900','12000','12100','12200','12300','12400','12500','12600','12700',
+                '12800','12900','13000','13100','13200','13300','13400','13500','13600','19900']
         ];
         $zoning = '';
         foreach ($ZoningArr as $key=>$val){

+ 13 - 3
common/models/ShopGoods.php

@@ -61,6 +61,11 @@ class ShopGoods extends \common\components\ActiveRecord
             'name' => '豪宅积分',
             'label' => 'house_points',
         ],
+        7 => [
+            'id' => 7,
+            'name' => 'PayStack',
+            'label' => 'pay_stack',
+        ],
     ];
     const GOODS_TYPE = [
         1 =>[
@@ -96,8 +101,10 @@ class ShopGoods extends \common\components\ActiveRecord
             'name' => '普通商品',
             'sell_type' => [
                 self::SALE_TYPE[1],
-                self::SALE_TYPE[3]]
-            ],
+                self::SALE_TYPE[3],
+                self::SALE_TYPE[7],
+            ]
+        ],
         [
             'id' => 4,
             'name' => '旅游积分商品',
@@ -229,7 +236,10 @@ class ShopGoods extends \common\components\ActiveRecord
             ],
             'house_points' => [
                 'name' => '豪宅积分'
-            ]
+            ],
+            'pay_stack' => [
+                'name' => 'PayStack'
+            ],
         ];
     }
 

+ 7 - 3
common/models/User.php

@@ -92,6 +92,7 @@ use common\libs\logging\operate\valueType\Config as ValueTypeConfig;
  * @property int $IS_FIRST_OPEN 首次开通
  * @property int $IS_MODIFY_PASSWORD 是否修改密码
  * @property int $IS_STUDIO 是否是工作室
+ * @property string $EMAIL 邮箱
  */
 class User extends \common\components\ActiveRecord
 {
@@ -112,7 +113,7 @@ class User extends \common\components\ActiveRecord
             [['USER_NAME', 'PASSWORD_HASH', 'PAY_PASSWORD', 'REAL_NAME', 'ID_CARD', 'AVATAR'], 'required'],
             [['NATION', 'ID_TYPE', 'BANK_PROVINCE', 'BANK_CITY', 'BANK_COUNTY', 'CREATED_AT', 'UPDATED_AT', 'STATUS', 'DEC_CLOSED', 'DEC_CLOSED_AT', 'PROVINCE', 'CITY', 'COUNTY', 'DELETED', 'DELETED_AT', 'IS_DEC', 'IS_ATLAS', 'IS_RECHARGE','IS_STUDIO',  'PERIOD_AT', 'DEC_PROVINCE', 'DEC_CITY', 'DEC_COUNTY', 'IS_UNION', 'STATUS_AT', 'VERIFIED', 'VERIFIED_AT', 'ALLOW_LOGIN', 'NOT_OPERATING', 'REG_FROM', 'BANK_UPDATED_AT', 'IS_DIRECT_SELLER', 'DEC_LV_UPDATED_AT', 'DEC_LV_UPDATED_PERIOD', 'PART_FUNC_CLOSED', 'LAST_DEC_LV_UPDATED_PERIOD', 'LAST_DEC_LV_UPDATED_AT', 'DEC_CREATED_AT', 'DEC_CREATED_PERIOD', 'PASSWORD_CHANGED', 'SUB_COM_LEADER', 'READ_AGREEMENT', 'IS_FIRST_OPEN', 'IS_MODIFY_PASSWORD'], 'integer'],
             [['ZG_UPGRADE_PV'], 'number'],
-            [['ID', 'OPEN_BANK', 'BANK_NO', 'DEC_LV', 'EMP_LV', 'SUB_COM_ID', 'DEC_ID', 'DEC_ROLE_ID', 'ID_CARD_PREFIX', 'SEX', 'DEC_PHONE', 'GUARANTOR', 'USER_CREATOR', 'USER_UPDATER', 'LAST_DEC_LV'], 'string', 'max' => 32],
+            [['ID', 'OPEN_BANK', 'BANK_NO', 'DEC_LV', 'EMP_LV', 'SUB_COM_ID', 'DEC_ID', 'DEC_ROLE_ID', 'ID_CARD_PREFIX', 'SEX', 'DEC_PHONE', 'GUARANTOR', 'USER_CREATOR', 'USER_UPDATER', 'LAST_DEC_LV', 'EMAIL'], 'string', 'max' => 32],
             [['USER_NAME', 'SPOUSE_NAME', 'TEL'], 'string', 'max' => 16],
             [['PASSWORD_HASH', 'PAY_PASSWORD', 'ID_IMAGE', 'BANK_ADDRESS', 'AVATAR'], 'string', 'max' => 255],
             [['REAL_NAME', 'APP_CLIENT_ID', 'BONUS_APP_CLIENT_ID'], 'string', 'max' => 128],
@@ -212,6 +213,7 @@ class User extends \common\components\ActiveRecord
             'IS_FIRST_OPEN' => '首次开通',
             'IS_MODIFY_PASSWORD' => '是否修改密码',
             'IS_STUDIO' => '是否是工作室',
+            'EMAIL' => 'Email',
         ];
     }
 
@@ -237,7 +239,7 @@ class User extends \common\components\ActiveRecord
     public static function getBaseInfoFromRedis($userId){
         $userInfo = Yii::$app->redis->hget(Cache::USER_INFO_KEY, $userId);
         if(!$userInfo){
-            $userInfo = static::find()->select('ID,USER_NAME,NATION,REAL_NAME,ID_CARD,ID_TYPE,MOBILE,ADDRESS,STATUS,DEC_LV,LAST_DEC_LV,EMP_LV,DEC_CLOSED,AVATAR,OPEN_BANK,BANK_ADDRESS,BANK_NO,VERIFIED,IS_UNION,IS_DEC,IS_ATLAS,IS_RECHARGE,IS_STUDIO,DEC_ROLE_ID,PROVINCE,CITY,COUNTY')->where('ID=:ID', [':ID'=>$userId])->asArray()->one();
+            $userInfo = static::find()->select('ID,USER_NAME,NATION,REAL_NAME,ID_CARD,ID_TYPE,MOBILE,ADDRESS,STATUS,DEC_LV,LAST_DEC_LV,EMP_LV,DEC_CLOSED,AVATAR,OPEN_BANK,BANK_ADDRESS,BANK_NO,VERIFIED,IS_UNION,IS_DEC,IS_ATLAS,IS_RECHARGE,IS_STUDIO,DEC_ROLE_ID,PROVINCE,CITY,COUNTY,EMAIL')->where('ID=:ID', [':ID'=>$userId])->asArray()->one();
             Yii::$app->redis->hset(Cache::USER_INFO_KEY, $userId, Json::encode($userInfo));
         } else {
             $userInfo = Json::decode($userInfo);
@@ -251,7 +253,7 @@ class User extends \common\components\ActiveRecord
      * @return mixed
      */
     public static function updateBaseInfoToRedis($userId){
-        $userInfo = static::find()->select('ID,USER_NAME,NATION,REAL_NAME,ID_CARD,ID_TYPE,MOBILE,ADDRESS,STATUS,DEC_LV,LAST_DEC_LV,EMP_LV,DEC_CLOSED,AVATAR,OPEN_BANK,BANK_ADDRESS,BANK_NO,VERIFIED,IS_UNION,IS_DEC,IS_ATLAS,IS_RECHARGE,IS_STUDIO,DEC_ROLE_ID,PROVINCE,CITY,COUNTY')->where('ID=:ID', [':ID'=>$userId])->asArray()->one();
+        $userInfo = static::find()->select('ID,USER_NAME,NATION,REAL_NAME,ID_CARD,ID_TYPE,MOBILE,ADDRESS,STATUS,DEC_LV,LAST_DEC_LV,EMP_LV,DEC_CLOSED,AVATAR,OPEN_BANK,BANK_ADDRESS,BANK_NO,VERIFIED,IS_UNION,IS_DEC,IS_ATLAS,IS_RECHARGE,IS_STUDIO,DEC_ROLE_ID,PROVINCE,CITY,COUNTY,EMAIL')->where('ID=:ID', [':ID'=>$userId])->asArray()->one();
         return Yii::$app->redis->hset(Cache::USER_INFO_KEY, $userId, Json::encode($userInfo));
     }
 
@@ -297,6 +299,7 @@ class User extends \common\components\ActiveRecord
             'COUNTY' => $userInfo['COUNTY'],
             'BANK_NO' => $userInfo['BANK_NO'],
 //            'BANK_NO' => Tool::hideBankNo($userInfo['BANK_NO']),
+            'EMAIL' => $userInfo['EMAIL'],
         ];
     }
 
@@ -442,6 +445,7 @@ class User extends \common\components\ActiveRecord
             ],
             'BIRTHDAY' => '生日',
             'SEX' => '性别',
+            'EMAIL' => 'Email'
         ];
     }
 

+ 500 - 0
common/models/forms/ApproachOrderForm.php

@@ -0,0 +1,500 @@
+<?php
+namespace common\models\forms;
+
+use common\helpers\Cache;
+use common\helpers\Date;
+use common\components\Model;
+use common\helpers\Form;
+use common\helpers\PayStack;
+use common\helpers\user\Balance;
+use common\helpers\user\Cash;
+use common\helpers\user\Info;
+use common\libs\logging\operate\AdminOperate;
+use common\models\ApproachOrder;
+use common\models\ApproachOrderGoods;
+use common\models\DealType;
+use common\models\Order;
+use common\models\OrderGoods;
+use common\models\Period;
+use common\models\ReceiveAddress;
+use common\models\Region;
+use common\models\ShopGoods;
+use common\models\User;
+use common\models\UserNetwork;
+use yii\base\Exception;
+
+/**
+ * Login form
+ */
+class ApproachOrderForm extends Model
+{
+    public $sn;
+    public $expressCompany;
+    public $orderTrackNo;
+    public $status;
+    public $remark;
+
+    public $type;
+    public $addressId;
+    public $payType;
+    public $goodsId;
+    public $goodsNum;
+    public $payPassword;
+    public $email;
+
+    public $userName;
+    public $consignee;
+    public $acceptMobile;
+    public $province;
+    public $city;
+    public $county;
+    public $detailaddress;
+
+    private $_address;
+    private $_decAmount;
+    private $_decPv;
+    private $_freight;
+    private $_payAmount;
+    private $_orderGoods;
+
+    /**
+     * @var ApproachOrder
+     */
+    private $_model;
+
+    public function init() {
+        parent::init();
+        $this->adminOperateLogger = new AdminOperate([
+            'fetchClass' => ApproachOrder::class,
+        ]);
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rules()
+    {
+        return [
+            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress','email'], 'trim'],
+            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress','email'], 'required'],
+            [['status'], 'isStatus'],
+            [['addressId'], 'isAddress'],
+            [['payType'], 'isPayType'],
+            [['payPassword'], 'validatePassword'],
+        ];
+    }
+
+    public function attributeLabels()
+    {
+        return [
+            'sn' => '订单号',
+            'expressCompany' => '快递公司',
+            'orderTrackNo' => '快递单号',
+            'status' => '状态',
+            'remark' => '备注',
+            'type' => '订单类型',
+            'addressId' => '收货地址',
+            'payType' => '支付方式',
+            'goodsId' => '商品ID',
+            'goodsNum' => '商品数量',
+            'userName' => '复消会员编号',
+            'consignee' => '收货人',
+            'acceptMobile' => '收货电话',
+            'province' => '省',
+            'city' => '市',
+            'county' => '区',
+            'detailaddress' => '收货详细地址',
+            'email' => 'Email',
+        ];
+    }
+
+    /**
+     * 指定校验场景
+     * @return array
+     */
+    public function scenarios()
+    {
+        $parentScenarios =  parent::scenarios();
+        $customScenarios = [
+            // 管理员修改订单状态
+            'adminStatus' => ['sn', 'status'],
+            // 管理员修改订单状态
+            'verifyPayStack' => ['sn', 'remark', 'email'],
+            // 会员下单
+            'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'remark', 'payPassword', 'email'],
+        ];
+        return array_merge($parentScenarios, $customScenarios);
+    }
+
+    /**
+     * 校验之前
+     * @return bool
+     */
+    public function beforeValidate()
+    {
+        $parentValidate = parent::beforeValidate();
+        if ($this->sn) {
+            $this->_model = ApproachOrder::findOne(['SN' => $this->sn]);
+            if (!$this->_model){
+                $this->addError('sn', '订单不存在');
+                return false;
+            }
+        }
+
+        if ($this->scenario == 'verifyPayStack'){
+            if ($this->_model['STATUS'] != \Yii::$app->params['orderStatus']['notPaid']['value']) {
+                $this->addError('sn', '订单支付状态错误');
+                return false;
+            }
+        }
+
+        return $parentValidate;
+    }
+
+    /**
+     * 判断收货地址是否存在
+     * @param $attribute
+     */
+    public function isAddress($attribute){
+        if (!$receiveAddress = ReceiveAddress::find()->where(' ID=:ID', [':ID' => $this->addressId])->asArray()->one()) {
+            $this->addError($attribute, '收货地址不存在');
+        } else {
+            $this->_address = $receiveAddress;
+        }
+    }
+
+    /**
+     * 校验支付密码
+     * @param $attribute
+     * @param $params
+     */
+    public function validatePassword($attribute, $params) {
+        if (!User::validatePayPassword(\Yii::$app->user->id, $this->payPassword)) {
+            $this->addError($attribute, '支付密码不正确');
+        }
+    }
+
+    /**
+     * 判断支付方式
+     * @param $attribute
+     */
+    public function isPayType($attribute)
+    {
+        if ($this->payType != 'pay_stack'){
+            $this->addError($attribute, '只允许PayStack方式支付');
+            return;
+        }
+
+        // 一个订单只能包含一类商品
+        $goods = ShopGoods::find()->select('ID,CATEGORY_TYPE')->where(['in', 'ID', $this->goodsId])->andWhere(['STATUS' => 1])->asArray()->all();
+        $goodsCategoryType = array_unique(array_column($goods, 'CATEGORY_TYPE'));
+        if (count($goodsCategoryType) != 1) {
+            $this->addError($attribute, '订单不能包含多种商品分类');
+            return;
+        }
+
+        // 购买方式
+        $sellTypeLabelMap = array_column(ShopGoods::SALE_TYPE, NULL, 'label');
+        if (!array_key_exists($this->payType, $sellTypeLabelMap)) {
+            $this->addError($attribute, '不支持PayStack方式支付');
+            return;
+        }
+
+        // 所选支付方式必须是商品分类支持的类型
+        $categoryType = array_column(ShopGoods::CATEGORY_TYPE, NULL, 'id');
+        // 商品类型
+        $currCategoryType = $goodsCategoryType[0];
+        if (!array_key_exists($currCategoryType, $categoryType)) {
+            $this->addError($attribute, '商品分类错误');
+            return;
+        }
+
+        $sellType = $categoryType[$currCategoryType]['sell_type'] ?? [];
+        if (!$sellType || !in_array($this->payType, array_column($sellType, 'label'))) {
+            $this->addError($attribute, '支付方式错误3');
+        }
+    }
+
+    /**
+     * 校验类型
+     * @param $attribute
+     */
+    public function isStatus($attribute){
+        if(!in_array($this->type, \Yii::$app->params['orderStatus'])){
+            $this->addError($attribute, '类型错误');
+            return ;
+        }
+        if ($this->scenario == 'adminStatus'){
+            if ($this->status == $this->_model['STATUS']) {
+                $this->addError($attribute, '订单状态没有改变');
+                return ;
+            }
+            if($this->status == \Yii::$app->params['orderStatus']['notPaid'] && $this->_model['STATUS'] >= \Yii::$app->params['orderStatus']['delivery']) {
+                $this->addError($attribute, '订单已经进入物流状态不能改为未支付');
+                return ;
+            }
+            elseif($this->status == \Yii::$app->params['orderStatus']['paid'] && $this->_model['STATUS'] >= \Yii::$app->params['orderStatus']['cancel']) {
+                $this->addError($attribute, '订单已失效不能处理');
+                return ;
+            }
+            elseif($this->status == \Yii::$app->params['orderStatus']['delivery']) {
+                $this->addError($attribute, '订单不能单独处理为物流状态');
+                return ;
+            }
+            elseif($this->status == \Yii::$app->params['orderStatus']['complete'] && $this->_model['STATUS'] > \Yii::$app->params['orderStatus']['cancel']) {
+                $this->addError($attribute, '订单已失效不能处理');
+                return ;
+            }
+            elseif($this->status == \Yii::$app->params['orderStatus']['cancel']) {
+                if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['complete']) {
+                    $this->addError($attribute, '订单已完成不能取消');
+                    return ;
+                }
+                if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['del']) {
+                    $this->addError($attribute, '订单已删除不能取消');
+                    return ;
+                }
+            }
+            elseif($this->status == \Yii::$app->params['orderStatus']['del']) {
+                if($this->_model['STATUS'] == \Yii::$app->params['orderStatus']['complete']) {
+                    $this->addError($attribute, '订单已完成不能删除');
+                    return ;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * 校验PayStack支付,更新订单状态.同步到正式订单.
+     * @throws Exception
+     */
+    public function verifyPayStack(): ?ApproachOrder
+    {
+        if (!$this->validate()) {
+            return null;
+        }
+
+        // 调用PayStack支付校验
+        $payload = PayStack::transactionVerify($this->remark['reference']);
+        if ($payload['status'] !== true) {
+            throw new Exception(Form::formatErrorsForApi($payload['message']));
+        }
+        if ($payload['data']['amount'] != $this->_model->PAY_AMOUNT * 100) {
+            throw new Exception(Form::formatErrorsForApi('支付金额与订单金额不符'));
+        }
+
+        $db = \Yii::$app->db;
+        $transaction = $db->beginTransaction();
+        try {
+            // 更新准订单状态为已支付
+            $this->_model->STATUS = \Yii::$app->params['orderStatus']['paid']['value'];
+            $this->_model->REMARK = json_encode($this->remark);
+            $this->_model->PAY_AT = Date::nowTime();
+            $this->_model->EMAIL = $this->email;
+            if (!$this->_model->save()) {
+                throw new Exception(Form::formatErrorsForApi($this->_model->getErrors()));
+            }
+            // 更新订单商品的支付Email
+            ApproachOrderGoods::updateAll(['EMAIL' => $this->email], 'ORDER_SN = :ORDER_SN', [':ORDER_SN' => $this->sn]);
+
+
+            // 同步准订单到正式订单
+            Order::insertOne($this->_model->toArray());
+            // 同步准订单商品到正式订单商品
+            $approachOrderGoods = ApproachOrderGoods::findAllAsArray('ORDER_SN = :ORDER_SN', [':ORDER_SN' => $this->sn]);
+            foreach ($approachOrderGoods as &$approachOrderGood) {
+                $approachOrderGood['EMAIL'] = $this->email;
+            }
+            OrderGoods::batchInsert($approachOrderGoods);
+
+            $transaction->commit();
+        } catch (Exception $e) {
+            $transaction->rollBack();
+            $this->addError('edit', $e->getMessage());
+            return null;
+        }
+
+        return $this->_model;
+    }
+
+    /**
+     * 复销
+     * @throws Exception
+     * @throws \yii\db\Exception
+     */
+    public function add(){
+        if(!$this->validate()){
+            return null;
+        }
+
+        $ids = $this->goodsId;
+        $totalAmount = 0;
+        $totalPv = 0;
+        $goodsType = ShopGoods::GOODS_TYPE;
+        foreach ($this->goodsNum as $k => $v) {
+            if ($v) {
+                $goods = ShopGoods::findOneAsArray('ID=:ID AND STATUS=1',[':ID'=> $ids[$k]]);
+                if($goods['STORE_NUMS']>0){
+                    if ($goods['TYPE'] == 1 || $goods['TYPE'] == 2) {
+                        $discount = $goodsType[$goods['TYPE']]['discount'];
+                        $realPrice = $goods['SELL_PRICE'] * $discount/100;
+                        $realPv = $goods['PRICE_PV'] * $discount/100;
+                    } else {
+                        $discount = $goods['SELL_DISCOUNT'];
+                        $realPrice = $goods['SELL_PRICE'] * $discount;
+                        $realPv = $goods['PRICE_PV'] * $discount;
+                    }
+                    $totalAmount += $realPrice * intval($v);
+                    $totalPv += $realPv * intval($v);
+
+                    $this->_orderGoods[] = [
+                        'GOODS_ID' => $goods['ID'],
+                        'PRICE' => $goods['SELL_PRICE'],
+                        'PV' => $goods['PRICE_PV'],
+                        'REAL_PRICE' => $realPrice,
+                        'REAL_PV' => $realPv,
+                        'POINT' => $goods['POINT'],
+                        'BUY_NUMS' => intval($v),
+                        'SKU_CODE' => $goods['GOODS_NO'],
+                        'GOODS_TITLE' => $goods['GOODS_NAME'],
+                        'CATEGORY_TYPE' => $goods['CATEGORY_TYPE'],
+                        'PAY_TYPE' => $this->payType,
+                        'EMAIL' => $this->email,
+                    ];
+                }
+            }
+        }
+
+        $this->_decAmount = $totalAmount;
+        $this->_decPv = $totalPv;
+        $this->_freight = ($totalAmount>=300) ? 0 : 15;
+        if($this->_address['PROVINCE']==1){
+            $this->_freight = 0;
+        }
+        $this->_payAmount = $this->_decAmount + $this->_freight;
+
+        $db = \Yii::$app->db;
+        $transaction = $db->beginTransaction();
+        try {
+            //写入订单
+            if (!$orderResult = $this->addOrder()) {
+                throw new Exception(Form::formatErrorsForApi($orderResult->getErrors()));
+            }
+
+            $transaction->commit();
+
+            return $orderResult;
+        }catch (\Exception $e){
+            $transaction->rollBack();
+            $this->addError('add', $e->getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * 复销订单
+     * @throws Exception
+     */
+    public function addOrder()
+    {
+        $periodObj = Period::instance();
+        $nowPeriodNum = $periodObj->getNowPeriodNum();
+        $nowCalcMonth = $periodObj->getYearMonth($nowPeriodNum);
+
+        $userId = \Yii::$app->user->id;
+
+        $userName = Info::getUserNameByUserId($userId);
+        $userRealName = Info::getUserRealNameByUserId($userId);
+        $userMobile = Info::getUserMobileByUserId($userId);
+        $userEmail = Info::getUserEmailByUserId($userId);
+        // 加入订单信息
+        if ($this->_address['PROVINCE'] != 1) {
+            $warehouse = Region::getWarehouseByCode($this->_address['PROVINCE']);//仓库
+            if (!$warehouse) {
+//                throw new Exception('地区2暂时不支持配送,具体联系客服');
+            }
+        }else{
+            $warehouse = '01';
+        }
+        $_hasPV = $this->_decPv;
+
+        $ordNo = $this->_generateSn();
+        $orderModel = new ApproachOrder();
+        $orderModel->SN = 'OS' . $ordNo;
+        $orderModel->DEC_SN = 'DS' . $ordNo;
+        $orderModel->ORDER_TYPE = $this->type;
+        $orderModel->USER_ID = $userId;
+        $orderModel->USER_NAME = $userName;
+        $orderModel->ORDER_AMOUNT = $this->_decAmount;
+        $orderModel->PV = $_hasPV;
+        $orderModel->PAY_AMOUNT = $this->_payAmount;
+        $orderModel->PAY_PV = $_hasPV; // 兑换积分不能算业绩
+        $orderModel->PAY_AT = 0;
+        $orderModel->PAY_TYPE = $this->payType;
+        $orderModel->PERIOD_NUM = $nowPeriodNum;
+        $orderModel->P_CALC_MONTH = Date::ociToDate($nowCalcMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH);
+        $orderModel->FREIGHT = $this->_freight;
+        $orderModel->PAY_FREIGHT = $this->_freight;
+        $orderModel->CONSIGNEE = $this->_address['CONSIGNEE'];
+        $orderModel->MOBILE = $this->_address['MOBILE'];
+        $orderModel->PROVINCE = $this->_address['PROVINCE'];
+        $orderModel->CITY = $this->_address['CITY'];
+        $orderModel->COUNTY = $this->_address['COUNTY'];
+        $orderModel->ADDRESS = $this->_address['ADDRESS'];
+        $orderModel->FRONT_REMARK = $this->remark;
+        $orderModel->WAREHOUSE = $warehouse;
+        $orderModel->STATUS = \Yii::$app->params['orderStatus']['notPaid']['value'];
+        $orderModel->CREATED_AT = Date::nowTime();
+        $orderModel->CREATE_USER = $userName;
+        $orderModel->EMAIL = $userEmail;
+        if($this->_address['PROVINCE']==1){
+            $orderModel->EXPRESS_TYPE = 1;
+            $orderModel->CONSIGNEE = $userRealName;
+            $orderModel->MOBILE = $userMobile;
+            $orderModel->PROVINCE = 1;
+            $orderModel->CITY = 1;
+            $orderModel->COUNTY = 1;
+            $orderModel->ADDRESS = '';
+        }
+        if(!$orderModel->save()){
+            $this->addErrors($orderModel->getErrors());
+            return false;
+        }
+        // 加入商品到订单商品表
+        foreach($this->_orderGoods as $key=>$value) {
+            $this->_orderGoods[$key]['ORDER_SN'] = $orderModel->SN;
+            $this->_orderGoods[$key]['P_CALC_MONTH'] = Date::ociToDate($nowCalcMonth, Date::OCI_TIME_FORMAT_SHORT_MONTH);
+        }
+        ApproachOrderGoods::batchInsert($this->_orderGoods);
+
+        // TODO: 记录流水
+
+        return $orderModel;
+    }
+
+    /**
+     * 生成流水号
+     * @return string
+     */
+    private function _generateSn() {
+        return Date::today('Ymd') . $this->_random(10, 1);
+    }
+
+    /**
+     * 生成随机数
+     * @param $length
+     * @param int $numeric
+     * @return string
+     */
+    private function _random($length, $numeric = 0) {
+        $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
+        $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed));
+        $hash = '';
+        $max = strlen($seed) - 1;
+        for ($i = 0; $i < $length; $i++) {
+            $hash .= $seed[mt_rand(0, $max)];
+        }
+        return $hash;
+    }
+}

+ 1 - 1
common/models/forms/DecPackageForm.php

@@ -45,7 +45,7 @@ class DecPackageForm extends Model
             'packageName' => '套餐名称',
             'packageNo' => '套餐编号',
             'amount' => '套餐金额',
-            'amountPv' => '套餐PV',
+            'amountPv' => '套餐BV',
             'levelId' => '所属报单级别',
             'packageContent' => '套餐详情',
         ];

+ 2 - 2
common/models/forms/ExcelOrderDecForm.php

@@ -47,8 +47,8 @@ class ExcelOrderDecForm extends \common\components\ActiveRecord
         '数量' => 'BUY_NUMS',
         '商品单价' => 'PRICE',
         '商品金额' => 'REAL_PRICE',
-        '商品PV' => 'PV',
-        'PV合计' => 'REAL_PV',
+        '商品BV' => 'PV',
+        'BV合计' => 'REAL_PV',
         '期数' => 'PERIOD_NUM',
     ];
 

+ 2 - 2
common/models/forms/ExcelOrderShopForm.php

@@ -47,8 +47,8 @@ class ExcelOrderShopForm extends \common\components\ActiveRecord
         '数量' => 'BUY_NUMS',
         '商品单价' => 'PRICE',
         '商品金额' => 'REAL_PRICE',
-        '商品PV' => 'PV',
-        'PV合计' => 'REAL_PV',
+        '商品BV' => 'PV',
+        'BV合计' => 'REAL_PV',
         '期数' => 'PERIOD_NUM',
     ];
 

+ 85 - 22
common/models/forms/OrderForm.php

@@ -5,6 +5,7 @@ use common\helpers\Cache;
 use common\helpers\Date;
 use common\components\Model;
 use common\helpers\Form;
+use common\helpers\PayStack;
 use common\helpers\user\Balance;
 use common\helpers\user\Cash;
 use common\helpers\user\Info;
@@ -37,6 +38,7 @@ class OrderForm extends Model
     public $goodsId;
     public $goodsNum;
     public $payPassword;
+    public $email;
 
     public $userName;
     public $consignee;
@@ -71,8 +73,8 @@ class OrderForm extends Model
     public function rules()
     {
         return [
-            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress'], 'trim'],
-            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress'], 'required'],
+            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress','email'], 'trim'],
+            [['sn', 'expressCompany', 'orderTrackNo', 'status', 'remark','type','addressId','payType','goodsId','goodsNum', 'payPassword','userName','consignee','acceptMobile','province','city','county','detailaddress','email'], 'required'],
             [['status'], 'isStatus'],
             [['addressId'], 'isAddress'],
             [['payType'], 'isPayType'],
@@ -100,6 +102,7 @@ class OrderForm extends Model
             'city' => '市',
             'county' => '区',
             'detailaddress' => '收货详细地址',
+            'email' => 'Email',
         ];
     }
 
@@ -123,6 +126,8 @@ class OrderForm extends Model
             'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'remark', 'payPassword'],
             // 帮会员复消下单
             'reconsumeOrder' => ['type','userName', 'payType','goodsId','goodsNum', 'remark', 'payPassword','consignee','acceptMobile','province','city','county','detailaddress'],
+            // 管理员退款
+            'adminRefund' => ['sn'],
         ];
         return array_merge($parentScenarios, $customScenarios);
     }
@@ -152,6 +157,25 @@ class OrderForm extends Model
             }
         }
 
+        if ($this->scenario == 'adminRefund'){
+            if ($this->_model['STATUS'] != \Yii::$app->params['orderStatus']['paid']['value']) {
+                $this->addError('sn', '订单状态支付状态不支持退款');
+                return false;
+            }
+            if ($this->_model['DELIVERY_STATUS'] != \Yii::$app->params['deliveryStatus']['notDelivery']['value']) {
+                $this->addError('sn', '订单物流状态不支持退款');
+                return false;
+            }
+            if ($this->_model['PAY_TYPE'] != 'pay_stack') {
+                $this->addError('sn', '订单支付方式不支持退款');
+                return false;
+            }
+            if (!$this->_model['REMARK']) {
+                $this->addError('sn', '订单支付信息不存在');
+                return false;
+            }
+        }
+
         return $parentValidate;
     }
 
@@ -300,9 +324,55 @@ class OrderForm extends Model
         return $this->_model;
     }
 
+    /**
+     * 订单退款
+     * @return Order|null
+     * @throws Exception
+     */
+    public function adminRefund()
+    {
+        if(!$this->validate()){
+            return null;
+        }
+
+        // 支付信息存在于remark中
+        $remark = $this->_model->REMARK ? json_decode($this->_model->REMARK, true) : [];
+        $reference = $remark['reference'] ?? '';
+        if (!$reference) {
+            throw new Exception(Form::formatErrorsForApi('支付信息不存在'));
+        }
+        // 退款金额. 订单支付金额 * 100
+        $amount = $this->_model->PAY_AMOUNT * 100;
+        // 调用PayStack支付校验
+        $payload = PayStack::transactionRefund($reference, $amount);
+        if ($payload['status'] !== true) {
+            throw new Exception(Form::formatErrorsForApi($payload['message']));
+        }
+
+        $db = \Yii::$app->db;
+        $transaction = $db->beginTransaction();
+        try {
+            $this->_model->STATUS = \Yii::$app->params['orderStatus']['refund']['value'];
+            $this->_model->REMARK = json_encode([
+                    'payment' => $remark,
+                    'refund'  => $payload['data']
+                ]
+            );
+            if (!$this->_model->save()) {
+                throw new Exception(Form::formatErrorsForApi($this->_model->getErrors()));
+            }
+            $transaction->commit();
+        } catch (Exception $e) {
+            $transaction->rollBack();
+            $this->addError('edit', $e->getMessage());
+            return null;
+        }
+
+        return $this->_model;
+    }
+
     /**
      * 复销
-     * @return bool|null
      * @throws Exception
      * @throws \yii\db\Exception
      */
@@ -329,18 +399,7 @@ class OrderForm extends Model
                     }
                     $totalAmount += $realPrice * intval($v);
                     $totalPv += $realPv * intval($v);
-//                    if($this->payType=='cash') {
-//                        $discount = $goodsType[$goods['TYPE']]['discount'];
-//                        $realPrice = $goods['SELL_PRICE'] * $discount/100;
-//                        $realPv = $goods['PRICE_PV'] * $discount/100;
-//                        $totalAmount += $realPrice * intval($v);
-//                        $totalPv += $realPv * intval($v);
-//                    }else{
-//                        $realPrice = $goods['SELL_PRICE'];
-//                        $realPv = $goods['PRICE_PV'];
-//                        $totalAmount += $realPrice * intval($v);
-//                        $totalPv += $realPv * intval($v);
-//                    }
+
                     $this->_orderGoods[] = [
                         'GOODS_ID' => $goods['ID'],
                         'PRICE' => $goods['SELL_PRICE'],
@@ -353,6 +412,7 @@ class OrderForm extends Model
                         'GOODS_TITLE' => $goods['GOODS_NAME'],
                         'CATEGORY_TYPE' => $goods['CATEGORY_TYPE'],
                         'PAY_TYPE' => $this->payType,
+                        'EMAIL' => $this->email,
                     ];
                 }
             }
@@ -380,13 +440,13 @@ class OrderForm extends Model
             }
 
             $transaction->commit();
+
+            return $orderResult;
         }catch (\Exception $e){
             $transaction->rollBack();
             $this->addError('add', $e->getMessage());
             return null;
         }
-
-        return true;
     }
 
     /**
@@ -412,9 +472,9 @@ class OrderForm extends Model
                 return ['code' => 500, 'message' => (Balance::BALANCE_TYPE[$payType]['title'] ?? '积分') . '不足,无法购买商品'];
             }
         } else{
-            if ($payAmount > Balance::getBalanceReconsumePoints($loginUserId)) {
-                return ['code' => 500, 'message' => '复消积分不足,无法购买商品'];
-            }
+//            if ($payAmount > Balance::getBalanceReconsumePoints($loginUserId)) {
+//                return ['code' => 500, 'message' => '复消积分不足,无法购买商品'];
+//            }
         }
 
         return ['code' => 200];
@@ -434,6 +494,7 @@ class OrderForm extends Model
         $userName = Info::getUserNameByUserId($userId);
         $userRealName = Info::getUserRealNameByUserId($userId);
         $userMobile = Info::getUserMobileByUserId($userId);
+        $userEmail = Info::getUserEmailByUserId($userId);
         // 加入订单信息
         if ($this->_address['PROVINCE'] != 1) {
             $warehouse = Region::getWarehouseByCode($this->_address['PROVINCE']);//仓库
@@ -470,9 +531,10 @@ class OrderForm extends Model
         $orderModel->ADDRESS = $this->_address['ADDRESS'];
         $orderModel->FRONT_REMARK = $this->remark;
         $orderModel->WAREHOUSE = $warehouse;
-        $orderModel->STATUS = 1;
+        $orderModel->STATUS = \Yii::$app->params['orderStatus']['paid']['value'];
         $orderModel->CREATED_AT = Date::nowTime();
         $orderModel->CREATE_USER = $userName;
+        $orderModel->EMAIL = $userEmail ?? '';
         if($this->_address['PROVINCE']==1){
             $orderModel->EXPRESS_TYPE = 1;
             $orderModel->CONSIGNEE = $userRealName;
@@ -508,9 +570,10 @@ class OrderForm extends Model
             Balance::changeUserBonus(\Yii::$app->user->id, 'car_points', -abs($this->_payAmount), ['DEAL_TYPE_ID' => DealType::CAR_POINTS_EXCHANGE,'REMARK' => '会员名车积分兑换']);
         } else if ($this->payType == 'house_points') {
             Balance::changeUserBonus(\Yii::$app->user->id, 'house_points', -abs($this->_payAmount), ['DEAL_TYPE_ID' => DealType::HOUSE_POINTS_EXCHANGE,'REMARK' => '会员豪宅积分兑换']);
-        } else{
+        } else if ($this->payType == 'reconsume_points') {
             Balance::changeUserBonus(\Yii::$app->user->id,'reconsume_points', -abs($this->_payAmount),['DEAL_TYPE_ID' => DealType::RECONSUME_POINTS_EXCHANGE,'REMARK' => '会员复销积分兑换']);
         }
+
         return $orderModel;
     }
 

+ 16 - 11
common/models/forms/ReceiveAddressForm.php

@@ -24,6 +24,8 @@ class ReceiveAddressForm extends Model
     public $province;
     public $city;
     public $county;
+    public $lgaName;
+    public $cityName;
     public $address;
     public $isDefault;
 
@@ -46,10 +48,10 @@ class ReceiveAddressForm extends Model
     public function rules()
     {
         return [
-            [['id', 'consignee', 'mobile', 'province', 'city', 'county', 'address', 'isDefault'], 'trim'],
-            [['id', 'consignee', 'mobile', 'province', 'city', 'county', 'address'], 'required'],
+            [['id', 'consignee', 'mobile', 'province', 'lgaName', 'cityName', 'address', 'isDefault'], 'trim'],
+            [['id', 'consignee', 'mobile', 'province', 'lgaName', 'cityName', 'address'], 'required'],
             [['mobile'], 'mobile'],
-            [['province', 'city', 'county'], 'exist', 'targetClass' => Region::class, 'targetAttribute' => 'REGION_CODE'],
+            [['province'], 'exist', 'targetClass' => Region::class, 'targetAttribute' => 'REGION_CODE'],
         ];
     }
 
@@ -59,8 +61,10 @@ class ReceiveAddressForm extends Model
             'consignee' => '收货人',
             'mobile' => '手机号',
             'province' => '省/市',
-            'city' => '市/区',
-            'county' => '区/县',
+//            'city' => '市/区',
+//            'county' => '区/县',
+            'lgaName' => 'LGA Name',
+            'cityName' => 'City Name',
             'address' => '详细地址',
         ];
     }
@@ -73,8 +77,8 @@ class ReceiveAddressForm extends Model
     {
         $parentScenarios =  parent::scenarios();
         $customScenarios = [
-            'userAdd' => ['consignee', 'mobile', 'province', 'city', 'county', 'address', 'isDefault'],
-            'userEdit' => ['id', 'consignee', 'mobile', 'province', 'city', 'county', 'address', 'isDefault'],
+            'userAdd' => ['consignee', 'mobile', 'province', 'lgaName', 'cityName', 'address', 'isDefault'],
+            'userEdit' => ['id', 'consignee', 'mobile', 'province', /*'lgaName', 'cityName',*/ 'address', 'isDefault'],
             'userIsDefault' => ['id', 'isDefault'],
         ];
         return array_merge($parentScenarios, $customScenarios);
@@ -129,14 +133,15 @@ class ReceiveAddressForm extends Model
             if ($this->isDefault) {
                 ReceiveAddress::updateAll(['IS_DEFAULT' => 0], 'USER_ID=:USER_ID', [':USER_ID'=>\Yii::$app->user->id]);
             }
+//            print_r($this);exit;
             if($this->scenario == 'userAdd'){
                 $this->_model->USER_ID = \Yii::$app->user->id;
                 $this->_model->USER_NAME = Info::getUserNameByUserId(\Yii::$app->user->id);
                 $this->_model->CONSIGNEE = $this->consignee;
                 $this->_model->MOBILE = $this->mobile;
                 $this->_model->PROVINCE = $this->province;
-                $this->_model->CITY = $this->city;
-                $this->_model->COUNTY = $this->county;
+                $this->_model->LGA_NAME = $this->lgaName;
+                $this->_model->CITY_NAME = $this->cityName;
                 $this->_model->ADDRESS = $this->address;
                 $this->_model->IS_DEFAULT = $this->isDefault ? 1 : 0;
                 $this->_model->CREATED_AT = Date::nowTime();
@@ -144,8 +149,8 @@ class ReceiveAddressForm extends Model
                 $this->_model->CONSIGNEE = $this->consignee;
                 $this->_model->MOBILE = $this->mobile;
                 $this->_model->PROVINCE = $this->province;
-                $this->_model->CITY = $this->city;
-                $this->_model->COUNTY = $this->county;
+                $this->_model->LGA_NAME = $this->lgaName;
+                $this->_model->CITY_NAME = $this->cityName;
                 $this->_model->ADDRESS = $this->address;
                 $this->_model->IS_DEFAULT = $this->isDefault ? 1 : 0;
                 $this->_model->UPDATED_AT = Date::nowTime();

+ 21 - 8
common/models/forms/RechargeForm.php

@@ -6,6 +6,7 @@ use common\components\Model;
 use common\helpers\Cache;
 use common\helpers\Date;
 use common\helpers\Form;
+use common\helpers\PayStack;
 use common\helpers\Tool;
 use common\helpers\user\Cash;
 use common\helpers\user\Info;
@@ -31,6 +32,7 @@ class RechargeForm extends Model {
 //    public $bankCounty;
 
     public $sn;
+    public $currency;
     public $amount;
     public $bankRealName;
 
@@ -42,7 +44,7 @@ class RechargeForm extends Model {
     public function rules() {
         return [
             [['userName', 'idCard', 'applyAmount', 'auditStatus', 'remark', 'selectedIds', 'sn','amount', 'bankRealName', 'bankNo'], 'trim'],
-            [['selectedIds', 'auditStatus', 'userName','applyAmount','openBank','bankNo','bankAddress'], 'required'],
+            [['selectedIds', 'auditStatus', 'userName','applyAmount', 'currency'/*,'openBank','bankNo','bankAddress'*/], 'required'],
             [['selectedIds'], 'exist', 'targetClass' => Recharge::class, 'targetAttribute' => 'ID', 'message' => '充值申请不存在'],
             [['userName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME', 'message' => '会员不存在'],
             [['applyAmount'], 'price'],
@@ -60,7 +62,7 @@ class RechargeForm extends Model {
         $parentScenarios = parent::scenarios();
         $customScenarios = [
             'addByAdmin' => ['userName', 'applyAmount'],
-            'addByUser' => ['applyAmount','openBank','bankNo','bankAddress'],
+            'addByUser' => ['applyAmount','openBank','bankNo','bankAddress','currency'],
             'statusByAdmin' => ['selectedIds', 'auditStatus', 'createRemark'],
         ];
         return array_merge($parentScenarios, $customScenarios);
@@ -74,9 +76,10 @@ class RechargeForm extends Model {
             'selectedIds' => '充值申请ID',
             'userName' => '会员编号',
             'applyAmount' => '申请充值的金额',
-            'openBank' => '汇款银行',
-            'bankNo' => '汇款账号',
-            'bankAddress' => '银行支行',
+//            'openBank' => '汇款银行',
+//            'bankNo' => '汇款账号',
+//            'bankAddress' => '银行支行',
+            'currency' => '货币',
 //            'bankProvince' => '银行省',
 //            'bankCity' => '银行市',
 //            'bankCounty' => '银行县',
@@ -185,6 +188,12 @@ class RechargeForm extends Model {
         }
         $db = \Yii::$app->db;
         $transaction = $db->beginTransaction();
+        // 向paystack发起订单
+        $userInfo = Info::baseInfo($this->_userId);
+        $rechargeOrder = PayStack::transactionInit($this->currency, $this->applyAmount, $userInfo['EMAIL']);
+        if($rechargeOrder['status']!=1){
+            throw new Exception('api error');
+        }
         try {
             $nowTime = Date::nowTime();
             $period = Recharge::getPeriod($nowTime);
@@ -199,10 +208,14 @@ class RechargeForm extends Model {
             $rechargeModel->RECHARGE_PERIOD_NUM = $period['nowPeriodNum'];
             $rechargeModel->RECHARGE_YEAR = $period['nowYear'];
             $rechargeModel->RECHARGE_MONTH = $period['nowMonth'];
+            $rechargeModel->CURRENCY = $this->currency;
             $rechargeModel->AMOUNT = $this->applyAmount;
-            $rechargeModel->OPEN_BANK = $this->openBank;
-            $rechargeModel->BANK_ADDRESS = $this->bankAddress;
-            $rechargeModel->BANK_NO = $this->bankNo;
+            $rechargeModel->RECHARGE_REF = $rechargeOrder['data']['reference'];
+            $rechargeModel->RECHARGE_ORDER_ID = $rechargeOrder['data']['access_code'];
+            $rechargeModel->RECHARGE_STATUS = 0;
+            $rechargeModel->OPEN_BANK = 'a';
+            $rechargeModel->BANK_ADDRESS = 'b';
+            $rechargeModel->BANK_NO = 'c';
 //            $rechargeModel->BANK_PROVINCE = $this->bankProvince ?? 0;
 //            $rechargeModel->BANK_CITY = $this->bankCity ?? 0;
 //            $rechargeModel->BANK_COUNTY = $this->bankCounty ?? 0;

+ 1 - 1
common/models/forms/ShopGoodsForm.php

@@ -129,7 +129,7 @@ class ShopGoodsForm extends Model
             }
 
             // 购买方式格式化为','分割的方式
-            $sellType = implode(',', array_column($sellType, 'id'));
+            $this->sellType = implode(',', array_column($sellType, 'id'));
             // 如果是普通商品,有PV,旅游、名车、豪宅商品没有PV
             if ($this->categoryType != 1) {
                 $this->pricePv = 0;

+ 7 - 3
common/models/forms/UserForm.php

@@ -41,6 +41,8 @@ class UserForm extends Model
     public $openBank;
     public $bankAddress;
     public $bankNo;
+    public $email;
+
     //修改密码
     public $password;
     public $oldPassword;
@@ -69,7 +71,7 @@ class UserForm extends Model
     public function rules()
     {
         return [
-            [['userId', 'userName', 'zcPv', 'zcAmount', 'conUserName', 'recUserName','conUid', 'recUid', 'location','nation','realName', 'mobile','openBank','bankAddress','bankNo'], 'trim'],
+            [['userId', 'userName', 'zcPv', 'zcAmount', 'conUserName', 'recUserName','conUid', 'recUid', 'location','nation','realName', 'mobile','openBank','bankAddress','bankNo', 'email'], 'trim'],
             [['userId', 'userName', 'zcPv', 'zcAmount', 'conUid', 'recUid', 'location'], 'required', 'on'=>'addWithUid'],
             [['userId', 'userName', 'zcPv', 'zcAmount', 'conUserName', 'recUserName', 'location'], 'required', 'on'=>['addWithUserName', 'addByAdmin']],
             [['idCard', 'allData'], 'required', 'on'=>['addWithUserName']],
@@ -81,7 +83,7 @@ class UserForm extends Model
             [['conUid', 'location'], 'required', 'on'=>['validateLocation', 'validateAddWithUid']],
             [['conUserName', 'location'], 'required', 'on'=>['validateLocationConName', 'validateAddWithName']],
 
-            [['nation','realName', 'mobile', 'idCard', 'openBank', 'bankAddress', 'bankNo'], 'required', 'on'=>'modifyProfile'],
+            [['nation','realName', 'mobile', 'idCard', 'openBank', 'bankAddress', 'bankNo', 'email'], 'required', 'on'=>'modifyProfile'],
             [['oldPassword','verifyPassword'], 'required','on' => ['modifyPassword', 'modifyPasswordPay', 'noLoginModifyPassword']],
             [['password'], 'required','on' => ['modifyPassword', 'noLoginModifyPassword']],
             [['payPassword'], 'required','on' => ['modifyPasswordPay']],
@@ -122,6 +124,7 @@ class UserForm extends Model
             'oldPassword' => '原密码',
             'password' => '登录密码',
             'payPassword' => '支付密码',
+            'email' => 'Email',
         ];
     }
 
@@ -537,7 +540,7 @@ class UserForm extends Model
         if(!$this->validate()){
             return null;
         }
-        $this->userOperateLogger->beforeUpdate(\Yii::$app->user->id,'ID',['select'=>'NATION,OPEN_BANK,BANK_NO,BANK_ADDRESS']);
+        $this->userOperateLogger->beforeUpdate(\Yii::$app->user->id,'ID',['select'=>'NATION,OPEN_BANK,BANK_NO,BANK_ADDRESS,EMAIL']);
 
         $uid = \Yii::$app->user->id;
         $model = User::findOne(['ID'=>$uid]);
@@ -548,6 +551,7 @@ class UserForm extends Model
         $model->OPEN_BANK = $this->openBank;
         $model->BANK_NO = $this->bankNo;
         $model->BANK_ADDRESS = $this->bankAddress;
+        $model->EMAIL = $this->email;
         if(!$model->save()){
             $this->addErrors($model->getErrors());
             return null;

+ 3 - 1
composer.json

@@ -27,7 +27,9 @@
         "ext-pdo": "*",
         "ext-json": "*",
         "monolog/monolog": "^2.4",
-        "tecnickcom/tcpdf": "^6.4"
+        "tecnickcom/tcpdf": "^6.4",
+        "ext-curl": "*",
+        "smladeoye/yii2-paystack": "^1.0"
     },
     "require-dev": {
         "yiisoft/yii2-debug": "~2.0.0",

+ 2 - 2
frontendApi/config/menu.php

@@ -94,9 +94,9 @@ return [
             ['name'=>'转账记录', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'transfer-list', 'routePath'=>'finance/transfer-list', 'show'=>1,'allow'=>'transferRecordSwitch'],
             ['name'=>'我要转账', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'transfer-add', 'routePath'=>'finance/transfer-add', 'show'=>1,'allow'=>'transferSwitch'],
             ['name'=>'提现明细', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'withdraw', 'routePath'=>'finance/withdraw', 'show'=>1,],
-            ['name'=>'申请提现', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'withdraw-add', 'routePath'=>'finance/withdraw-add', 'show'=>0,],
+            ['name'=>'申请提现', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'withdraw-add', 'routePath'=>'finance/withdraw-add', 'show'=>1,],
             ['name'=>'充值明细', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'recharge', 'routePath'=>'finance/recharge', 'show'=>1,],
-            ['name'=>'申请充值', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'recharge-add', 'routePath'=>'finance/recharge-add', 'show'=>0,],
+            ['name'=>'申请充值', 'class'=>'', 'icon'=>'', 'controller'=>'finance', 'action'=>'recharge-add', 'routePath'=>'finance/recharge-add', 'show'=>1,],
         ]
     ],
     'article'=>[

+ 3 - 0
frontendApi/config/urlManagerRules.php

@@ -68,6 +68,7 @@ return [
             'GET show-cart' => 'show-cart',
             'GET reconsume-cart' => 'reconsume-cart',
             'POST sure-order' => 'sure-order',
+            'POST verify-order' => 'verify-order',
             'POST reconsume-sure-order' => 'reconsume-sure-order',
             'GET pay-success' => 'pay-success',
             'GET order-list' => 'order-list',
@@ -75,6 +76,8 @@ return [
             'GET goods-active' => 'goods-active',
             'GET order-export/<orderSn>' => 'order-export',
             'GET dec-order-export/<orderSn>' => 'dec-order-export',
+            'POST sure-approach-order' => 'sure-approach-order',
+            'POST delete-approach-order' => 'delete-approach-order',
         ],
     ],
     [

+ 3 - 3
frontendApi/modules/v1/controllers/BonusController.php

@@ -373,7 +373,7 @@ class BonusController extends BaseController {
         $calcBonus = CalcBonus::find()->where('USER_ID=:USER_ID AND IS_SENT=1', [':USER_ID' => \Yii::$app->user->id])
         ->select('PERIOD_NUM,ORI_BONUS_QY,ORI_BONUS_YC,ORI_BONUS_VIP,ORI_BONUS_STANDARD,ORI_BONUS_BD,ORI_BONUS_TG,
         ORI_BONUS_XF,BONUS_TOTAL,MANAGE_TAX,BONUS_REAL,BONUS_INCOME,ORI_BONUS_YJ,ORI_BONUS_GX,ORI_BONUS_GL,RECONSUME_POINTS,
-        LAST_DEC_LV,LAST_EMP_LV,EXCHANGE_POINTS,ORI_BONUS_BS')
+        LAST_DEC_LV,LAST_EMP_LV,EXCHANGE_POINTS,ORI_BONUS_BS,ORI_BONUS_BS_MNT,ORI_BONUS_BS_ABBR,BONUS_TRAVEL,BONUS_CAR,BONUS_HOUSE')
         ->limit($showBonusPeriodNum)
         ->orderBy('PERIOD_NUM DESC')
         ->asArray()
@@ -411,7 +411,7 @@ class BonusController extends BaseController {
                 $calcBonus[$key]['ORI_BONUS_BS_MNT'] = ['name' => '管理奖金', 'value' => Tool::formatPrice($calcBonus[$key]['ORI_BONUS_BS_MNT'])];
                 $calcBonus[$key]['ORI_BONUS_BS_ABBR'] = ['name' => '绩效奖金', 'value' => Tool::formatPrice($calcBonus[$key]['ORI_BONUS_BS_ABBR'])];
 
-                $calcBonus[$key]['ORI_BONUS_QUARTER'] = ['name' => '季度奖金', 'value' => Tool::formatPrice($calcBonus[$key]['ORI_BONUS_QUARTER'])];
+                $calcBonus[$key]['ORI_BONUS_QUARTER'] = ['name' => '季度奖金', 'value' => Tool::formatPrice($calcBonus[$key]['ORI_BONUS_QUARTER'] ?? 0)];
                 $calcBonus[$key]['BONUS_TRAVEL'] = ['name' => '旅游奖', 'value' => Tool::formatPrice($calcBonus[$key]['BONUS_TRAVEL'])];
                 $calcBonus[$key]['BONUS_CAR'] = ['name' => '名车奖', 'value' => Tool::formatPrice($calcBonus[$key]['BONUS_CAR'])];
                 $calcBonus[$key]['BONUS_HOUSE'] = ['name' => '豪宅奖', 'value' => Tool::formatPrice($calcBonus[$key]['BONUS_HOUSE'])];
@@ -491,7 +491,7 @@ class BonusController extends BaseController {
 //            $tableKey[] = 'BONUS_TOTAL';
 //        }
 
-        return static::notice(['tableData' => $calcBonus, 'tableKey' => $tableKey]);
+        return static::notice(['tableData' => $calcBonus, 'tableKey' => '']);
     }
 
     /**

+ 5 - 3
frontendApi/modules/v1/controllers/ConfigController.php

@@ -9,6 +9,7 @@ namespace frontendApi\modules\v1\controllers;
 
 use common\helpers\Cache;
 use common\helpers\Form;
+use common\helpers\snowflake\SnowFake;
 use common\models\forms\ReceiveAddressForm;
 use common\models\forms\UserConfigForm;
 use common\models\ReceiveAddress;
@@ -86,17 +87,18 @@ class ConfigController extends BaseController
         $condition = ' AND USER_ID=:USER_ID';
         $params[':USER_ID'] = \Yii::$app->user->id;
         $data = ReceiveAddress::lists($condition, $params, [
-            'SELECT' => 'ID,CONSIGNEE,MOBILE,PROVINCE,CITY,COUNTY,ADDRESS,IS_DEFAULT',
+            'SELECT' => 'ID,CONSIGNEE,MOBILE,PROVINCE,LGA_NAME,CITY_NAME,ADDRESS,IS_DEFAULT',
             'orderBy' => 'IS_DEFAULT DESC,CREATED_AT DESC',
             'useSlaves' => true,
         ]);
         if($data['list']){
             foreach($data['list'] as $key=>$row){
                 $data['list'][$key]['PROVINCE_NAME'] = Region::getCnName($row['PROVINCE']);
-                $data['list'][$key]['CITY_NAME'] = Region::getCnName($row['CITY']);
-                $data['list'][$key]['COUNTY_NAME'] = Region::getCnName($row['COUNTY']);
+//                $data['list'][$key]['CITY_NAME'] = Region::getCnName($row['CITY']);
+//                $data['list'][$key]['COUNTY_NAME'] = Region::getCnName($row['COUNTY']);
             }
         }
+//        print_r($data);exit;
         return static::notice($data);
     }
 

+ 2 - 2
frontendApi/modules/v1/controllers/FinanceController.php

@@ -496,11 +496,11 @@ class FinanceController extends BaseController {
             'orderBy' => 'CREATED_AT DESC',
         ]);
         foreach ($data['list'] as $key => $value) {
-            $data['list'][$key]['OPEN_BANK_NAME'] = $value['OPEN_BANK'] ? OpenBank::getCnName($value['OPEN_BANK']) : '';
+//            $data['list'][$key]['OPEN_BANK_NAME'] = $value['OPEN_BANK'] ? OpenBank::getCnName($value['OPEN_BANK']) : '';
             //$data['list'][$key]['BANK_PROVINCE_NAME'] = $value['BANK_PROVINCE'] ? Region::getCnName($value['BANK_PROVINCE']) : '';
             //$data['list'][$key]['BANK_CITY_NAME'] = $value['BANK_CITY'] ? Region::getCnName($value['BANK_CITY']) : '';
             //$data['list'][$key]['BANK_COUNTY_NAME'] = $value['BANK_COUNTY'] ? Region::getCnName($value['BANK_COUNTY']) : '';
-            $data['list'][$key]['STATUS_NAME'] = Recharge::STATUS_NAME[$value['AUDIT_STATUS']];
+            $data['list'][$key]['STATUS_NAME'] = Recharge::RECHARGE_STATUS_NAME[$value['RECHARGE_STATUS']];
         }
         return static::notice($data);
     }

+ 54 - 5
frontendApi/modules/v1/controllers/ShopController.php

@@ -12,8 +12,11 @@ use Codeception\PHPUnit\ResultPrinter\HTML;
 use common\helpers\Date;
 use common\helpers\Form;
 use common\helpers\user\Info;
+use common\models\ApproachOrder;
+use common\models\ApproachOrderGoods;
 use common\models\DealType;
 use common\models\DecOrder;
+use common\models\forms\ApproachOrderForm;
 use common\models\forms\DeclarationForm;
 use common\models\forms\OrderForm;
 use common\models\Order;
@@ -131,8 +134,8 @@ class ShopController extends BaseController {
             $formModel->remark = '复销备注';
             $post = \Yii::$app->request->post();
             $post['type'] = DeclarationForm::TYPE_FX;
-            if ($formModel->load($post, '') && $formModel->add()) {
-                return static::notice('购物成功');
+            if ($formModel->load($post, '') && $order = $formModel->add()) {
+                return static::notice($order);
             } else {
                 return static::notice(Form::formatErrorsForApi($formModel->getErrors()),400);
             }
@@ -152,6 +155,48 @@ class ShopController extends BaseController {
         return static::notice($data);
     }
 
+    /**
+     * 确认订单
+     */
+    public function actionSureApproachOrder(){
+        if (\Yii::$app->request->isPost) {
+            $formModel = new ApproachOrderForm();
+            $formModel->scenario = 'userOrder';
+            $formModel->remark = '复销备注';
+            $post = \Yii::$app->request->post();
+            $post['type'] = DeclarationForm::TYPE_FX;
+            if ($formModel->load($post, '') && $order = $formModel->add()) {
+                return static::notice($order);
+            } else {
+                return static::notice(Form::formatErrorsForApi($formModel->getErrors()),400);
+            }
+        }
+    }
+
+    /**
+     * 订单支付成功
+     * @throws \yii\web\HttpException
+     */
+    public function actionVerifyOrder(){
+        if (\Yii::$app->request->isPost) {
+            return parent::edit(ApproachOrderForm::class, 'PayStack pay Success', 'verifyPayStack', ['verifyPayStack']);
+        }
+
+        return static::notice('非法请求', 400);
+    }
+
+    /**
+     * 删除准订单
+     */
+    public function actionDeleteApproachOrder()
+    {
+        $orderSn = \Yii::$app->request->post('orderSn');
+        ApproachOrder::deleteAll('SN = :SN', [':SN' => $orderSn]);
+        ApproachOrderGoods::deleteAll('ORDER_SN = :ORDER_SN', [':ORDER_SN' => $orderSn]);
+
+        return static::notice('');
+    }
+
     /**
      * 我的报单
      * @return mixed
@@ -194,8 +239,10 @@ class ShopController extends BaseController {
             ],
         ]);
         foreach ($data['list'] as $key => $value) {
-            $data['list'][$key]['PAY_AT'] = Date::convert($value['PAY_AT'],'Y-m-d H:i:s');
+            $data['list'][$key]['PAY_AT'] = $value['PAY_AT'] ? Date::convert($value['PAY_AT'],'Y-m-d H:i:s') : '';
             $data['list'][$key]['CATEGORY_TYPE'] = intval($value['CATEGORY_TYPE']);
+            $data['list'][$key]['PAY_TYPE'] = array_column(ShopGoods::SALE_TYPE, NULL, 'label')[$value['PAY_TYPE']]['name'] ?? '';
+            $data['list'][$key]['STATUS'] = \Yii::$app->params['orderStatus'][$value['STATUS']]['label'] ?? '';
             $data['list'][$key]['CATEGORY'] = array_column(ShopGoods::CATEGORY_TYPE, NULL, 'id')[$value['CATEGORY_TYPE']]['name'] ?? '普通商品';
             $data['list'][$key]['FULL_ADDRESS'] = '';
             if($value['PROVINCE']){
@@ -508,8 +555,10 @@ ORDER;
         ob_clean();
 
         $file_name = $orderSn . '.pdf';
-        $path = '/pdfs/' . $file_name;
-        $pdf->Output(Yii::$app->basePath . '/web' . $path, 'F');
+        $path = 'pdfs/' . $file_name;
+        $pdf->Output(Yii::$app->basePath . '/web/' . $path, 'F');
+
+        @exec('chmod -R 777 /' . Yii::$app->basePath . '/web' . $path);
 
         return static::notice(['fileUrl' => $path, 'targetName' => $file_name]);
     }

+ 2 - 1
frontendEle/package.json

@@ -22,8 +22,9 @@
     "element-ui": "^2.13.0",
     "nix-tinymce": "^1.0.7",
     "v-charts": "^1.16.20",
-    "vue": "^2.6.11",
+    "vue": "^2.6.14",
     "vue-countup-v2": "^1.0.3",
+    "vue-paystack": "^2.0.4",
     "vue-router": "^3.0.2",
     "vuex": "^3.0.1"
   },

+ 5 - 5
frontendEle/src/components/DecListTable.vue

@@ -8,20 +8,20 @@
         </template>
       </el-table-column>
       <el-table-column label="报单金额" prop="DEC_AMOUNT" v-if="type!=='OR'"></el-table-column>
-      <el-table-column label="报单PV" prop="DEC_PV" v-if="type!=='OR'"></el-table-column>
+      <el-table-column label="报单BV" prop="DEC_PV" v-if="type!=='OR'"></el-table-column>
       <el-table-column label="订货单金额" prop="ORDER_AMOUNT" v-if="type==='OR'"></el-table-column>
-      <el-table-column label="订货单PV" prop="ORDER_PV" v-if="type==='OR'"></el-table-column>
+      <el-table-column label="订货单BV" prop="ORDER_PV" v-if="type==='OR'"></el-table-column>
       <el-table-column label="支付钱包">
         <template slot-scope="scope">
           {{paidType[scope.row.PAID_WALLET].title}}<br>
         </template>
       </el-table-column>
-      <el-table-column label="返利PV" v-if="type==='OR'">
+      <el-table-column label="返利BV" v-if="type==='OR'">
         <template slot-scope="scope">
           {{scope.row.FL_PV}}<br>
         </template>
       </el-table-column>
-      <el-table-column label="补贴PV" v-if="type==='OR'">
+      <el-table-column label="补贴BV" v-if="type==='OR'">
         <template slot-scope="scope">
           {{scope.row.BT_PV}}<br>
         </template>
@@ -85,4 +85,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 1 - 0
frontendEle/src/utils/network.js

@@ -100,6 +100,7 @@ const network = {
           // 更新本地userInfo
           userInfo.userId(response.ID)
           userInfo.userName(response.USER_NAME)
+          userInfo.userEmail(response.EMAIL)
           userInfo.baseData({AVATAR: response.AVATAR,VERIFIED: response.VERIFIED,DEC_LV: response.DEC_LV,EMP_LV: response.EMP_LV,PROVINCE: response.PROVINCE,CITY: response.CITY,COUNTY: response.COUNTY})
           // 成功
           resolve(response)

+ 12 - 1
frontendEle/src/utils/userInfo.js

@@ -7,6 +7,7 @@ const userInfo = {
   clear () {
     localStorage.removeItem('userId')
     localStorage.removeItem('userName')
+    localStorage.removeItem('userEmail')
     localStorage.removeItem('accessToken')
     localStorage.removeItem('accessTokenExpiresIn')
     localStorage.removeItem('accessTokenUpdateAt')
@@ -57,6 +58,16 @@ const userInfo = {
     }
     localStorage.setItem('userName', arg[0])
   },
+  userEmail (...arg) {
+    if (arg.length === 0) {
+      return localStorage.getItem('userEmail')
+    }
+    if (arg[0] === '') {
+      localStorage.removeItem('userEmail')
+      return
+    }
+    localStorage.setItem('userEmail', arg[0])
+  },
   accessToken (...arg) {
     if (arg.length === 0) {
       return localStorage.getItem('accessToken')
@@ -156,4 +167,4 @@ const userInfo = {
   },
 }
 
-export default userInfo
+export default userInfo

+ 34 - 13
frontendEle/src/views/config/receive-address-edit.vue

@@ -16,6 +16,27 @@
           </template>
           <el-input v-model="form.mobile"></el-input>
         </el-form-item>
+        <el-form-item>
+          <template slot="label">
+            <span class="text-danger">*</span>
+            House Number & Street Name
+          </template>
+          <el-input v-model="form.address"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <template slot="label">
+            <span class="text-danger">*</span>
+            City
+          </template>
+          <el-input v-model="form.cityName"></el-input>
+        </el-form-item>
+        <el-form-item>
+          <template slot="label">
+            <span class="text-danger">*</span>
+            Local Government Area
+          </template>
+          <el-input v-model="form.lgaName"></el-input>
+        </el-form-item>
         <el-form-item prop="areaSelected">
           <template slot="label">
             <span class="text-danger">*</span>
@@ -27,13 +48,7 @@
             v-model="form.areaSelected">
           </el-cascader>
         </el-form-item>
-        <el-form-item>
-          <template slot="label">
-            <span class="text-danger">*</span>
-            详细地址
-          </template>
-          <el-input v-model="form.address"></el-input>
-        </el-form-item>
+
         <el-form-item>
           <template slot="label">
             是否默认
@@ -87,8 +102,10 @@
           consignee: this.form.consignee,
           mobile: this.form.mobile,
           province: this.form.areaSelected[0] ? this.form.areaSelected[0] : '',
-          city: this.form.areaSelected[1] ? this.form.areaSelected[1] : '',
-          county: this.form.areaSelected[2] ? this.form.areaSelected[2] : '',
+          // city: this.form.areaSelected[1] ? this.form.areaSelected[1] : '',
+          // county: this.form.areaSelected[2] ? this.form.areaSelected[2] : '',
+          lgaName: this.form.lgaName,
+          cityName: this.form.cityName,
           address: this.form.address,
           isDefault: this.form.isDefault,
         }
@@ -99,8 +116,10 @@
             consignee: this.form.consignee,
             mobile: this.form.mobile,
             province: this.form.areaSelected[0] ? this.form.areaSelected[0] : '',
-            city: this.form.areaSelected[1] ? this.form.areaSelected[1] : '',
-            county: this.form.areaSelected[2] ? this.form.areaSelected[2] : '',
+            // city: this.form.areaSelected[1] ? this.form.areaSelected[1] : '',
+            // county: this.form.areaSelected[2] ? this.form.areaSelected[2] : '',
+            lgaName: this.form.lgaName,
+            cityName: this.form.cityName,
             address: this.form.address,
             isDefault: this.form.isDefault,
           }
@@ -122,8 +141,10 @@
           this.form.consignee = response.CONSIGNEE
           this.form.mobile = response.MOBILE
           this.form.areaSelected[0] = response.PROVINCE
-          this.form.areaSelected[1] = response.CITY
-          this.form.areaSelected[2] = response.COUNTY
+          // this.form.areaSelected[1] = response.CITY
+          // this.form.areaSelected[2] = response.COUNTY
+          this.form.lgaName = response.LGA_NAME
+          this.form.cityName = response.CITY_NAME
           this.form.address = response.ADDRESS
           this.form.isDefault = response.IS_DEFAULT === '1' ? true : false
           this.loading = false

+ 4 - 4
frontendEle/src/views/config/receive-address-list.vue

@@ -4,10 +4,10 @@
       <el-table class="table-box" ref="multipleTable" :data="tableData" stripe style="width: 100%;">
         <el-table-column label="收货人" prop="CONSIGNEE" width="150"></el-table-column>
         <el-table-column label="手机号码" prop="MOBILE" width="150"></el-table-column>
-        <el-table-column label="省/市" prop="PROVINCE_NAME" width="150"></el-table-column>
-        <el-table-column label="市/区" prop="CITY_NAME" width="150"></el-table-column>
-        <el-table-column label="区/县" prop="COUNTY_NAME" width="150"></el-table-column>
-        <el-table-column label="详细地址" prop="ADDRESS" ></el-table-column>
+        <el-table-column label="House" prop="ADDRESS" width="350"></el-table-column>
+        <el-table-column label="City" prop="CITY_NAME" width="150"></el-table-column>
+        <el-table-column label="Local Government Area" prop="LGA_NAME" width="150"></el-table-column>
+        <el-table-column label="State" prop="PROVINCE_NAME" width="150"></el-table-column>
         <el-table-column label="是否默认" width="100">
           <template slot-scope="scope">
             {{scope.row.IS_DEFAULT === '1' ? '是' : '否'}}

+ 13 - 13
frontendEle/src/views/finance/perf.vue

@@ -13,40 +13,40 @@
           <template slot-scope="scope">
             <el-form label-position="left" inline class="demo-table-expand">
               <el-form-item label="个人首购">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_ZC)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_ZC)}}BV</span>
               </el-form-item>
               <el-form-item label="个人增购">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_ZG)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_ZG)}}BV</span>
               </el-form-item>
               <el-form-item label="个人零售">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_LS)}}BV</span>
               </el-form-item>
               <el-form-item label="个人复销">
-                <span>{{tool.formatPrice(scope.row.PV_PCS_FX)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PCS_FX)}}BV</span>
               </el-form-item>
               <el-form-item label="左区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_1L_ZC) + Number.parseFloat(scope.row.PV_1L_ZG) + Number.parseFloat(scope.row.PV_1L_LS) + Number.parseFloat(scope.row.PV_1L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_1L_ZC) + Number.parseFloat(scope.row.PV_1L_ZG) + Number.parseFloat(scope.row.PV_1L_LS) + Number.parseFloat(scope.row.PV_1L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="中区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_2L_ZC) + Number.parseFloat(scope.row.PV_2L_ZG) + Number.parseFloat(scope.row.PV_2L_LS) + Number.parseFloat(scope.row.PV_2L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_2L_ZC) + Number.parseFloat(scope.row.PV_2L_ZG) + Number.parseFloat(scope.row.PV_2L_LS) + Number.parseFloat(scope.row.PV_2L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="右区业绩">
-                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_3L_ZC) + Number.parseFloat(scope.row.PV_3L_ZG) + Number.parseFloat(scope.row.PV_3L_LS) + Number.parseFloat(scope.row.PV_3L_FX))}}PV</span>
+                <span>{{tool.formatPrice(Number.parseFloat(scope.row.PV_3L_ZC) + Number.parseFloat(scope.row.PV_3L_ZG) + Number.parseFloat(scope.row.PV_3L_LS) + Number.parseFloat(scope.row.PV_3L_FX))}}BV</span>
               </el-form-item>
               <el-form-item label="零售区业绩">
-                <span>{{tool.formatPrice(scope.row.PV_PERSON_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.PV_PERSON_LS)}}BV</span>
               </el-form-item>
               <el-form-item label="上期左区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_1L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_1L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期中区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_2L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_2L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期右区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_3L)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_3L)}}BV</span>
               </el-form-item>
               <el-form-item label="上期零售区结余未碰业绩">
-                <span>{{tool.formatPrice(scope.row.SURPLUS_LS)}}PV</span>
+                <span>{{tool.formatPrice(scope.row.SURPLUS_LS)}}BV</span>
               </el-form-item>
             </el-form>
           </template>
@@ -132,4 +132,4 @@ export default {
     margin-right: 0;
     margin-bottom: 0;
   }
-</style>
+</style>

+ 80 - 89
frontendEle/src/views/finance/recharge-add.vue

@@ -1,100 +1,91 @@
 <template>
-    <div v-loading="loading">
-        <div class="white-box">
-            <el-form ref="form"  label-width="250px" class="form-page">
-                <el-form-item label="充值金额">
-                    <el-input v-model="form.applyAmount"></el-input>
-                </el-form-item>
-                <el-form-item label="银行账号">
-                    <el-input v-model="form.bankNo"></el-input>
-                </el-form-item>
-                <el-form-item label="汇款银行">
-                    <el-select v-model="form.openBank" placeholder="请选择开户行">
-                        <el-option v-for="(item,index) in allOpenBank" :key="index" :label="item.BANK_NAME"
-                                   :value="item.BANK_CODE"></el-option>
-                    </el-select>
-                </el-form-item>
-
-                <el-form-item label="开户支行">
-                    <el-input v-model="form.bankAddress"></el-input>
-                </el-form-item>
-
-                <el-form-item>
-                    <el-button type="primary" @click="onSubmits" :loading="submitButtonStat">保存</el-button>
-                </el-form-item>
-            </el-form>
-        </div>
+  <div v-loading="loading">
+    <div class="white-box">
+      <el-form ref="form"  label-width="250px" class="form-page">
+        <el-form-item label="货币">
+          <el-select v-model="form.currency" placeholder="请选择">
+            <el-option
+              v-for="item in currencyList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value">
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="充值金额">
+            <el-input v-model="form.applyAmount"></el-input>
+        </el-form-item>
+        <el-form-item>
+            <el-button type="primary" @click="onSubmits" :loading="submitButtonStat">保存</el-button>
+        </el-form-item>
+      </el-form>
     </div>
+  </div>
 </template>
 
 <script>
-    import Vue from 'vue'
-    import network from '@/utils/network'
-    import baseInfo from '@/utils/baseInfo'
-    import store from '@/utils/vuexStore'
-    export default {
-        name: "recharge-add",
-        mounted() {
-            this.getData()
-        },
-        data(){
-            return{
-
-                form:{
-                    applyAmount:'',
-                    bankNo:'',
-                    bankAddress:'',
-                    openBank:'',
-
-
-                },
-                loading: false,
-                allOpenBank: null,
-                submitButtonStat: false
-            }
-        },
-        methods: {
-            getData () {
-
-                network.getData(`/finance/recharge-add`).then(response => {
-                    console.log(response)
-                    this.loading = false;
-                    this.allOpenBank = response.allOpenBank;
-
-                }).catch(() => {
-                });
-
-            },
-            onSubmits() {
-                this.submitButtonStat = true
-                let path = '/finance/recharge-add'
-                let postData = {
-                    openBank: this.form.openBank,
-                    bankAddress: this.form.bankAddress,
-                    bankNo: this.form.bankNo,
-                    applyAmount: this.form.applyAmount,
-
-
-                };
-
-                return network.postData(path, postData).then(response => {
-                    console.log(response);
-                    this.$message({
-                        message: response,
-                        type: 'success'
-                    })
-                    this.submitButtonStat = false
-                    this.$router.go(-1)
-                }).catch(() => {
-                    this.submitButtonStat = false
-                })
-            },
+import Vue from 'vue'
+import network from '@/utils/network'
+import baseInfo from '@/utils/baseInfo'
+import store from '@/utils/vuexStore'
+export default {
+  name: "recharge-add",
+  mounted() {
+    this.getData()
+  },
+  data(){
+    return{
+      currencyList: {
+        'NGN': {
+          'value': 'NGN',
+          'label': 'Nigeria naira (NGN)'
         }
-
-
+      },
+      form:{
+        currency: 'NGN',
+        applyAmount: '',
+        // bankNo: '',
+        // bankAddress: '',
+        // openBank: '',
+      },
+      loading: false,
+      allOpenBank: null,
+      submitButtonStat: false
     }
+  },
+  methods: {
+    getData () {
+      network.getData(`/finance/recharge-add`).then(response => {
+        console.log(response)
+        this.loading = false;
+        this.allOpenBank = response.allOpenBank;
+      }).catch(() => {
+      });
+    },
+    onSubmits() {
+      this.submitButtonStat = true
+      let path = '/finance/recharge-add'
+      let postData = {
+        currency: this.form.currency,
+        applyAmount: this.form.applyAmount,
+      };
+      return network.postData(path, postData).then(response => {
+        // console.log(postData)
+        // console.log(response);
+        this.$message({
+          message: response,
+          type: 'success'
+        })
+        this.submitButtonStat = false
+        this.$router.go(-1)
+      }).catch(() => {
+        this.submitButtonStat = false
+      })
+    },
+  }
+}
 </script>
 
 <style scoped>
 
-</style>
+</style>

+ 36 - 24
frontendEle/src/views/finance/recharge.vue

@@ -3,43 +3,55 @@
         <div v-loading="loading">
             <div class="white-box">
                 <el-table class="withdraw-table" :data="tableData" stripe style="width: 100%;">
-
-                    <el-table-column label="创建时间">
+                    <el-table-column label="SN" prop="SN" width="200px"><!--货币名称-->
+                    </el-table-column>
+                    <el-table-column label="创建时间" width="160px">
                         <template slot-scope="scope">
                             {{tool.formatDate(scope.row.CREATED_AT)}}
                         </template>
                     </el-table-column>
 
-                    <el-table-column label="充值金额" prop="AMOUNT">
+<!--                    <el-table-column label="RECHARGE ORDER ID" prop="RECHARGE_ORDER_ID" width="200px">&lt;!&ndash;PS订单ID&ndash;&gt;-->
+<!--                    </el-table-column>-->
 
+                    <el-table-column label="CURRENCY" prop="CURRENCY" width="100px"><!--货币名称-->
                     </el-table-column>
 
-                    <el-table-column label="充值状态名称">
-                        <template slot-scope="scope">
-                        <el-tag :type="tool.statusType(scope.row.AUDIT_STATUS)">{{scope.row.STATUS_NAME}}</el-tag>
-                        </template>
+                    <el-table-column label="充值金额" prop="AMOUNT" width="150px">
                     </el-table-column>
-                    <el-table-column label="汇款银行" prop="OPEN_BANK_NAME">
 
+                    <el-table-column label="充值状态" width="200px">
+                      <template slot-scope="scope">
+                        <el-tag :type="tool.statusType(scope.row.RECHARGE_STATUS)">{{scope.row.STATUS_NAME}}</el-tag>
+                      </template>
                     </el-table-column>
 
-                    <el-table-column label="我的汇款账号" prop="BANK_NO">
-
+                    <el-table-column label="动作">
+                      <template slot-scope="scope">
+<!--                        <el-button type="primary" plain>主要按钮</el-button>-->
+<!--                        <el-button type="success" plain>成功按钮</el-button>-->
+<!--                        <el-button type="info" plain>信息按钮</el-button>-->
+<!--                        <el-button type="warning" plain>警告按钮</el-button>-->
+<!--                        <el-button type="danger" plain>危险按钮</el-button>-->
+                        <template v-if="scope.row.RECHARGE_STATUS==0">
+                          <el-button type="primary" plain>去支付</el-button>
+                          <el-button type="info" plain disabled>验证</el-button>
+                        </template>
+                        <template v-else-if="scope.row.RECHARGE_STATUS==1">
+                          <el-button type="info" plain disabled>已支付</el-button>
+                          <el-button type="primary" plain>验证</el-button>
+                        </template>
+                        <template v-else-if="scope.row.RECHARGE_STATUS==2">
+                          <el-button type="info" plain disabled>已支付</el-button>
+                          <el-button type="info" plain disabled>已验证</el-button>
+                        </template>
+                        <template v-else>
+                          <el-button type="danger" plain disabled>支付失败</el-button>
+                          <el-button type="danger" plain disabled>验证</el-button>
+                        </template>
+                      </template>
                     </el-table-column>
 
-                      <el-table-column label="打印凭证" width="200">
-                            <template slot-scope="scope">
-                                <el-button type="primary" size="small" @click="handleAddInvoiceShow(scope.row)"
-                                           v-if="scope.row.AUDIT_STATUS==='0'" icon="el-icon-upload">上传凭证
-                                </el-button>
-
-                                <el-button type="success" size="small" @click="handleInvoiceShow(scope.row)"
-                                           v-if="scope.row.AUDIT_STATUS!=='0'" icon="el-icon-view">查看凭证
-                                </el-button>
-                            </template>
-                        </el-table-column>
-
-
                 </el-table>
                 <div class="white-box-footer">
                     <el-button type="primary" size="small" @click="handleAdd">我要充值</el-button>
@@ -215,4 +227,4 @@
 
 <style scoped>
 
-</style>
+</style>

+ 1 - 1
frontendEle/src/views/shop/dec-order-list.vue

@@ -6,7 +6,7 @@
                 <el-table-column label="商品名称" prop="GOODS_TITLE"></el-table-column>
                 <el-table-column label="数量" prop="BUY_NUMS"></el-table-column>
                 <el-table-column label="报单金额" prop="REAL_PRICE"></el-table-column>
-                <el-table-column label="报单PV" prop="REAL_PV"></el-table-column>
+                <el-table-column label="报单BV" prop="REAL_PV"></el-table-column>
                 <el-table-column label="报单编号" prop="DEC_SN"></el-table-column>
                 <el-table-column label="订单编号" prop="ORDER_SN"></el-table-column>
                 <el-table-column label="会员编号" prop="USER_NAME"></el-table-column>

+ 1 - 1
frontendEle/src/views/shop/index.vue

@@ -28,7 +28,7 @@
                               <span>{{ Math.round(scope.row.SELL_PRICE * 100) / 100 }}</span>
                           </template>
                       </el-table-column>
-                      <el-table-column label="价格PV" prop="PRICE_PV" v-if="goodsCategory === '1'">
+                      <el-table-column label="价格BV" prop="PRICE_PV" v-if="goodsCategory === '1'">
                           <template slot-scope="scope">
                               <span>{{ Math.round(scope.row.PRICE_PV * 100) / 100 }}</span>
                           </template>

+ 9 - 13
frontendEle/src/views/shop/order-list.vue

@@ -10,7 +10,7 @@
                         {{ Math.round(props.row.REAL_PRICE * props.row.BUY_NUMS * 100) / 100 }}
                     </template>
                 </el-table-column>
-                <el-table-column label="会员PV">
+                <el-table-column label="会员BV">
                     <template slot-scope="props">
                         <span v-if="![4, 5, 6].includes(props.row.CATEGORY_TYPE)">{{ Math.round(props.row.REAL_PV * props.row.BUY_NUMS * 100) / 100 }}</span>
                         <span v-else>0</span>
@@ -23,7 +23,9 @@
                 <el-table-column label="收货人" prop="CONSIGNEE"></el-table-column>
                 <el-table-column label="收货电话" prop="MOBILE"></el-table-column>
                 <el-table-column label="地址" prop="FULL_ADDRESS"></el-table-column>
+                <el-table-column label="支付方式" prop="PAY_TYPE"></el-table-column>
                 <el-table-column label="支付时间" prop="PAY_AT"></el-table-column>
+                <el-table-column label="订单状态" prop="STATUS"></el-table-column>
                 <el-table-column label="操作">
                   <template slot-scope="scope">
                       <el-button type="primary" size="small" @click.native="handleOrderExportPDF(scope.row.SN)">导出PDF</el-button>
@@ -41,6 +43,7 @@
     import network from '@/utils/network'
     import tool from '@/utils/tool'
     import Pagination from '@/components/Pagination'
+    import {SERVER_API_HTTP_TYPE, SERVER_API_DOMAIN} from '@/utils/config'
     export default {
         name: "order-list",
         components: {Pagination},
@@ -75,16 +78,7 @@
   //
       objectSpanMethod(obj) {
 
-        if (
-          obj.columnIndex === 5 ||
-          obj.columnIndex === 6 ||
-          obj.columnIndex === 7 ||
-          obj.columnIndex === 8 ||
-          obj.columnIndex === 9 ||
-          obj.columnIndex === 10||
-          obj.columnIndex === 11||
-          obj.columnIndex === 12
-        ) {
+        if (obj.columnIndex > 4) {
           // ⼆维数组存储的数据取出
           var _row = this.spanArr[obj.rowIndex];
           var _col = _row > 0 ? 1 : 0;
@@ -113,7 +107,9 @@
               orderList[index].REAL_NAME === orderList[index - 1].REAL_NAME &&
               orderList[index].CONSIGNEE === orderList[index - 1].CONSIGNEE &&
               orderList[index].MOBILE === orderList[index - 1].MOBILE &&
-              orderList[index].PAY_AT === orderList[index - 1].PAY_AT
+              orderList[index].PAY_AT === orderList[index - 1].PAY_AT &&
+              orderList[index].STATUS === orderList[index - 1].STATUS &&
+              orderList[index].PAY_TYPE === orderList[index - 1].PAY_TYPE
             ) {
               // 查找到符合条件的数据时每次要把之前存储的数据+1
               this.spanArr[this.pos] += 1;
@@ -169,7 +165,7 @@
 
                     let downloadElement = document.createElement('a')
                     downloadElement.target = '_blank'
-                    downloadElement.href = fileUrl
+                    downloadElement.href = SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/' + fileUrl
                     // 下载后文件名
                     downloadElement.download = targetName
                     //点击下载

+ 291 - 133
frontendEle/src/views/shop/order.vue

@@ -1,138 +1,179 @@
 <template>
-    <div v-loading="loading">
-        <div class="white-box">
-            <div class="table">
-                <el-table
-                    :data="goods"
-                    style="width: 100%"
-                    show-summary
-                    :summary-method="getSummaries">
-                     <el-table-column label="商品名称" prop="GOODS_NAME">
-                    </el-table-column>
-
-                    <el-table-column label="图片" >
-                        <template slot-scope="scope">
-                            <img :src="scope.row.COVER" alt="" style="width:100%">
-                        </template>
-                    </el-table-column>
-
-                    <el-table-column label="会员价格" prop="member_price">
-                        <template slot-scope="scope">
-                            <span>{{ Math.round(scope.row.member_price * 100) / 100 }}</span>
-                        </template>
-                    </el-table-column>
-                    <el-table-column label="会员PV" prop="member_pv" v-if="category_type === 1">
-                        <template slot-scope="scope">
-                            <span>{{ Math.round(scope.row.member_pv * 100) / 100 }}</span>
-                        </template>
-                    </el-table-column>
-<!--                    <el-table-column label="库存" prop="STORE_NUMS">-->
-<!--                    </el-table-column>-->
-
-                    <el-table-column label="数量" prop="chose_num">
-
-                    </el-table-column>
-                    <el-table-column label="合计金额" prop="member_price_plus">
-                        <template slot-scope="scope">
-                            <span>{{ Math.round(scope.row.member_price_plus * 100) / 100 }}</span>
-                        </template>
-                    </el-table-column>
-                    <el-table-column label="合计PV" prop="member_pv_plus" v-if="category_type === 1">
-                        <template slot-scope="scope">
-                            <span>{{ Math.round(scope.row.member_pv_plus * 100) / 100 }}</span>
-                        </template>
-                    </el-table-column>
-                </el-table>
-            </div>
-            <div class="address_box">
-                请选择收货地址:
-                <el-radio-group v-model="addressId" @change='choseAddress'>
-                    <div v-for="(item , index) in all_address" :key='index' class="address">
-                        <el-radio :label="item.ID" >
-                            {{item.PROVINCE_NAME}}省 {{item.CITY_NAME}}市 {{item.COUNTY_NAME}}县&nbsp;&nbsp;&nbsp;&nbsp;
-                            详细地址:{{item.ADDRESS}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-                            收件人姓名:{{item.CONSIGNEE}}&nbsp;&nbsp;&nbsp;&nbsp;
-                            手机号码:{{item.MOBILE}}
-                        </el-radio>
-                    </div>
-                    <div class="address">
-                      <el-radio label="100000000000000000">自提</el-radio>
-                    </div>
-                </el-radio-group>
-            </div>
-            <div class="address_box">
-                请选择支付方式:
-                <el-radio-group v-model="payType" @change='chosePayType'>
-                    <div v-for="(item, index) in payList" :key='index' class="address">
-                        <el-radio :label="item.label">{{ item.name }}</el-radio>
-                    </div>
-                </el-radio-group>
-            </div>
-            <div class="box address_box">
-                订单合计:
-                <div class="sum">
-                    <div class="sum_box" v-if="category_type === 1">
-                        <div>运费</div>
-                        <div><span v-if="category_type === 1">{{ prefixSign }}</span> {{ payType === "cash" ? freight : pointFreight }} <span v-if="category_type === 1">{{ unit }}</span></div>
-                    </div>
-                    <div class="sum_box">
-                        <div>实付金额</div>
-                        <div><span v-if="category_type === 1">{{ prefixSign }}</span> {{ payType === "cash" ? cashSum : pointsSum }} <span v-if="category_type === 1">{{ unit }}</span></div>
-                    </div>
-                </div>
-            </div>
+    <div>
+        <div v-loading="loading">
+            <div class="white-box">
+                <div class="table">
+                    <el-table
+                        :data="goods"
+                        style="width: 100%"
+                        show-summary
+                        :summary-method="getSummaries">
+                         <el-table-column label="商品名称" prop="GOODS_NAME">
+                        </el-table-column>
 
-            <div class="box address_box">
-                账户余额:
-                <div class="sum">
-                    <div v-if="category_type === 1">
-<!--                        <div class="sum_box">-->
-<!--                            <div>账户积分</div>-->
-<!--                            <div>{{ balance.points }}</div>-->
-<!--                        </div>-->
-                        <div class="sum_box">
-                            <div>账户余额</div>
-                            <div>¥{{ balance.cash }}元</div>
+                        <el-table-column label="图片" >
+                            <template slot-scope="scope">
+                                <img :src="scope.row.COVER" alt="" style="width:100%">
+                            </template>
+                        </el-table-column>
+
+                        <el-table-column label="会员价格" prop="member_price">
+                            <template slot-scope="scope">
+                                <span>{{ Math.round(scope.row.member_price * 100) / 100 }}</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="会员BV" prop="member_pv" v-if="category_type === 1">
+                            <template slot-scope="scope">
+                                <span>{{ Math.round(scope.row.member_pv * 100) / 100 }}</span>
+                            </template>
+                        </el-table-column>
+    <!--                    <el-table-column label="库存" prop="STORE_NUMS">-->
+    <!--                    </el-table-column>-->
+
+                        <el-table-column label="数量" prop="chose_num">
+
+                        </el-table-column>
+                        <el-table-column label="合计金额" prop="member_price_plus">
+                            <template slot-scope="scope">
+                                <span>{{ Math.round(scope.row.member_price_plus * 100) / 100 }}</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="合计BV" prop="member_pv_plus" v-if="category_type === 1">
+                            <template slot-scope="scope">
+                                <span>{{ Math.round(scope.row.member_pv_plus * 100) / 100 }}</span>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                </div>
+                <div class="address_box">
+                    请选择收货地址:
+                    <el-radio-group v-model="addressId" @change='choseAddress'>
+                        <div v-for="(item , index) in all_address" :key='index' class="address">
+                            <el-radio :label="item.ID" >
+                                {{item.PROVINCE_NAME}}省 {{item.CITY_NAME}}市 {{item.COUNTY_NAME}}县&nbsp;&nbsp;&nbsp;&nbsp;
+                                详细地址:{{item.ADDRESS}}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+                                收件人姓名:{{item.CONSIGNEE}}&nbsp;&nbsp;&nbsp;&nbsp;
+                                手机号码:{{item.MOBILE}}
+                            </el-radio>
+                        </div>
+                        <div class="address">
+                          <el-radio label="100000000000000000">自提</el-radio>
+                        </div>
+                    </el-radio-group>
+                </div>
+                <div class="address_box">
+                    请选择支付方式:
+                    <el-radio-group v-model="payType" @change='chosePayType'>
+                        <div v-for="(item, index) in payList" :key='index' class="address">
+                            <el-radio :label="item.label">{{ item.name }}</el-radio>
+                        </div>
+                    </el-radio-group>
+                </div>
+                <div class="box address_box">
+                    订单合计:
+                    <div class="sum">
+                        <div class="sum_box" v-if="category_type === 1">
+                            <div>运费</div>
+                            <div><span v-if="category_type === 1">{{ prefixSign }}</span> {{ payType === "cash" ? freight : pointFreight }} <span v-if="category_type === 1">{{ unit }}</span></div>
                         </div>
                         <div class="sum_box">
-                            <div>兑换点数</div>
-                            <div>{{ balance.exchange }}</div>
+                            <div>实付金额</div>
+                            <div><span v-if="category_type === 1">{{ prefixSign }}</span> {{ payType === "cash" ? cashSum : pointsSum }} <span v-if="category_type === 1">{{ unit }}</span></div>
                         </div>
                     </div>
+                </div>
 
-                    <div v-if="category_type === 4">
-                        <div class="sum_box">
-                            <div>旅游积分</div>
-                            <div>{{ balance.travel_points }}</div>
+                <div class="box address_box">
+                    账户余额:
+                    <div class="sum">
+                        <div v-if="category_type === 1">
+    <!--                        <div class="sum_box">-->
+    <!--                            <div>账户积分</div>-->
+    <!--                            <div>{{ balance.points }}</div>-->
+    <!--                        </div>-->
+                            <div class="sum_box">
+                                <div>账户余额</div>
+                                <div>¥{{ balance.cash }}元</div>
+                            </div>
+                            <div class="sum_box">
+                                <div>兑换点数</div>
+                                <div>{{ balance.exchange }}</div>
+                            </div>
                         </div>
-                    </div>
 
-                    <div v-if="category_type === 5">
-                        <div class="sum_box">
-                            <div>名车积分</div>
-                            <div>{{ balance.car_points }}</div>
+                        <div v-if="category_type === 4">
+                            <div class="sum_box">
+                                <div>旅游积分</div>
+                                <div>{{ balance.travel_points }}</div>
+                            </div>
                         </div>
-                    </div>
 
-                    <div v-if="category_type === 6">
-                        <div class="sum_box">
-                            <div>豪宅积分</div>
-                            <div>{{ balance.house_points }}</div>
+                        <div v-if="category_type === 5">
+                            <div class="sum_box">
+                                <div>名车积分</div>
+                                <div>{{ balance.car_points }}</div>
+                            </div>
+                        </div>
+
+                        <div v-if="category_type === 6">
+                            <div class="sum_box">
+                                <div>豪宅积分</div>
+                                <div>{{ balance.house_points }}</div>
+                            </div>
                         </div>
                     </div>
                 </div>
-            </div>
 
-            <div>
-                <el-button type="primary" @click="goToAccounts()" :loading="submitButtonStat">去结算</el-button>
+                <div>
+                    <el-button type="primary" @click="goToAccounts()" :loading="submitButtonStat">去结算</el-button>
+                </div>
             </div>
         </div>
+
+        <el-dialog title="订单支付" v-if="visible" :visible.sync="visible" width="30%" v-loading="payStackLoading" :before-close="handleClose">
+            <section>
+                <h1>Lorem Ipsum Dolor Sit Amet</h1>
+                <div class="formcontainer">
+                    <el-divider></el-divider>
+                    <div class="container">
+                        <el-form :model="form">
+                            <el-form-item label="Email" label-width="100px" required>
+                                <el-input v-model="form.email" autocomplete="off"></el-input>
+                            </el-form-item>
+                            <el-form-item label="Amount" label-width="100px" required>
+                                <el-input v-model="form.amount" autocomplete="off" readonly></el-input>
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </div>
+            </section>
+
+            <paystack
+                :firstname="form.firstname"
+                :lastname="form.lastname"
+                :amount="form.amount * 100"
+                :email="form.email"
+                :metadata="form.metadata"
+                :currency="form.currency"
+                :paystackkey="form.publicKey"
+                :reference="reference"
+                :callback="processPayment"
+                :close="processClose"
+            >
+                <el-button type="primary" size="small">支 付</el-button>
+<!--                <el-button type="danger" size="small"  class="cancelButton" @click="handleClose">取 消</el-button>-->
+            </paystack>
+        </el-dialog>
     </div>
 </template>
 
 <script>
  import network from '@/utils/network'
  import tool from '@/utils/tool'
+ import userInfo from '@/utils/userInfo'
+ import { PAY_STACK_PUBLIC_KEY, PAY_STACK_CURRENCY } from '@/utils/config'
+ import paystack from 'vue-paystack'
+
     export default{
         name:'order',
         data(){
@@ -156,8 +197,34 @@
                 category_type: '',
                 prefixSign: '¥',
                 unit: '元',
+                sn: '',
+
+                visible: false,
+                payStackLoading: false,
+                form: {
+                    publicKey: PAY_STACK_PUBLIC_KEY,
+                    currency: PAY_STACK_CURRENCY,
+                    firstname: userInfo.userName(),
+                    lastname: '',
+                    email: userInfo.userEmail(),
+                    amount: 0,  // kobo
+                    orderSn: '',
+                    metadata: {
+                        cart_id: this.sn,
+                        custom_fields: [
+                            {
+                                "display_name": "orderSn",
+                                "variable_name": "orderSn",
+                                "value": this.sn
+                            },
+                        ]
+                    },
+                },
             }
         },
+        components: {
+            paystack
+        },
         created(){
             let option= sessionStorage.getItem('order_goods');
             this.category_type = parseInt(sessionStorage.getItem('category_type'))
@@ -187,6 +254,16 @@
                 this.getSumMoney();
             }
         },
+        computed: {
+            reference() {
+                let text = "";
+                let possible =
+                    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+                for (let i = 0; i < 10; i++)
+                    text += possible.charAt(Math.floor(Math.random() * possible.length));
+                return text;
+            }
+        },
         methods:{
             setFreight(){
               if(this.addressId=='100000000000000000'){//如果地址为自提,则运费为0
@@ -220,7 +297,12 @@
                 let amountBalance = 0
                 // 前置判断余额是否够支付
                 if (this.category_type === 1) {
-                    amountBalance = (this.payType === 'cash') ? this.balance.cash : this.balance.exchange
+                    if (this.payType === 'cash') {
+                        amountBalance = this.balance.cash
+                    } else if (this.payType === 'exchange') {
+                        amountBalance = this.balance.exchange
+                    }
+                    // amountBalance = (this.payType === 'cash') ? this.balance.cash : this.balance.exchange
                 } else if (this.category_type === 4) {
                     amountBalance = this.balance.travel_points
                 } else if (this.category_type === 5) {
@@ -231,14 +313,15 @@
 
                 // 提示信息
                 let tips = '余额'
-                if (this.payType !== 'cash') {
+                if (this.payType !== 'cash' && this.payType !== 'pay_stack') {
                     let payObj = this.payList.find((item) => {
                         return item.label === this.payType
                     })
                     tips = (payObj.length <= 0) ? '' : payObj.name
                 }
 
-                if ((amountBalance - this.cashSum) < 0) {
+                // 余额是否充足
+                if ((amountBalance > 0) && (this.payType !== 'pay_stack') && ((amountBalance - this.cashSum) < 0)) {
                     let tips = this.payList[this.payType] ? this.payList[this.payType].label : '余额'
                     this.$message({
                         message: tips + '不足,无法购买商品',
@@ -249,7 +332,6 @@
                 }
 
                 this.submitButtonStat = true
-                // let path = 'sure-order'
                 this.$prompt('请输入支付密码', '提示', {
                     confirmButtonText: '确定',
                     cancelButtonText: '取消',
@@ -258,27 +340,39 @@
                     inputErrorMessage: '请输入支付密码'
                 }).then(({value}) => {
                     this.payPassword = value
-                    let data = {
+                    let params = {
                         addressId: this.addressId,
                         payType: this.payType,
                         goodsId: this.goodsId,
                         goodsNum: this.goodsNum,
-                        payPassword: this.payPassword
+                        payPassword: this.payPassword,
+                        email: this.form.email,
                     }
-                    return network.postData('shop/sure-order',data).then(response => {
-                        this.$message({
-                            message: response,
-                            type: 'success'
+
+                    // PayStack支付
+                    if (this.payType === 'pay_stack') {
+                        return network.postData('shop/sure-approach-order', params).then((response) => {
+                            this.submitButtonStat = false
+
+                            this.form.orderSn = response.SN
+                            this.form.amount = this.cashSum
+                            this.form.metadata.custom_fields[0].value = response.SN
+                            this.visible = true
+                        }).catch(() => {
+                            this.submitButtonStat = true
                         })
+                    } else {
+                        // 非PayStack支付
+                        return network.postData(serviceApi, params).then((response) => {
+                            this.submitButtonStat = false
 
-                        this.submitButtonStat = false
-                        this.$router.go(-1)
-                        this.$router.push({path: `/shop/order-list`})
-                    }).catch(() => {
-                        this.submitButtonStat = false
-                    }).catch((response) => {
-                        this.submitButtonStat = false
-                    })
+                                // 非PayStack支付
+                                this.$router.go(-1)
+                                this.$router.push({path: `/shop/order-list`})
+                        }).catch(() => {
+                            this.submitButtonStat = true
+                        })
+                    }
                 }).catch(() => {
                     this.submitButtonStat = false
                 })
@@ -321,8 +415,7 @@
                 //console.log('points_plus_sum',points_plus_sum);
                 //console.log('cash_plus_sum',cash_plus_sum);
                 // this.pointsSum=tool.formatPrice(tool.sum(points_plus_sum) + this.pointFreight);
-              console.log(this.freight)
-              this.pointsSum = this.cashSum = tool.formatPrice(tool.sum(cash_plus_sum) + this.freight) ;
+              this.pointsSum = this.cashSum = this.form.amount = tool.formatPrice(tool.sum(cash_plus_sum) + this.freight) ;
             },
             getShowCart(){
                 network.getData('shop/show-cart', { categoryType: this.categoryType })
@@ -356,7 +449,68 @@
             },
             choseAddress(addressId){
               this.getSumMoney()
-                // console.log(addressId);
+            },
+            // 关闭支付回调
+            handleClose() {
+                let _this = this
+                _this.$confirm('确认关闭?').then(() => {
+                    return network.postData('shop/delete-approach-order', {orderSn: this.form.orderSn}).then(() => {
+                        // 关闭支付模态框
+                        _this.visible = false
+                        // 关闭购物车页面,返回到订单列表页
+                        sessionStorage.setItem('order_goods', null)
+                        sessionStorage.setItem('category_type', null)
+                        this.$router.push({path: `/shop/index`})
+                    })
+                }).catch(() => {
+                    // 关闭支付模态框
+                    _this.visible = false
+                    // 关闭购物车页面,返回到订单列表页
+                    sessionStorage.setItem('order_goods', null)
+                    sessionStorage.setItem('category_type', null)
+                    this.$router.push({path: `/shop/index`})
+                })
+            },
+            // 支付成功回调
+            processPayment(response) {
+                // 支付失败
+                if (response.status !== 'success') {
+                    this.$message({
+                        message: 'Success!',
+                        type: 'error'
+                    })
+                    return false
+                }
+
+                this.payStackLoading = true
+                // 支付成功,更新订单
+                return network.postData('shop/verify-order', { sn: this.form.orderSn, remark: response, email: this.form.email }).then(_ => {
+                    this.$message({
+                        message: 'Success!',
+                        type: 'success'
+                    })
+
+                    this.visible = false
+                    this.payStackLoading = false
+                    this.$router.go(-1)
+                    this.$router.push({path: `/shop/order-list`})
+                }).catch((err) => {
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                    this.payStackLoading = false
+                    return false
+                })
+            },
+            // 关闭支付回调
+            processClose() {
+                // 关闭支付模态框
+                this.visible = false
+                // 关闭购物车页面,返回到订单列表页
+                sessionStorage.removeItem('order_goods')
+                sessionStorage.removeItem('category_type')
+                this.$router.push({path: `/shop/index`})
             }
         }
     }
@@ -391,4 +545,8 @@
 .sum_box > div:nth-child(1){
     margin-right: 1rem;
 }
+.payButton {
+    border: none;
+    padding: 0;
+}
 </style>

+ 2 - 2
frontendEle/src/views/shop/reconsume-order.vue

@@ -18,7 +18,7 @@
 
                     <el-table-column label="会员价格" prop="member_price">
                     </el-table-column>
-                    <el-table-column label="会员PV" prop="member_pv">
+                    <el-table-column label="会员BV" prop="member_pv">
                     </el-table-column>
 <!--                    <el-table-column label="库存" prop="STORE_NUMS">-->
 <!--                    </el-table-column>-->
@@ -29,7 +29,7 @@
                     <el-table-column label="合计金额" prop="member_price_plus">
 
                     </el-table-column>
-                    <el-table-column label="合计PV" prop="member_pv_plus"></el-table-column>
+                    <el-table-column label="合计BV" prop="member_pv_plus"></el-table-column>
                 </el-table>
             </div>
             <!--<div class="sum">-->

+ 2 - 2
frontendEle/src/views/shop/reconsume.vue

@@ -24,7 +24,7 @@
 
                 <el-table-column label="商品价格" prop="SELL_PRICE">
                 </el-table-column>
-                <el-table-column label="价格PV" prop="PRICE_PV">
+                <el-table-column label="价格BV" prop="PRICE_PV">
                 </el-table-column>
                 <el-table-column label="库存" prop="STORE_NUMS">
                 </el-table-column>
@@ -216,4 +216,4 @@
 .flex{
     display: flex;
 }
-</style>
+</style>

+ 3 - 3
frontendEle/src/views/user/dec.vue

@@ -50,7 +50,7 @@
                                 <el-table-column label="套餐金额" prop="AMOUNT">
 
                                 </el-table-column>
-                                <el-table-column label="套餐PV" prop="PV">
+                                <el-table-column label="套餐BV" prop="PV">
                                     <template>
 
                                     </template>
@@ -92,7 +92,7 @@
                                 <el-table-column label="卖价" prop="SELL_PRICE">
 
                                 </el-table-column>
-                                <el-table-column label="PV价格" prop="PRICE_PV">
+                                <el-table-column label="BV价格" prop="PRICE_PV">
 
                                 </el-table-column>
                                 <el-table-column label="数量" width="150">
@@ -109,7 +109,7 @@
                                 <el-button @click="getSum()">计算合计</el-button>
                                 <div class='flex data' style="flex:1;justify-content: flex-end;">
                                     <div style="margin-right:2rem">商品价格:¥{{sell_price_sum}}</div>
-                                    <div>商品PV:¥{{price_pv_sum}}</div>
+                                    <div>商品BV:¥{{price_pv_sum}}</div>
                                 </div>
                             </div>
 

+ 6 - 1
frontendEle/src/views/user/index.vue

@@ -22,6 +22,9 @@
             <el-form-item label="手机号">
               <el-input v-model="infoData.MOBILE" :disabled="true"></el-input>
             </el-form-item>
+            <el-form-item label="Email">
+              <el-input v-model="infoData.EMAIL"></el-input>
+            </el-form-item>
             <el-form-item label="银行名称">
               <el-select v-model="infoData.OPEN_BANK" placeholder="请选择银行名称">
                 <el-option v-for="(item,index) in allOpenBank" :key="index" :label="item.BANK_NAME"
@@ -67,6 +70,7 @@ export default {
         OPEN_BANK: '',
         BANK_ADDRESS: '',
         BANK_NO: '',
+        EMAIL: '',
       },
       allOpenBank:null,
       allNation:null,
@@ -95,6 +99,7 @@ export default {
             openBank: this.infoData.OPEN_BANK,
             bankAddress: this.infoData.BANK_ADDRESS,
             bankNo: this.infoData.BANK_NO,
+            email: this.infoData.EMAIL,
         }
         return network.postData(path, postData).then(response => {
 
@@ -117,4 +122,4 @@ export default {
 
 <style scoped>
 
-</style>
+</style>

+ 8 - 0
vendor/matscode/paystack/.gitignore

@@ -0,0 +1,8 @@
+composer.phar
+/vendor/
+
+# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
+# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
+# composer.lock
+
+/.idea

+ 674 - 0
vendor/matscode/paystack/LICENSE

@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    {one line to give the program's name and a brief idea of what it does.}
+    Copyright (C) {year}  {name of author}
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    {project}  Copyright (C) {year}  {fullname}
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ 137 - 0
vendor/matscode/paystack/README.md

@@ -0,0 +1,137 @@
+# matscode/paystack
+###### This package is for communicating with PAYSTACK RESTful API. [Paystack](https://paystack.com/)
+Having other resource point available on PAYSTACK API, Resources like; 
+- Transaction
+- Customers
+- Plans
+- Subscription
+- Transfers
+- Charges
+- and many more
+
+Just to name a few, it is only the Transaction Resource that is made available currently in this package. Development is ongoing while releases are Stable. Incase you find a BUG/Security Issue, Please, do be kind to open an issue or email [matscode(at)Gmail(dot)Com](mailto://matscode@gmail.com).
+<br>
+**PS**: This library also works for you if you use paystack inline. You just have to use the `verify()` method, passing in your transaction `$reference|$token|$id` is compulsory.
+
+## Requirements
+- Curl 
+
+## Install
+
+### Via Composer
+
+``` bash
+$ composer require matscode/paystack
+```
+If you use a Framework, check your documentation for how vendor packages are autoloaded else Add this to the top of your source file;
+
+``` php
+require_once __DIR__ . "/vendor/autoload.php";
+```
+
+## Making Transactions/Recieving Payment
+
+### Starting Up Paystack Transaction
+
+``` php
+use Matscode\Paystack\Transaction;
+use Matscode\Paystack\Utility\Debug; // for Debugging purpose
+use Matscode\Paystack\Utility\Http;
+
+$secretKey = 'sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+// creating the transaction object
+$Transaction = new Transaction( $secretKey );
+```
+
+### Initializing Transaction
+
+Set data/payload/requestBody to post with initialize request. Minimum required data are email and amount.
+
+``` php
+// Set data to post using array
+$data = 
+[
+    'email'  => 'customer@email.com',
+    'amount' => 500000 // amount is treated in kobo using this method
+];
+$response = $Transaction->initialize($data);
+```
+OR 
+``` php
+// Set data to post using this method
+$response =
+        $Transaction
+            ->setCallbackUrl('http://michaelakanji.com') // to override/set callback_url, it can also be set on your dashboard 
+            ->setEmail( 'matscode@gmail.com' )
+            ->setAmount( 75000 ) // amount is treated in Naira while using this method
+            ->initialize();
+```
+If you want to get the 200OK raw Object as it is sent by Paystack, Set the 2nd argument of the `initialize()` to `true`, example below
+``` php
+// Set data to post using this method
+$response =
+        $Transaction 
+            ->setEmail( 'matscode@gmail.com' )
+            ->setAmount( 75000 ) // amount is treated in Naira while using this method
+            ->initialize([], true);
+```
+Now do a redirect to payment page (using authorization_url)
+<br>
+NOTE: Recommended to Debug `$response` or check if authorizationUrl is set, and save your Transaction reference code. useful to verify Transaction status
+
+``` php
+// recommend to save Transaction reference in database and do a redirect
+$reference = $response->reference;
+// redirect
+Http::redirect($response->authorizationUrl); 
+```
+Using a Framework? It is recommended you use the reverse routing/redirection functions provided by your Framework
+
+
+### Verifying Transaction
+This part would live in your callback file i.e `callback.php` or `whatsoever_you_name.php`
+<br>
+It is also imperative that you create Transaction Obj once more.
+<br>
+This method would return the Transaction Obj but `false` if saved `$reference` is not passed in as argument and also cant be guessed. Using `verify()` would require you do a manual check on the response Obj
+``` php
+$response = $Transaction->verify();
+// Debuging the $response
+Debug::print_r( $response);
+```
+OR
+``` php
+// This method does the check for you and return `(bool) true|false` 
+$response = $Transaction->isSuccessful();
+```
+The two methods above try to guess your Transaction `$reference` but it is highly recommended you pass the Transaction `$reference` as an argument on the method as follows
+``` php
+// This method does the check for you and return `(bool) true|false`
+$response = $Transaction->isSuccessful($reference);
+```
+Moreso, you can also compare if amount paid by customer is the amount expected. This method only works after calling `verify()` or `isSuccessful()` in the same script. It is recommended to do this if you use paystack inline to initialize the transaction.
+``` php
+$amountExpected = 5000; // amount must be in kobo
+// returns `(bool) true|false`
+$Transaction->amountEquals($amountExpected);
+```
+Now you can process Customer Valuable.
+<br>
+<br>
+You might wanna save Transaction `$authorizationCode` for the current customer subsequent Transaction but not a nessecity. It would only counts to future updates of this package or if you choose to extend the package.
+``` php
+// returns Auth_xxxxxxx 
+$response = $Transaction->authorizationCode($reference); // can also guess Transaction $reference
+```
+
+## Hire Me
+I am available on contract if you need help integrating paystack into your Business Website or something.
+<br>
+Contact me via my email above - [michaelakanji.com](http://michaelakanji.com)
+
+## Contributions
+If you seem to understand the architecture, you are welcome to fork and pull else you can wait a bit more till when i provide convention documentation.
+
+## Licence
+GNU GPLV3

+ 19 - 0
vendor/matscode/paystack/composer.json

@@ -0,0 +1,19 @@
+{
+    "name": "matscode/paystack",
+    "description": "This package is for communicating with PAYSTACK API",
+    "type": "library",
+    "keywords": ["payment","paystack", "php"],
+    "license": "GNU GPLv3",
+    "minimum-stability": "stable",
+    "autoload": {
+        "psr-4": {"Matscode\\Paystack\\": "src/"}
+    },
+    "authors": [
+        {
+            "name": "Michael Akanji",
+            "email": "matscode@gmail.com",
+            "homepage": "http://michaelakanji.com"
+        }
+    ],
+    "require": {}
+}

+ 152 - 0
vendor/matscode/paystack/src/Base.php

@@ -0,0 +1,152 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-26
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack;
+
+	use Matscode\Paystack\CURL;
+	use Matscode\Paystack\Utility\Text;
+
+	class Base
+	{
+
+		private
+			$_apiBaseUrl = 'https://api.paystack.co/', // with trailing slash
+			$_curl,
+			$_secretKey,
+			$_endPoint,
+
+			/*Getting Error Infomation*/
+			$_errorMessages = [];
+
+		public
+			$resource,
+			$action,
+			$args,
+			$data,
+			// response from the endpoint
+			$response;
+
+		public function __construct( $secretKey )
+		{
+			// save key in memory
+			$this->_secretKey = $secretKey;
+
+			return $this;
+		}
+
+		public function setResource( $resource )
+		{
+			$this->resource = $resource;
+
+			return $this;
+		}
+
+		public function setAction( $action, array $args = [] )
+		{
+			if ( ! is_array( $args ) ) {
+				throw new \Exception( 'Action arguments can only be of datatype Array' );
+			}
+
+			$this->action = $action;
+			$this->args   = $args;
+
+			return $this;
+		}
+
+		/**
+		 * Initiate Request to the paystack RESTful API and return response Obj
+		 *
+		 * @param array  $withData
+		 * @param string $requestMethod
+		 * @param bool   $returnArray set to true to return response as associate array
+		 *
+		 * @todo Utilize the third argument..
+		 *
+		 * @return mixed
+		 * @throws \Exception
+		 */
+		public function sendRequest( array $withData = [], $requestMethod = 'POST', $returnArray = false )
+		{
+			if ( ! is_array( $withData ) ) {
+				throw new \Exception( 'sendRequest arguments can only be of datatype Array' );
+			}
+
+			$this->data = $withData;
+
+			$this->_endPoint = $this->_apiBaseUrl .
+			                   Text::removeSlashes( $this->resource ) . '/' .
+			                   Text::removeSlashes( $this->action );
+			// append parameters to endPoint
+			if ( count( $this->args ) > 0 ) {
+				$this->_endPoint .= '/' . implode( '/', $this->args );
+			}
+
+			// send the request and return result as json object
+			$this->_curl =
+				( new CURL(
+					$this->_endPoint,
+					$requestMethod ) )
+					->setRequestHeader( 'Authorization', 'Bearer ' . $this->_secretKey );
+
+			$this->response =
+				json_decode(
+					$this->_curl
+						->run( $this->data, 'json' ) );
+
+			return $this->response;
+		}
+
+		/**
+		 * @return mixed
+		 */
+		public function getEndPoint()
+		{
+			// this works only after executing sendRequest
+			return $this->_endPoint;
+		}
+
+		/**
+		 * @param mixed $errorMessages
+		 */
+		public function setErrorMessages( $errorMessages )
+		{
+			//if errorMessages is string
+			if ( is_string( $errorMessages ) ) {
+				$this->_errorMessages[] = $errorMessages;
+			}
+			//if errorMessages is array
+			if ( is_array( $errorMessages ) ) {
+				$this->_errorMessages = array_merge( $this->_errorMessages, $errorMessages );
+			}
+		}
+
+		/**
+		 * @param bool   $toString
+		 * @param string $delimiter
+		 *
+		 * @return array|string
+		 */
+		public function getErrorMessages( $toString = false, $delimiter = '<br>' )
+		{
+			$errorMessages = $this->_errorMessages;
+			if ( $toString ) {
+				// return errorMessage as String
+				unset( $errorMessages ); //to avoid datatype conflict
+				$errorMessages = join( $delimiter, $this->_errorMessages );
+			}
+
+			return $errorMessages;
+		}
+
+
+	}

+ 247 - 0
vendor/matscode/paystack/src/CURL.php

@@ -0,0 +1,247 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-25
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack;
+
+	class CURL
+	{
+		private
+			$_url,
+			$_curl,
+			$_requestWithPost = false,
+			$_allowedReqMethodForPost =
+			[
+				'POST',
+				'UPDATE',
+				'PUT',
+				'PATCH',
+			],
+			$_errorCode,
+			$_errorMessage;
+
+		public
+			$requestMethod,
+			$requestHeader = [];
+
+		const
+			USER_AGENT = 'PHP CURL/1.0 (@matscode)';
+
+
+		public function __construct( $url, $requestMethod = null )
+		{
+			if ( ! extension_loaded( 'curl' ) ) {
+				throw new \ErrorException( 'CURL Extension not loaded, Install libcurl php extension' );
+			}
+
+			//initialize CUrl
+			$this->_url = $url;
+			$this->_curlInit( $this->_url );
+
+			//set requestMethod property
+			$this->requestMethod = $requestMethod;
+
+			//set the default request method to 'POST'
+			if ( ! is_null( $this->requestMethod ) ) {
+				$this->setRequestMethod( $this->requestMethod );
+			}
+
+			return $this;
+		}
+
+		private function _curlInit( $url )
+		{
+			$this->_curl = curl_init();
+
+			$this->setOption( CURLOPT_USERAGENT, self::USER_AGENT )
+			     ->setOption( CURLOPT_URL, $url )
+				// return response
+				 ->setOption( CURLOPT_RETURNTRANSFER, true );
+
+			// turn off caching
+			$this->setRequestHeader( 'Cache-Control', 'no-cache' );
+
+			return $this;
+		}
+
+		public function setOption( $option, $value )
+		{
+			// Set curl option
+			curl_setopt( $this->_curl, $option, $value );
+
+			return $this;
+		}
+
+		public function setRequestMethod( $requestMethod )
+		{
+			switch ( $requestMethod ) {
+				case 'GET' :
+					$this->setOption( CURLOPT_HTTPGET, true );
+					break;
+				case 'UPDATE' :
+					$this->setOption( CURLOPT_CUSTOMREQUEST, 'UPDATE' );
+					break;
+				case 'PUT' :
+					$this->setOption( CURLOPT_CUSTOMREQUEST, 'PUT' );
+					break;
+				case 'PATCH' :
+					$this->setOption( CURLOPT_CUSTOMREQUEST, 'PATCH' );
+					break;
+				case 'DELETE' :
+					$this->setOption( CURLOPT_CUSTOMREQUEST, 'DELETE' );
+					break;
+				case 'POST':
+					$this->doPostRequest();
+
+				default:
+					$this->setOption( CURLOPT_POST, true );
+					break;
+			}
+
+			return $this;
+		}
+
+
+		/**
+		 * @param null $qStringArray
+		 *
+		 * @return string
+		 */
+		public function getUrl( $qStringArray = null )
+		{
+			if ( ! is_null( $qStringArray ) &&
+			     ( is_array( $qStringArray ) || is_object( $qStringArray ) )
+			) {
+				$this->_url .= '?' . http_build_query( $qStringArray );
+			}
+
+			return $this->_url;
+		}
+
+		/**
+		 * @param string $url
+		 *
+		 * @return $this
+		 */
+		public function setUrl(
+			$url
+		) {
+			$this->setOption( CURLOPT_URL, $url );
+			$this->_url = $url;
+
+			return $this;
+		}
+
+		public function doPostRequest()
+		{
+			if ( in_array( $this->requestMethod, $this->_allowedReqMethodForPost ) ) {
+				$this->_requestWithPost = true;
+			}
+
+			return $this;
+		}
+
+		public function run( $data, $as = 'urlencoded', $closeCurl = false ) // urlencoded | json | form-data
+		{
+			if ( $this->_requestWithPost ) {
+				//make a post request
+				switch ( $as ) {
+					case 'json':
+						if ( is_array( $data ) ) {
+							$data = json_encode( $data );
+							$this->setRequestHeader( 'Content-Type', 'application/json' );
+						} else {
+							throw new \ErrorException( 'Data argument passed to the run method must be of datatype Array when posting as JSON' );
+						}
+						break;
+					case 'form-data':
+						if ( is_array( $data ) || is_object( $data ) ) {
+							$this->setRequestHeader( 'Content-Type', 'multipart/form-data' );
+						} else {
+							throw new \ErrorException( 'Data argument passed to the run method must be of datatype Array or Object when postiing as FORM-DATA' );
+						}
+						break;
+					case 'urlenconded':
+						// convert data to queryString - Native
+						$data = http_build_query( $data );
+					// continue to default
+					default:
+						$this->setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+						break;
+				}
+
+				$this->setOption( CURLOPT_POSTFIELDS, $data );  //Post Fields
+			} else {
+				//make a built query string and reset CURLOPT_URL
+				$this->setOption( CURLOPT_URL, $this->getUrl( $data ) );
+			}
+
+			// execute curl
+			$response = curl_exec( $this->_curl );
+			// save error details in memory
+			$this->_errorCode    = curl_errno( $this->_curl );
+			$this->_errorMessage = curl_error( $this->_curl );
+
+			if ( $closeCurl ) {
+				// close curl connection by default
+				if ( is_resource( $this->_curl ) ) {
+					curl_close( $this->_curl );
+				}
+			}
+
+			// return response from endpoint
+			return $response;
+		}
+
+		/**
+		 * @param $key
+		 * @param $value
+		 *
+		 * @return $this
+		 */
+		public function setRequestHeader( $key, $value = null )
+		{
+			if ( ! is_array( $key ) ) {
+				// assist with capitalizing http header keys
+				$headers[] = ucwords( $key ) . ': ' . $value;
+			} else {
+				$headers = $key;
+			}
+
+			// merge requestHeader to base header
+			$this->requestHeader = array_merge( $headers, $this->requestHeader );
+
+			$this->setOption( CURLOPT_HTTPHEADER, $this->requestHeader );
+
+			return $this;
+		}
+
+
+		public function getErrorCode()
+		{
+			return $this->_errorCode;
+		}
+
+		public function getErrorMessage()
+		{
+			return $this->_errorMessage;
+		}
+
+		/**
+		 * @return array
+		 */
+		public function getRequestHeader()
+		{
+			return $this->requestHeader;
+		}
+
+	}

+ 287 - 0
vendor/matscode/paystack/src/Transaction.php

@@ -0,0 +1,287 @@
+<?php
+	/**
+	 *
+	 * Class for Transaction Logic
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-25
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack;
+
+
+	use Matscode\Paystack\Utility\Text;
+
+	class Transaction extends Base
+	{
+		public
+			$amount = 0,
+			$email = null,
+			$reference = null,
+			$transactionResponse =
+			[
+				'verify'     => null,
+				'initialize' => null
+			];
+
+		private
+			$_callbackUrl = null;
+
+
+		public function __construct( $secretKey = null )
+		{
+			if ( ! is_null( $secretKey ) ) {
+				parent::__construct( $secretKey );
+			}
+			// set the default resource for current class
+			$this
+				->setResource( 'transaction' );
+
+			return $this;
+		}
+
+		/**
+		 * This method must be called to request for payment. which return an initial transaction obj
+		 *
+		 * @param array $data
+		 * @param bool  $rawResponse
+		 *
+		 * @return mixed|\stdClass
+		 */
+		public function initialize( array $data = [], $rawResponse = false )
+		{
+			// values set via mutator
+			$data['callback_url'] = $this->_callbackUrl;
+
+			// override refernce $data['reference'] value
+			if ( $this->reference ) {
+				$data['reference'] = $this->reference;
+			} elseif ( ! isset( $data['reference'] ) ) {
+				$this->reference = $data['reference'] = Text::uniqueRef();
+			} else {
+				$this->reference = $data['reference'];
+			}
+
+			// override amount $data['amount'] value
+			if ( $this->amount ) {
+				$data['amount'] = $this->amount;
+			} else {
+				// save amount in memory
+				$this->amount = $data['amount'];
+			}
+
+			// override email $data['email'] value
+			if ( ! is_null( $this->email ) ) {
+				$data['email'] = $this->email;
+			} else {
+				// save amount in memory
+				$this->email = $data['email'];
+			}
+
+			$this->transactionResponse['initialize'] =
+				$this
+					->setAction( 'initialize' )
+					->sendRequest( $data );
+
+
+			if ( $rawResponse ) {
+				$response =
+					$this->transactionResponse['initialize'];
+			} else {
+				// Initialize a new Obj to save Striped response
+				$response = new \stdClass();
+				if ( isset( $this->transactionResponse['initialize']->data ) &&
+				     is_object( $this->transactionResponse['initialize']->data )
+				) {
+					$response->authorizationUrl = $this->transactionResponse['initialize']->data->authorization_url;
+					$response->reference        = $this->transactionResponse['initialize']->data->reference;
+				} else {
+					// return the raw response
+					$response =
+						$this->transactionResponse['initialize'];
+				}
+			}
+
+			return $response;
+		}
+
+		/**
+		 * Is used to Check if a transaction is successful and return the transaction object datd
+		 *
+		 * @param null $reference
+		 *
+		 * @todo Use session to keep reference temporary per transaction To enhance Transaction reference guessing.
+		 *
+		 * @return mixed
+		 * @throws \Exception
+		 */
+		public function verify( $reference = null )
+		{
+			// try to guess reference if not set
+			if ( is_null( $reference ) ) {
+				// guess reference
+				if ( isset( $_GET['reference'] ) ) {
+					$reference = $_GET['reference'];
+				} else {
+					// return false
+					return false;
+				}
+			}
+
+			$this->transactionResponse['verify'] =
+				$this
+					->setAction( 'verify', [ $reference ] )
+					->sendRequest( [], 'GET' );
+
+			return $this->transactionResponse['verify'];
+		}
+
+		/**
+		 * Like verify(), but it only checks to see if a transactions is successful returning boolean
+		 *
+		 * @param null $reference
+		 *
+		 * @return bool
+		 */
+		public function isSuccessful( $reference = null )
+		{
+			// get verify response
+			$response = $this->verify( $reference );
+
+			// Initialize as !isSuccessful
+			$isSuccessful = false;
+
+			// check if transaction is successful
+			if ( isset($response->data) && is_object( $response->data ) &&
+			     $response->status == true &&
+			     $response->data->status == 'success'
+			) {
+				$isSuccessful = true;
+			}
+
+			return $isSuccessful;
+		}
+
+		/**
+		 * Compares the amount paid by customer to the amount passed into it
+		 *
+		 * @param $amountExpected
+		 *
+		 * @return bool
+		 */
+		public function amountEquals( $amountExpected )
+		{
+			// $this->verify(); // call verify() or isSuccessful() before calling this method
+			$transactionResponse = $this->transactionResponse['verify'];
+			if ( is_object( $transactionResponse ) ) {
+				return
+					( (int) $transactionResponse->data->amount === $amountExpected );
+			}
+
+			return false;
+		}
+
+		/**
+		 * @param null $reference
+		 *
+		 * @return string|null
+		 */
+		public function getAuthorizationCode( $reference = null )
+		{
+			$authorizationCode = null;
+			// get verify response
+			if ( $this->isSuccessful( $reference ) ) {
+				$response          = $this->verify( $reference );
+				$authorizationCode = $response->data->authorization->authorization_code;
+			}
+
+			return $authorizationCode;
+		}
+
+		/**
+		 * @param $email
+		 *
+		 * @return $this
+		 */
+		public function setEmail( $email )
+		{
+			// setting the email
+			$this->email = $email;
+
+			return $this;
+		}
+
+		public function getEmail( $email )
+		{
+			// setting the email
+			$this->email = $email;
+		}
+
+		/**
+		 * @param int $amount
+		 *
+		 * @todo Allow to set kobo using '.' syntax
+		 * @return $this
+		 */
+		public function setAmount( $amount )
+		{
+			// setting amount in naira //TODO: Allow to set kobo using '.' syntax
+			$this->amount = ( $amount * 100 );
+
+			return $this;
+		}
+
+		/**
+		 * @return int
+		 */
+		public function getAmount()
+		{
+			return $this->amount;
+		}
+
+		/**
+		 * Sets the transaction reference code/id
+		 *
+		 * @param null $reference
+		 */
+		public function setReference( $reference )
+		{
+			$this->reference = $reference;
+		}
+
+		/**
+		 * @param bool $afterInitialize
+		 *
+		 * @return null
+		 *
+		 */
+		public function getReference( $afterInitialize = false )
+		{
+			if ( $afterInitialize ) {
+				$reference = $this->response->data->reference;
+			} else {
+				$reference = $this->reference;
+			}
+
+			return $reference;
+		}
+
+		/**
+		 * To set callback URL, can be used to override callback URL set on paystack dashboard
+		 *
+		 * @param string $callbackUrl
+		 *
+		 * @return $this
+		 */
+		public function setCallbackUrl( $callbackUrl )
+		{
+			$this->_callbackUrl = $callbackUrl;
+
+			return $this;
+		}
+
+	}

+ 44 - 0
vendor/matscode/paystack/src/Utility/Debug.php

@@ -0,0 +1,44 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-27
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack\Utility;
+
+
+	class Debug
+	{
+		private
+		static
+			$openTag = '<pre style="overflow: auto; max-height: 70%; max-width: 95%; position: fixed; z-index: 9999; left: 15px; top: 15px; padding: 15px; background-color: #fcfcfc; border: solid 1px #aaa; line-height: 1.1rem;">',
+			$closeTag = '</pre>';
+
+		public static function printStr( $value )
+		{
+			echo self::$openTag .
+			     $value .
+			     self::$closeTag;
+		}
+
+		public static function print_r( $value )
+		{
+			echo self::$openTag .
+			     print_r( $value, true ) .
+			     self::$closeTag;
+		}
+
+		public static function var_dump( $value )
+		{
+			echo self::$openTag;
+			var_dump( $value );
+			echo self::$closeTag;
+		}
+	}

+ 24 - 0
vendor/matscode/paystack/src/Utility/Http.php

@@ -0,0 +1,24 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-27
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack\Utility;
+
+	class Http
+	{
+		public static function redirect( $location, $replace = true, $httpResponseCode = null )
+		{
+			// do a redirect
+			header( 'Location: ' . $location, $replace, $httpResponseCode );
+		}
+
+	}

+ 55 - 0
vendor/matscode/paystack/src/Utility/Text.php

@@ -0,0 +1,55 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-26
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+
+	namespace Matscode\Paystack\Utility;
+
+
+	class Text
+	{
+		/**
+		 *
+		 * @author Hackan <hackan@gmail.com>
+		 * @link   https://php.net/manual/en/function.uniqid.php#120123
+		 *
+		 * @param int $length
+		 *
+		 * @param int $capsMix
+		 *
+		 * @return bool|string
+		 * @throws \Exception
+		 */
+		public static function uniqueRef( $length = 15, $capsMix = 5 )
+		{
+			// uniqid gives 15 chars, but you could adjust it to your needs.
+			if ( function_exists( "random_bytes" ) ) {
+				$bytes = random_bytes( ceil( $length / 2 ) );
+			} elseif ( function_exists( "openssl_random_pseudo_bytes" ) ) {
+				$bytes = openssl_random_pseudo_bytes( ceil( $length / 2 ) );
+			} else {
+				throw new \Exception( "No cryptographically secure random function available" );
+			}
+
+			if ( $capsMix > 10 ) {
+				throw new \Exception( 'capsMix can not be greater than 10' );
+			}
+			$caps = substr( str_shuffle( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ), 1, $capsMix );
+
+			return str_shuffle( substr( bin2hex( $bytes ), 0, $length ) . $caps );
+		}
+
+
+		public static function removeSlashes( $string )
+		{
+			return trim( $string, '/' );
+		}
+	}

+ 48 - 0
vendor/matscode/paystack/test/callback.php

@@ -0,0 +1,48 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-27
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+	require_once "../vendor/autoload.php";
+
+	use Matscode\Paystack\Transaction;
+	use Matscode\Paystack\Utility\Debug;
+
+	$secretKey = 'sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+	// creating the transaction object
+	$Transaction = new Transaction( $secretKey );
+
+	// transaction can be verified by doing manual check on the response Obj
+	/*
+	$response = $Transaction->verify();
+
+	Debug::print_r( $response);*/
+
+	// OR
+	$result = $Transaction->isSuccessful();
+
+	/*
+	Debug::print_r( $result);
+	*/
+
+	// To check if verified amount is the expected amount before giving value to customer
+
+	$result = $Transaction->amountEquals(5000); // amount in kobo
+
+	Debug::printStr( $result );
+
+
+	// Getting AuthorizationCode
+	/*
+	$authorizationCode = $Transaction->getAuthorizationCode();
+
+	Debug::print_r( $authorizationCode);
+	*/

+ 45 - 0
vendor/matscode/paystack/test/index.php

@@ -0,0 +1,45 @@
+<?php
+	/**
+	 *
+	 * Description
+	 *
+	 * @package        Paystack
+	 * @category       Source
+	 * @author         Michael Akanji <matscode@gmail.com>
+	 * @date           2017-06-26
+	 * @copyright (c)  2016 - 2017, TECRUM (http://www.tecrum.com)
+	 *
+	 */
+	require_once "../vendor/autoload.php";
+
+	use Matscode\Paystack\Transaction;
+	use Matscode\Paystack\Utility\Debug;
+	use Matscode\Paystack\Utility\Http;
+
+	$secretKey = 'sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+	// creating the transaction object
+	$Transaction = new Transaction( $secretKey );
+
+	// Set data to post using this method
+	/*
+	$response = $Transaction->initialize( [
+		'email'  => 'customer@email.com',
+		'amount' => 500000
+	] );
+	*/
+
+	// OR
+
+	$response =
+		$Transaction
+			->setEmail( 'matscode@gmail.com' )
+			->setAmount( 50 )
+			->initialize();
+
+	// print response
+	 Debug::print_r( $response );
+
+	// save reference somewhere and do a redirect
+	 Http::redirect($response->authorizationUrl);
+

+ 6 - 0
vendor/nategood/httpful/.gitignore

@@ -0,0 +1,6 @@
+.DS_Store
+composer.lock
+vendor
+downloads
+.idea/*
+tests/.phpunit.result.cache

+ 12 - 0
vendor/nategood/httpful/.travis.yml

@@ -0,0 +1,12 @@
+language: php
+
+php:
+  - 7.2
+  - 7.3
+  - 7.4
+
+matrix:
+  fast_finish: true
+
+script:
+  - phpunit -c ./tests/phpunit.xml

Неке датотеке нису приказане због велике количине промена