Compare commits

...

325 Commits

Author SHA1 Message Date
  nizongfeng ee387485de 登录限制密码错误次数 1 year ago
  nizongfeng be99e738e3 登录限制密码错误次数 1 year ago
  nizongfeng a812cd8d0a 登录限制密码错误次数 1 year ago
  nizongfeng 89a14881cc 切换收款方式 1 year ago
  nizongfeng 151b92eb6a 切换收款方式 1 year ago
  nizongfeng ec3d3375b6 切换收款方式 1 year ago
  nizongfeng 7b0016d71a 1 3 years ago
  nizongfeng 8829706f9a 1 3 years ago
  nizongfeng 9768660ef0 1 3 years ago
  nizongfeng 1f7b0ae88d 1 3 years ago
  nizongfeng 1cd42f09b3 1 3 years ago
  nizongfeng 0547ed8905 1 3 years ago
  nizongfeng 59b10d7b9c 1 3 years ago
  nizongfeng 7e6941409f 1 3 years ago
  nizongfeng 02a046e063 1 3 years ago
  nizongfeng 67221f6e84 1 3 years ago
  nizongfeng 44ff3785e2 1 3 years ago
  nizongfeng 372b1ff009 1 3 years ago
  nizongfeng 1dd6f79138 1 3 years ago
  nizongfeng 80fa2af841 1 3 years ago
  nizongfeng 09210d1562 1 3 years ago
  nizongfeng b5155ad9ba 1 3 years ago
  nizongfeng 2cb5d9fe31 1 3 years ago
  nizongfeng 3aa7711150 1 3 years ago
  nizongfeng ae8f789fd4 1 3 years ago
  nizongfeng 71ce3b5e2c 1 3 years ago
  xubinxcode a9205c04f5 Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  xubinxcode 4d0712d0b5 一家 3 years ago
  nizongfeng 6c075d1a1d Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  nizongfeng 65c0b5480a 1 3 years ago
  xubinxcode 6ec1fb7880 一家 3 years ago
  xubinxcode 714db61c89 一家 3 years ago
  nizongfeng b77804968c 1 3 years ago
  nizongfeng 0994698ae4 1 3 years ago
  nizongfeng 8de0f26102 1 3 years ago
  nizongfeng b0d36ea285 1 3 years ago
  nizongfeng a02e537dbd 1 3 years ago
  nizongfeng 472ed8f762 切换支付方式 3 years ago
  xcodebin 7aaf7c3e79 登录居中 3 years ago
  xubinxcode 5fea129b46 一家 3 years ago
  xubinxcode 46d20a2bbe 一家 3 years ago
  xubinxcode 282438ddc2 Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  xubinxcode 57d4dbf76d 一家 3 years ago
  v-Brocloni 145e1e6e8f 订单状态导出 3 years ago
  v-Brocloni 1390cc8f4d 优化 3 years ago
  v-Brocloni 6d19f390e1 导出优化 3 years ago
  xubinxcode 269a1c09f4 一家 3 years ago
  v-Brocloni 9cf0f6b900 刷新 3 years ago
  v-Brocloni 692bd9d23d 1 3 years ago
  v-Brocloni c47aaef0d8 刷新 3 years ago
  v-Brocloni 144449a5f2 1 3 years ago
  娄梦宁 5316f4dc2d 弹窗输入 3 years ago
  v-Brocloni b8e936dc09 金额格式优化 3 years ago
  v-Brocloni ade5e2ea4e 1 3 years ago
  v-Brocloni 4cfd9a659f 1 3 years ago
  v-Brocloni df3ef1187d 1 3 years ago
  v-Brocloni f5feea9751 1 3 years ago
  v-Brocloni 837ddafef1 1 3 years ago
  v-Brocloni bdee9f2f10 1 3 years ago
  v-Brocloni f42935cd70 1 3 years ago
  v-Brocloni fd39c2d8e1 1 3 years ago
  v-Brocloni ba53124736 1 3 years ago
  v-Brocloni c77004f5b9 1 3 years ago
  v-Brocloni b09fb50bbb 1 3 years ago
  v-Brocloni 60acdb893b 修改 3 years ago
  v-Brocloni 004408c1f7 退款输入框 3 years ago
  v-Brocloni 58c57fe5be 退款金额不能高于订单总金额 3 years ago
  v-Brocloni 798d6ec511 展示退款金额 3 years ago
  v-Brocloni a17c29c681 导出是否提货 3 years ago
  v-Brocloni 3d28223d25 导出优化 3 years ago
  xubinxcode 0e8bd8d103 Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  xubinxcode 11be5a8abe 修复组件 3 years ago
  v-Brocloni da798fd3d7 合并 3 years ago
  v-Brocloni 2eac050e82 apache优化 3 years ago
  xubinxcode cba33a4e5c 宜家调整 3 years ago
  xubinxcode 556647683c 宜家调整 3 years ago
  xubinxcode d612694dd6 国际化 3 years ago
  xubinxcode 6382772f9a 国际化 3 years ago
  v-Brocloni ccbafb471c 调试 3 years ago
  v-Brocloni e8436d5022 调试 3 years ago
  v-Brocloni 7c0fbac14b 调试 3 years ago
  v-Brocloni 36902decd2 调试 3 years ago
  v-Brocloni 4d57c75d45 调试 3 years ago
  v-Brocloni 32de63a0e5 调试 3 years ago
  v-Brocloni 668374ba34 调试 3 years ago
  v-Brocloni da80722541 调试 3 years ago
  v-Brocloni 7f5fe9a2fa 调试 3 years ago
  v-Brocloni 3cc3d842d0 调试 3 years ago
  v-Brocloni 3228b550c9 修改代码异常 3 years ago
  娄梦宁 0544968b7f checkredis 3 years ago
  娄梦宁 17b3589659 checkredis 3 years ago
  娄梦宁 3f0ccd040e checkredis 3 years ago
  娄梦宁 a0536d3dcf checkredis 3 years ago
  娄梦宁 3aece73756 checkredis 3 years ago
  娄梦宁 35e88a8228 checkredis 3 years ago
  娄梦宁 400ed665c9 checkredis 3 years ago
  xubinxcode 408c9dadfc 首页轮播图自动切换 3 years ago
  v-Brocloni 828bac20c0 修改收款 3 years ago
  v-Brocloni 7c21d127a0 配置修改 3 years ago
  v-Brocloni 59fb65fcbf 配置修改 3 years ago
  v-Brocloni 2a2c4c3855 配置修改 3 years ago
  v-Brocloni 40a01c9688 配置修改 3 years ago
  v-Brocloni 209ecc7676 Revert "配置修改" 3 years ago
  v-Brocloni 8c002083e1 Revert "配置修改" 3 years ago
  v-Brocloni fb92292b8b Revert "配置修改" 3 years ago
  v-Brocloni d9902135ce 配置修改 3 years ago
  v-Brocloni b0fa408225 配置修改 3 years ago
  v-Brocloni 99c2238a2f 配置修改 3 years ago
  v-Brocloni fdb047b969 Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  v-Brocloni 1e1a4723d9 异常处理 3 years ago
  v-Brocloni bbfb3d06b3 异常处理 3 years ago
  xubin d60a253ebc Merge remote-tracking branch 'origin/yijia' into yijia 3 years ago
  xubin 5be743d76c 需求变更 3 years ago
  v-Brocloni 3e9361b3e4 支付宝支付 3 years ago
  v-Brocloni bf09b23b64 支付宝支付 3 years ago
  v-Brocloni 5cabb4a05a 支付宝支付 3 years ago
  v-Brocloni c76391308e 支付宝支付 3 years ago
  v-Brocloni 51de1f10e4 支付宝支付 3 years ago
  v-Brocloni 25c2909dfe 支付宝支付 3 years ago
  v-Brocloni c364f490b6 支付宝支付 3 years ago
  v-Brocloni 079a46669d 支付宝支付 3 years ago
  v-Brocloni 8bf78e94b0 支付宝支付 3 years ago
  v-Brocloni 16dd6f75ad 支付宝支付 3 years ago
  v-Brocloni bdc61b8c9a 支付宝支付 3 years ago
  v-Brocloni 8af348a7fb 支付宝支付 3 years ago
  v-Brocloni 72a070b785 登录过期时间 4小时 3 years ago
  v-Brocloni acc62b0d25 登录过期时间恢复 3 years ago
  xubin 2338564184 切换域名 3 years ago
  娄梦宁 50adbb2afa checkredis 4 years ago
  娄梦宁 c71ef11a8f checkredis 4 years ago
  娄梦宁 efa5a49cd7 checkredis 4 years ago
  娄梦宁 82b8474176 checkredis 4 years ago
  娄梦宁 6505671cf8 Merge remote-tracking branch 'origin/yijia' into yijia 5 years ago
  娄梦宁 1495cb7c8c checkredis 5 years ago
  娄梦宁 79e09d02b8 1 6 years ago
  娄梦宁 5bbf06488c checkredis 7 years ago
  娄梦宁 0dec9668a1 checkredis 7 years ago
  娄梦宁 a0d5e4eb04 checkredis 4 years ago
  xubin 2be259a561 去掉首页弹窗 4 years ago
  xubin 617697841a mac 编译 4 years ago
  xubin 002fbd4c42 .. 4 years ago
  xubinxcode ee1c6e4237 去掉原价格 4 years ago
  xubinxcode c165d7ce90 调整 4 years ago
  xubinxcode cb9689b9b7 首页调整 4 years ago
  xubinxcode c35ae9d888 页面调整 4 years ago
  xubinxcode d92a3366a1 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode c450bf8a74 背景渐变 4 years ago
  v-Brocloni 13bdb0966a 支付不需要登錄 4 years ago
  xubinxcode a8ddb13b30 首页文字 4 years ago
  xubinxcode 2f05accfc4 首页列表 4 years ago
  xubinxcode 0856601b36 首页所有商品 4 years ago
  xubinxcode 8bb072b446 PC支付 4 years ago
  xubinxcode 5978898682 调整支付 4 years ago
  xubinxcode b86a330407 弹窗支付 4 years ago
  xubinxcode 3e136165c0 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode 22863ea543 微调 4 years ago
  娄梦宁 e432d636bf checkredis 4 years ago
  xubinxcode a7f8ea823e 调整 4 years ago
  xubinxcode 4fcc065c3d Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode 7278fe70b4 调整 4 years ago
  v-Brocloni 59920633fd 二维码带图片 4 years ago
  v-Brocloni e451dd8324 优化 4 years ago
  v-Brocloni 720ea3ea7a 生产二维码 4 years ago
  娄梦宁 8f13fa9790 checkredis 4 years ago
  娄梦宁 5cdd1b19d7 checkredis 4 years ago
  娄梦宁 62ff97930c checkredis 4 years ago
  xubinxcode ff7985a800 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode e058789944 调整 4 years ago
  xubinxcode 7121184f10 调整 4 years ago
  loumengning d1caf3192c 11 4 years ago
  xubinxcode bb494e1a9e pc 4 years ago
  娄梦宁 90419a7519 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 625d847807 checkredis 4 years ago
  loumengning 1d78acd31b 11 4 years ago
  loumengning 4bca54591c 11 4 years ago
  loumengning 49f6d8cba4 11 4 years ago
  loumengning a58f341867 11 4 years ago
  loumengning 0e5b3e3aba 11 4 years ago
  loumengning 4f88c2884f 11 4 years ago
  loumengning 2a53ba49df 11 4 years ago
  loumengning a8f6f8c026 11 4 years ago
  loumengning b3f445ae43 11 4 years ago
  loumengning 39566930c8 11 4 years ago
  xubin 14b899d9d5 时间戳 4 years ago
  xubin 21101f7b3f Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubin 982edbc36d 统计 4 years ago
  娄梦宁 bd52586688 checkredis 4 years ago
  娄梦宁 b7e5acb962 checkredis 4 years ago
  娄梦宁 0aaf9ace2b checkredis 4 years ago
  娄梦宁 72ccd5c5bf checkredis 4 years ago
  娄梦宁 3ddfae41e9 checkredis 4 years ago
  娄梦宁 e29a71a9da checkredis 4 years ago
  娄梦宁 40beff7bb5 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 99c727302f checkredis 4 years ago
  xubin 26f2a32173 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubin 9def540429 去掉提示语 4 years ago
  娄梦宁 48cf7c2c3b Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  xubin edd31d9882 首页加载数据时机 4 years ago
  娄梦宁 c0edacae2b Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 d2e0a6248e checkredis 4 years ago
  xubin 7229faed07 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubin dbe3c0057b 去掉总库存 4 years ago
  娄梦宁 8b54b30bd2 checkredis 4 years ago
  娄梦宁 11c1df60ea Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 efc250cf7a checkredis 4 years ago
  xubin 86890ec6a7 按钮 4 years ago
  xubin 2957b4536b Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubin 064aa97ebe buy now 4 years ago
  娄梦宁 6d795f01ee Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  xubin 76b7c8eddf 三分 4 years ago
  娄梦宁 f9aaddc596 checkredis 4 years ago
  xubin cf83bc3bfc 秒杀 4 years ago
  xubin d86ba5a1de 轮播图 4 years ago
  xubin 1944348c08 lunbo 4 years ago
  xubin 774dd3f1d5 輪播 4 years ago
  娄梦宁 5d229b3b2a checkredis 4 years ago
  娄梦宁 aa3359a0f0 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 ee1984201b checkredis 4 years ago
  xubin 9eef5c764a 瀑布流 4 years ago
  xubinxcode 635e29a46c 调整 4 years ago
  loumengning 0da0dcb74f Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  loumengning 3df049e6dd 11 4 years ago
  xubinxcode a0c70f59da 打包 4 years ago
  v-Brocloni 5020d32c4d Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  v-Brocloni 83afb65b86 修改错误 4 years ago
  xubinxcode 0c189cd124 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode d44ea3e2a2 重新打包 4 years ago
  v-Brocloni 3e86d176f4 金额错误 4 years ago
  v-Brocloni 2709d9bf6c 调试 4 years ago
  v-Brocloni 7aa353e2a4 调试 4 years ago
  v-Brocloni 45460dda05 返回值处理 4 years ago
  v-Brocloni f8f3a08229 index.php还原 4 years ago
  v-Brocloni 5a4148b1b0 调试 4 years ago
  v-Brocloni b134ea2d3a 调试 4 years ago
  xubinxcode c00c971d2a 打包 4 years ago
  v-Brocloni 37715a9ba5 复原 4 years ago
  v-Brocloni fa0e617dd2 前端打包 4 years ago
  v-Brocloni e2fc64e1ed 测试 4 years ago
  v-Brocloni d7de6688a5 支付 4 years ago
  v-Brocloni dca8d7435f 调试 4 years ago
  v-Brocloni f07e185a14 还原 4 years ago
  v-Brocloni 5d212714e3 调试 4 years ago
  loumengning 18997a7421 11 4 years ago
  xubinxcode 7977a7b0f4 不让购买 4 years ago
  xubinxcode 92aae111f1 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode 48cc4633da 调整 4 years ago
  娄梦宁 c343eff0b3 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  xubinxcode a817aa7874 英文化 4 years ago
  娄梦宁 60fa743d21 checkredis 4 years ago
  loumengning 3fd1e91533 11 4 years ago
  loumengning 50c9d68e4c 11 4 years ago
  娄梦宁 74d918a9dd Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 ffbb8e0c18 checkredis 4 years ago
  xubinxcode c425abfb44 英文改动 4 years ago
  xubinxcode 24f6b9fc01 去掉待发货 4 years ago
  v-Brocloni 7193ebabef Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  v-Brocloni 502f8597b1 支付宝退款 4 years ago
  loumengning 67fd1b534a 11 4 years ago
  loumengning 82a1f803b0 11 4 years ago
  loumengning acca283b42 11 4 years ago
  loumengning 20fff3de49 11 4 years ago
  loumengning 0b2672a55f Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  loumengning 9e8362fec0 11 4 years ago
  娄梦宁 f6fd28e06e checkredis 4 years ago
  娄梦宁 65c0b26046 checkredis 4 years ago
  loumengning 1fa523ec8d 11 4 years ago
  xubinxcode 909ba4edfa 按钮 4 years ago
  xubinxcode ed111a0eb4 调整 4 years ago
  xubinxcode 368036b9d4 打包文件 4 years ago
  xubinxcode 5a8347950c 打包 4 years ago
  xubinxcode 9cd0be4c9e 英文化 4 years ago
  xubinxcode c9f5b16f5b 英文化 4 years ago
  xubinxcode 2c7887ac6d 功能按钮英文化 4 years ago
  xubinxcode f1313794ca 密码不可见 4 years ago
  loumengning 850057a8fd 11 4 years ago
  loumengning 2d0697686e 11 4 years ago
  xubinxcode b4a24accdf 修改密码 4 years ago
  娄梦宁 337009ee40 checkredis 4 years ago
  娄梦宁 0120438a55 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 6e5379e62e checkredis 4 years ago
  v-Brocloni 8a9af3e7fe 回答地址统一 4 years ago
  娄梦宁 094cc2238b checkredis 4 years ago
  xubinxcode bd521a9cbe 登录 4 years ago
  xubinxcode 14200bd57f 首页登陆问题 4 years ago
  xubinxcode 316ff7240a 调整 4 years ago
  xubinxcode 110525dbe8 购物车与订单状态改动 4 years ago
  娄梦宁 4173292a84 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 ad29b93bf0 checkredis 4 years ago
  v-Brocloni 8cdf10f2d9 放开订单好 4 years ago
  v-Brocloni 7f2d8038d5 微信支付 4 years ago
  v-Brocloni f322ca508d 修改配置 4 years ago
  xubin 0089b777fd 调整 4 years ago
  v-Brocloni 63fbefc356 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  v-Brocloni 7290d4df11 支付流程 4 years ago
  娄梦宁 8e903f918e Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 5226a88fe7 checkredis 4 years ago
  v-Brocloni 267a502efa 接口调试 4 years ago
  v-Brocloni 8c5b3d6cf4 调试 4 years ago
  v-Brocloni 864221c8a6 添加日志 4 years ago
  v-Brocloni ac2a547d94 添加插件 4 years ago
  娄梦宁 578c666b92 checkredis 4 years ago
  娄梦宁 a8e9b3dd61 Merge remote-tracking branch 'origin/yijia' into yijia 4 years ago
  娄梦宁 94b448bab2 checkredis 4 years ago
  v-Brocloni 7be6aae337 订单真实数据调用 4 years ago
  v-Brocloni ec6480757a 支付变更 4 years ago
  v-Brocloni 78d1abc15b 添加插件 4 years ago
  xubinxcode 185cb3b994 运费去掉,首页登陆后刷新 4 years ago
  xubinxcode 752a4f41e4 Merge branch 'yijia' of http://47.101.187.29:8081/loumengning/shop into yijia 4 years ago
  xubinxcode b5a7d5e2c0 删除运费与物流信息,首页登陆完成后刷新页面 4 years ago
  娄梦宁 62be2fb0a7 checkredis 4 years ago
  娄梦宁 fcffff2f94 checkredis 4 years ago
  娄梦宁 574457a12f checkredis 4 years ago
  娄梦宁 eef1392937 checkredis 4 years ago
  娄梦宁 084f8a8695 checkredis 4 years ago
  娄梦宁 083dd8427f checkredis 4 years ago
  娄梦宁 15929c1810 移除运费 4 years ago
  娄梦宁 5024802fdb 移除运费 4 years ago
  娄梦宁 2fe989bbb2 移除运费 4 years ago
  dengxupeng 14b104a55c fix: 四大tab也进入进行登录验证,修正创建订单报错问题 4 years ago
  dengxupeng f674d55122 删除创建订单页面配送地址配送费 4 years ago
  娄梦宁 fc8124b0c0 移除运费 4 years ago
  娄梦宁 a7cf5b331f 移除运费 4 years ago
  娄梦宁 ad05fd42b4 宜家 4 years ago
  娄梦宁 0fbee10df3 宜家 4 years ago
  娄梦宁 f9185ed62a 宜家 4 years ago
100 changed files with 9057 additions and 246 deletions
Split View
  1. +2
    -0
      a.php
  2. +35
    -0
      addons/config/AliPayConfig.php
  3. +65
    -0
      addons/epay/Epay.php
  4. +91
    -0
      addons/epay/assets/css/common.css
  5. +20
    -0
      addons/epay/assets/css/epay.css
  6. +100
    -0
      addons/epay/assets/css/wechat.css
  7. BIN
      addons/epay/assets/images/alipay.png
  8. BIN
      addons/epay/assets/images/expired.png
  9. BIN
      addons/epay/assets/images/logo-alipay.png
  10. BIN
      addons/epay/assets/images/logo-wechat.png
  11. BIN
      addons/epay/assets/images/logo.png
  12. BIN
      addons/epay/assets/images/paid.png
  13. BIN
      addons/epay/assets/images/scan.png
  14. BIN
      addons/epay/assets/images/tips.png
  15. BIN
      addons/epay/assets/images/wechat.png
  16. +52
    -0
      addons/epay/assets/js/common.js
  17. +113
    -0
      addons/epay/assets/less/common.less
  18. +28
    -0
      addons/epay/assets/less/epay.less
  19. +26
    -0
      addons/epay/certs/apiclient_cert.pem
  20. +28
    -0
      addons/epay/certs/apiclient_key.pem
  21. +70
    -0
      addons/epay/config.php
  22. +229
    -0
      addons/epay/controller/Api.php
  23. +112
    -0
      addons/epay/controller/Index.php
  24. +8
    -0
      addons/epay/info.ini
  25. +17
    -0
      addons/epay/library/OrderException.php
  26. +306
    -0
      addons/epay/library/Service.php
  27. +107
    -0
      addons/epay/library/Wechat.php
  28. +63
    -0
      addons/epay/library/Yansongda/Pay/Contracts/GatewayInterface.php
  29. +7
    -0
      addons/epay/library/Yansongda/Pay/Exceptions/Exception.php
  30. +28
    -0
      addons/epay/library/Yansongda/Pay/Exceptions/GatewayException.php
  31. +7
    -0
      addons/epay/library/Yansongda/Pay/Exceptions/InvalidArgumentException.php
  32. +292
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/Alipay.php
  33. +46
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/AppGateway.php
  34. +47
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/PosGateway.php
  35. +44
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/ScanGateway.php
  36. +44
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/TransferGateway.php
  37. +48
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/WapGateway.php
  38. +46
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Alipay/WebGateway.php
  39. +50
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/AppGateway.php
  40. +82
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/GroupredpackGateway.php
  41. +49
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/MiniappGateway.php
  42. +47
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/MpGateway.php
  43. +46
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/PosGateway.php
  44. +86
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/RedpackGateway.php
  45. +38
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/ScanGateway.php
  46. +78
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/TransferGateway.php
  47. +41
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/WapGateway.php
  48. +69
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/WebGateway.php
  49. +354
    -0
      addons/epay/library/Yansongda/Pay/Gateways/Wechat/Wechat.php
  50. +134
    -0
      addons/epay/library/Yansongda/Pay/Pay.php
  51. +147
    -0
      addons/epay/library/Yansongda/Pay/Support/Config.php
  52. +119
    -0
      addons/epay/library/Yansongda/Pay/Traits/HasHttpRequest.php
  53. +86
    -0
      addons/epay/view/api/wechat.html
  54. +212
    -0
      addons/epay/view/index/index.html
  55. +115
    -0
      addons/epay/view/layout/default.html
  56. +308
    -0
      addons/nzf/AliPay.php
  57. +466
    -0
      addons/nzf/CurlInterface.php
  58. +98
    -0
      addons/nzf/PayService.php
  59. +343
    -0
      addons/nzf/Util.php
  60. +337
    -0
      addons/nzf/WeChatPay.php
  61. +92
    -0
      addons/unishop/application/admin/controller/unishop/Order.php
  62. +1
    -1
      addons/unishop/application/admin/controller/unishop/Product.php
  63. +3
    -1
      addons/unishop/application/admin/view/unishop/order/index.html
  64. +39
    -14
      addons/unishop/behavior/Order.php
  65. +13
    -13
      addons/unishop/behavior/OrderFlash.php
  66. +1
    -1
      addons/unishop/controller/Address.php
  67. +2
    -2
      addons/unishop/controller/Ads.php
  68. +13
    -13
      addons/unishop/controller/Base.php
  69. +6
    -1
      addons/unishop/controller/Category.php
  70. +141
    -21
      addons/unishop/controller/Order.php
  71. +93
    -160
      addons/unishop/controller/Pay.php
  72. +2
    -2
      addons/unishop/controller/Product.php
  73. +46
    -10
      addons/unishop/controller/User.php
  74. +7
    -7
      addons/unishop/extend/Ali.php
  75. +38
    -0
      addons/unishop/library/phpqrcode/CHANGELOG
  76. +67
    -0
      addons/unishop/library/phpqrcode/INSTALL
  77. +165
    -0
      addons/unishop/library/phpqrcode/LICENSE
  78. +15
    -0
      addons/unishop/library/phpqrcode/QrCode.php
  79. +45
    -0
      addons/unishop/library/phpqrcode/README
  80. +2
    -0
      addons/unishop/library/phpqrcode/VERSION
  81. +2875
    -0
      addons/unishop/library/phpqrcode/bindings/tcpdf/qrcode.php
  82. +2
    -0
      addons/unishop/library/phpqrcode/cache/frame_1.dat
  83. BIN
      addons/unishop/library/phpqrcode/cache/frame_1.png
  84. BIN
      addons/unishop/library/phpqrcode/cache/frame_10.dat
  85. BIN
      addons/unishop/library/phpqrcode/cache/frame_10.png
  86. BIN
      addons/unishop/library/phpqrcode/cache/frame_11.dat
  87. BIN
      addons/unishop/library/phpqrcode/cache/frame_11.png
  88. BIN
      addons/unishop/library/phpqrcode/cache/frame_12.dat
  89. BIN
      addons/unishop/library/phpqrcode/cache/frame_12.png
  90. BIN
      addons/unishop/library/phpqrcode/cache/frame_13.dat
  91. BIN
      addons/unishop/library/phpqrcode/cache/frame_13.png
  92. BIN
      addons/unishop/library/phpqrcode/cache/frame_14.dat
  93. BIN
      addons/unishop/library/phpqrcode/cache/frame_14.png
  94. BIN
      addons/unishop/library/phpqrcode/cache/frame_15.dat
  95. BIN
      addons/unishop/library/phpqrcode/cache/frame_15.png
  96. +1
    -0
      addons/unishop/library/phpqrcode/cache/frame_16.dat
  97. BIN
      addons/unishop/library/phpqrcode/cache/frame_16.png
  98. BIN
      addons/unishop/library/phpqrcode/cache/frame_17.dat
  99. BIN
      addons/unishop/library/phpqrcode/cache/frame_17.png
  100. +2
    -0
      addons/unishop/library/phpqrcode/cache/frame_18.dat

+ 2
- 0
a.php View File

@@ -0,0 +1,2 @@
<?php
phpinfo();

+ 35
- 0
addons/config/AliPayConfig.php View File

@@ -0,0 +1,35 @@
<?php


namespace addons\config;


class AliPayConfig
{
public static $env= "lan";//wendy lan

private static $wendy=[
"ali_app_id"=>"2021001199650201",
"ali_notify_url"=>"http://internalsales.iicn.co/addons/unishop/pay/notify/type/alipay",
"ali_return_url"=>"http://internalsales.iicn.co/h5/#/pages/order/order?state=0",
"ali_public_key"=>"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8N4o64A4Wt434t3n2ohBgkulg3DDshTjeiAjSe40R4hyhYtatw6zvVbLHkFedlv9H2xcO/gp4+2AdNlP2w8hskc5IowEfnslLyZlL9TK/Ye6kG7MExbywdmC/E8FI0QIsuD4LECrzPFCDOwf+zoi/7b6B7NA6GkEP05N2N02e2PjucD4QyN1I797DEA+FocpKm2/10WnCSBDfaEA56k/yLCwNyV+DOwxX1DAhm10Kdzew/0souOcmo0nsztg+ZWqDk64/CHco/n/fqFENNdLfm550OU5MtjWf+wsytSxRhcQ1MprSlmRAbgoaQ4fP6RakKMYgFc/7lL3sT3m6nIBQIDAQAB",
"ali_private_key"=>"MIIEowIBAAKCAQEA0ttBosJiuTgQkLBu03CgkJ0FHXiiN6iYnWof2U8Qzcg/oIJDdfeb7KnpjHRblqoD108GrsfU8pfHwuqt65OeH0e+gQPQj2GRaQ2XrWqp3kitbFRfWHAcAoE81kHkLjKtUKDgx1afOmiybRJMryNBy9uPn5bUZLSIlMDr/GD6Hq+Z6p0ZAswCBFpZs2GTlPaDXHM/oOPDZEzNkdI05CDTSDCyjg2jCfQHZb6ItM6Xc3fPjbMoSd4quw/z3uqbfnIx62Bc0j7DbLJeup/ItCjuHaZ5gd0ITQPPEQQSxrYCaRKctC88JyW/wmPT/onSuVX/WWUdPOMIS1sZdyecjKncPwIDAQABAoIBADdRwtSavx/s75umTk023UlTiMYEojqMBw41i4mNztDOWrMXue83OTdMFLP+yxCqJjvUxeIRF3NWEti2jU6i+fcm8XoTsCIN7QJsyIB83XguBSHIuQMQ1qhpk7Z6rwzXytS+gHqL5VaDpVwsUuYYD+kV/4ZVIgARxUuRmdgq8TQfUA6X8kjrHMxBUA+LWQjOPWyNxH01AJ3zqGvsy+xhl3kVhZYcJ162jXRiwXj4+kpULZUj4AnpiGV4z71ucG9pneM67TErP1p9hQQoB+BdWGk4s3oWKSAeWDbS/4yySLq5rMHxy1RQ5aRNaxtdD+VAUaQKHPKR947lqPosRP+0t3ECgYEA6efg8JpZ82/IjJVC3HrgUeDE5V76hCojNc9zCXDJHfR7Umd5qZFkXEcqRR52U+OelygifeLW3yYo0HWtgn5hz2GbKAtWsXpSLRBmcsd0fUsgCeP9WK6CnILUb2lswC7au5s4nYoo8XwR3D86ahXzkDcti2lss4bP7sXp53WnN70CgYEA5sYEmB8cmUt+O4Vl9whZk7z3Uo9uLYZjvkxI1q9xBYnUbIOT+3QBoC1Q6J68RNKpudnip/5dpXdJJh4EZxR2Bu3PzP/0TQ9G64NgynB7u2/qCE5A1UER2mzn/LPSsSKCVOEfKHQChhNLg8fiOXcpRvVBlw6HH7h3KG6FKB87tasCgYEAteL8Rdyg6e4Y00kWLwDWApV4RqyuvatOqf9hAwxTOBnu88tHDhbjJeao9gqUFPPBVOV+vMlyMSApSMDZZcoFIRBTaLY4edYWpLhGEicLbIrIpShGz3kUU8RgkSo3yNImgRBY3Bidcfr6oHwCXpAnUBO4NNqMDqZcdt4r3zLcDzkCgYAuheUPNdZyIQIFxdLUhl5opkPF5Rx1GQ6qon5cqWnDkBG+/peqraxWOkyBWN7jkQSebwp+i40denrIsGx6y2kv5GlsDn2Vu2q0t/ufVCXdl6Y6nmv7ke6jdikejLIA+9AChI/fe+O2W9Vxb65vn1I29+KNLWSYRHvhLsaxW/qRmQKBgHsLvFDC95PWDcWXxR10JjPb/QHhrZBEjXPYEsqPryrvFtuohG/D2vKPltKrEh5xGOW5Xx02vPkLL3mf+92DMKVZ6PXBQo/sX3IENT0kHL0XkqEuM6aEcitLi6fLRJyrVjqfdcyI+GY7Yy8AzJZkFJvV9H/cI0kotXxQNiA6lJnK",
"ali_sandbox"=>0
];
private static $Lan=[
"ali_app_id"=>"2021002128652345",
"ali_notify_url"=>"http://internalsales.iicn.co/addons/unishop/pay/notify/type/alipay",
"ali_return_url"=>"http://internalsales.iicn.co/h5/#/pages/order/order?state=0",
"ali_public_key"=>"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvIjTYv298yvVONMTr/u2szr1iblKq/9dnd8psvKiJEs6KChLA2kpbUmzwPTN+uLqrn5V5YOi7nr/kOE+59fXZ/YKFyH3nPdqoHzvuBCwsaB73ArXR7wByclLgY/C2qOCHWGUi96WTkgUHbx36/ba9hd7v1uZ+SZtUj77E4cX8MgQFJ9v+UAzuwiF+9m7WOQE25JHgQMEIkFA8u9ZuPYnZ8TvwRYKCiDioZi47as2a1n6xBFkSKYYanwYPPw8TCbXcIANjzOZ0cGLdBiL3aG6uPCczNnPDKyO7mkI4JRqYT2XBNLPEVm11eSjeCeoqWsaOCeUVJR3r9Cb76yyqpIXCwIDAQAB",
"ali_private_key"=>"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVYKvDfnORWwGReyj/+tbG6HTz0qnEtZQ1Xh+JFPsQzWS90p8bogKk9eqyTux1C3XLVthLmAQ7tuFQnHY9Yn8egen3CVnPmO6Ui+PXvXGXPdRHlkQDorBYJPrW0yWfrPKMvQRKoFTxHj7CyrHK+VI+u+ls8jw73leRXImCUv2tOlUQC8EwQY9Ytsc3sGZiQOavYJ2CfMeBIQtWM5ARPg/67M9l8I84zOkQgJmC7aHfi9DEcz1PbEYpZ5m+9fmVSatPsNSN7ceFwQ0EDPa/p5X9EpPfs+SoGlNu84tgorGUzdr3HjEPNybYN7LJlOGDnVfMqmayMU6drkX+2hrXeprzAgMBAAECggEAO8R4NTotJ2WQVRNALlvA/8kWslAB2VEFweytFX4tjmV//2t8eePyxuoWQ83MUnCJaxiOZoCmgPYFZOmVba4xSpWUdWFqa+O24fyu5y1He8ojW5lGEWZQxJPXQYkuLptWWPVv+CP6mJcPaYUMajgjrjIljY/GhfXKd8DczCZElcB5rUVqDaogYbwSBP4YoqRwDv2ttpxdbTXVdrFGKK8hBt1c5w4jCUNplqdlXcdR8q5/eDRfU7nfRp4O3ulB3SXXmOWNnsVquH+VsvtafCy5vnH/6fM4xQ6QE9GMO5M833SpImxhKT1Kmy7kJQX2e425K+pn6JxQVsxDt4akcg/14QKBgQDbckqxPL6mnI0OAVo1riIMri/btqLxjajvpDCqUTNp5LQZKw7tX+LluHzLChzOmn3X9R8J1Hz4+fxUBoVRllTdnHR7XBgWjkOytIvxVE2zwf9qwiBH+1qkTF591uNPHGN/A1FsrkJncgk28/yZt3V2Apw5Ig2/EOowB3ke3F1n6QKBgQCuQnsb1O66ne7WMocu/2aU7b7bfTh51V4w7x6EklvRyP54InHY6lOZYLazJOhWNVUGKJT42Apkq3O7X0j0AU1dQ7u/cm9N1g8SAHRBsw6JBsSvCsMrWHabuRHSJlkV8VyMgHyKXza+4wh5Vf57cogE11s/SEhWcjmL9iUtfa1+ewKBgEue/w5EmI5htFn3LVcCQsmL3QIh1dTXtDegpQSMJuN+5HEn3WT/ffkbsiVlvreTlXouBhwlFUvXGZT7CkYrP+N+XsWD3ukm7T1P6kmne39Ogu4PJ4CmpX2os4c53esNJVxHkG+bPVbYfURqn8l45wlbrOojSgllks4qRRrVZXrBAoGAb3aWyHarPTNIUjp/vdAgDaMFMeAm/8c7OJG7M5FqqgWmv7FIoTdBwhnawzwYYQw8FnRe1c1a2InSvUd1op4ynjV1IkBQcbk6aolf06Z05bEunciEjnVHaNQ4UfO1iBOa30RQZTICEpemE/atkMjxuCcIdrIFk0X9CUmo/jAliYECgYEAoCRYZbT7q9qSPpTwaH2r3AH/Hgrn9z4NRAmxt8G/Z+Tp7+cv0zC/oxUPO89zFZSC2a/AHzgf8wQ53gYoaY/lP97aTmKO+7ZAeNWSN0KLLFEMF8fGIRG7V6TARg+saGdCn/AeZucm5ARWfR6MElDhKyjlKWNZoIyzQyGEZclGKzI=",
"ali_sandbox"=>0
];

public static function getByName($name){
if (static::$env=="wendy") {
return static::$wendy[$name];
}else{
return static::$Lan[$name];
}
}
}

+ 65
- 0
addons/epay/Epay.php View File

@@ -0,0 +1,65 @@
<?php

namespace addons\epay;

use app\common\library\Menu;
use think\Addons;
use think\Config;
use think\Loader;

/**
* 微信支付宝整合插件
*/
class Epay extends Addons
{

/**
* 插件安装方法
* @return bool
*/
public function install()
{

return true;
}

/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{

return true;
}

/**
* 插件启用方法
* @return bool
*/
public function enable()
{

return true;
}

/**
* 插件禁用方法
* @return bool
*/
public function disable()
{

return true;
}

/**
* 添加命名空间
*/
public function appInit()
{
//添加支付包的命名空间
Loader::addNamespace('Yansongda', ADDON_PATH . 'epay' . DS . 'library' . DS . 'Yansongda' . DS);
}

}

+ 91
- 0
addons/epay/assets/css/common.css View File

@@ -0,0 +1,91 @@
/*!
* Start Bootstrap - Modern Business (http://startbootstrap.com/)
* Copyright 2013-2016 Start Bootstrap
* Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE)
*/
/* Global Styles */
html,
body {
height: 100%;
}
body {
padding-top: 50px;
/* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.img-addon {
margin-bottom: 10px;
width: 100%;
}
.img-hover:hover {
opacity: 0.8;
}
.display-1 {
font-size: 44px;
}
.display-4 {
font-size: 24px;
line-height: 32px;
}
/* Home Page Carousel */
header.carousel {
height: 50%;
}
header.carousel .item,
header.carousel .item.active,
header.carousel .carousel-inner {
height: 100%;
}
header.carousel .fill {
width: 100%;
height: 100%;
}
.error-404 {
font-size: 100px;
}
/* Pricing Page Styles */
.price {
display: block;
font-size: 50px;
line-height: 50px;
}
.price sup {
top: -20px;
left: 2px;
font-size: 20px;
}
.period {
display: block;
font-style: italic;
}
/* Footer Styles */
footer {
margin: 50px 0;
}
/* Responsive Styles */
@media (max-width: 991px) {
.customer-img,
.img-related {
margin-bottom: 30px;
}
}
@media (max-width: 767px) {
.img-addon {
margin-bottom: 15px;
}
header.carousel .carousel {
height: 70%;
}
}
.carousel-body {
position: absolute;
width: 100%;
top: 25%;
text-align: center;
color: #fff;
}
.addonlist a > p {
margin-bottom: 15px;
}

+ 20
- 0
addons/epay/assets/css/epay.css View File

@@ -0,0 +1,20 @@
@import url("../../../css/bootstrap.min.css");
@import url("../../../libs/font-awesome/css/font-awesome.min.css");
html,
body {
height: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
overflow-x: hidden;
overflow-y: auto;
background: #f4f6f8;
font-size: 14px;
color: #616161;
}
.container {
max-width: 850px;
margin: 0 auto;
padding: 50px;
}

+ 100
- 0
addons/epay/assets/css/wechat.css View File

@@ -0,0 +1,100 @@
.wechat {
margin-top: 30px;
}

.wechat h2 {
margin: 0 0 15px 0;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
position: relative;
}

.wechat-body {
}

.wechat-qrcode {
margin-bottom: 20px;
position: relative;
}

.wechat-qrcode img {
width: 100%;
border: 1px solid #eee;
}

.wechat-qrcode .expired {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
opacity: .95;
background: #fff url(../images/expired.png) center center no-repeat;
}

.wechat-qrcode .paid {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
opacity: .95;
background: #fff url(../images/paid.png) center center no-repeat;
}

.wechat-scan {
padding: 0;
}

.wechat-scan img {
width: 100%;
}

.wechat-tips {
height: 60px;
padding: 8px 0 8px 125px;
background: #00c800 url(../images/scan.png) 50px 12px no-repeat;
background-size: 36px 36px;
}

.wechat-tips p {
margin: 0;
font-size: 14px;
line-height: 22px;
color: #fff;
font-weight: 700
}

.wechat-time {
font-size: 14px;
margin-bottom: 15px;
position: absolute;
top: 15px;
right: 10px;
font-weight: normal;
display: none;
}

.wechat-time span {
color: red;
}

.wechat-order {
margin-bottom: 5px;
}

.wechat-order em {
font-style: normal;
color: #666;
}

.wechat-order em.wechat-price {
color: #ff3333;
font-weight: bold;
}

@media (max-width: 767px) {
.wechat {
margin-top: 20px;
}
}

BIN
addons/epay/assets/images/alipay.png View File

Before After
Width: 136  |  Height: 48  |  Size: 3.6 KiB

BIN
addons/epay/assets/images/expired.png View File

Before After
Width: 63  |  Height: 48  |  Size: 4.6 KiB

BIN
addons/epay/assets/images/logo-alipay.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.6 KiB

BIN
addons/epay/assets/images/logo-wechat.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.7 KiB

BIN
addons/epay/assets/images/logo.png View File

Before After
Width: 440  |  Height: 98  |  Size: 23 KiB

BIN
addons/epay/assets/images/paid.png View File

Before After
Width: 48  |  Height: 48  |  Size: 2.2 KiB

BIN
addons/epay/assets/images/scan.png View File

Before After
Width: 64  |  Height: 64  |  Size: 922 B

BIN
addons/epay/assets/images/tips.png View File

Before After
Width: 329  |  Height: 421  |  Size: 21 KiB

BIN
addons/epay/assets/images/wechat.png View File

Before After
Width: 158  |  Height: 48  |  Size: 22 KiB

+ 52
- 0
addons/epay/assets/js/common.js View File

@@ -0,0 +1,52 @@
$(function () {
$('.carousel').carousel({
interval: 5000 //changes the speed
});
$(".btn-experience").on("click", function () {
location.href = "/addons/epay/index/experience?amount=" + $("input[name=amount]").val() + "&type=" + $(this).data("type") + "&method=" + $("#method").val();
});

var si, xhr;
if (typeof queryParams != 'undefined') {
var queryResult = function () {
xhr && xhr.abort();
xhr = $.ajax({
url: "",
type: "post",
data: queryParams,
dataType: 'json',
success: function (ret) {
if (ret.code == 1) {
var data = ret.data;
console.log(data);
if (typeof data.trade_state != 'undefined') {
if (data.trade_state == 'SUCCESS') {
$(".wechat-qrcode .paid").removeClass("hidden");
$(".wechat-tips p").html("支付成功!<br>3秒后将自动跳转...");
setTimeout(function () {
location.href = queryParams.return_url;
}, 3000);
clearInterval(si);
} else if (data.trade_state == 'REFUND') {
$(".wechat-tips p").html("请求失败!<br>请返回重新发起支付");
clearInterval(si);
} else if (data.trade_state == 'NOTPAY') {
} else if (data.trade_state == 'CLOSED') {
$(".wechat-tips p").html("订单已关闭!<br>请返回重新发起支付");
clearInterval(si);
} else if (data.trade_state == 'USERPAYING') {
} else if (data.trade_state == 'PAYERROR') {
clearInterval(si);
}
}
}
}
});
};
si = setInterval(function () {
queryResult();
}, 3000);
queryResult();
}

});

+ 113
- 0
addons/epay/assets/less/common.less View File

@@ -0,0 +1,113 @@
/*!
* Start Bootstrap - Modern Business (http://startbootstrap.com/)
* Copyright 2013-2016 Start Bootstrap
* Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE)
*/

/* Global Styles */

html,
body {
height: 100%;
}

body {
padding-top: 50px; /* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;

}

.img-addon {
margin-bottom: 10px;
width:100%;
}

.img-hover:hover {
opacity: 0.8;
}

.display-1 {
font-size:44px;
}
.display-4 {
font-size:24px;
line-height:32px;
}

/* Home Page Carousel */

header.carousel {
height: 50%;
}

header.carousel .item,
header.carousel .item.active,
header.carousel .carousel-inner {
height: 100%;
}

header.carousel .fill {
width: 100%;
height: 100%;
}

.error-404 {
font-size: 100px;
}

/* Pricing Page Styles */

.price {
display: block;
font-size: 50px;
line-height: 50px;
}

.price sup {
top: -20px;
left: 2px;
font-size: 20px;
}

.period {
display: block;
font-style: italic;
}

/* Footer Styles */

footer {
margin: 50px 0;
}

/* Responsive Styles */

@media(max-width:991px) {
.customer-img,
.img-related {
margin-bottom: 30px;
}
}

@media(max-width:767px) {
.img-addon {
margin-bottom: 15px;
}

header.carousel .carousel {
height: 70%;
}
}
.carousel-body {
position:absolute;
width: 100%;
top:25%;
text-align:center;
color:#fff;
}

.addonlist a > p{
margin-bottom:15px;
}

+ 28
- 0
addons/epay/assets/less/epay.less View File

@@ -0,0 +1,28 @@
@import (reference) "../../../../public/assets/less/bootstrap-less/mixins.less";
@import (reference) "../../../../public/assets/less/bootstrap-less/variables.less";
@import (reference) "../../../../public/assets/less/fastadmin/mixins.less";
@import (reference) "../../../../public/assets/less/fastadmin/variables.less";
@import "../../../../public/assets/less/lesshat.less";
@import url("../../../css/bootstrap.min.css");
@import url("../../../libs/font-awesome/css/font-awesome.min.css");

html,
body {
height: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
overflow-x: hidden;
overflow-y: auto;
background: #f4f6f8;
font-size: 14px;
color: #616161;

}

.container {
max-width: 850px;
margin: 0 auto;
padding:50px;
}

+ 26
- 0
addons/epay/certs/apiclient_cert.pem View File

@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEZTCCA86gAwIBAgIDHYb3MA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJD
TjESMBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UE
ChMHVGVuY2VudDEMMAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1jaENBMR8w
HQYJKoZIhvcNAQkBFhBtbXBheW1jaEB0ZW5jZW50MB4XDTE2MDQwNjEyNTAyNVoX
DTI2MDQwNDEyNTAyNVowgZUxCzAJBgNVBAYTAkNOMRIwEAYDVQQIEwlHdWFuZ2Rv
bmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdUZW5jZW50MQ4wDAYDVQQL
EwVNTVBheTEqMCgGA1UEAxQh6JyY6Jub6KGM572R57uc56eR5oqA5pyJ6ZmQ5YWs
5Y+4MREwDwYDVQQEEwgxMTc3NDYwNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAMJqPHEeUQvWZQWl5W/QvI/MR97jCY6iArnfPPkLBgWY6lEh7cGFn5Fq
C2DsTHxuUC/7si9Sq5QHA2K8VaLk8qYDj2CurT0yRFVAVss/NYfPerZ6nHLbEB4p
dYg6jUvQVWe7n5hJScq+89MNGUOpgF4uCCD/HyUDpRT8MFRQ+yGDTpuCjqZwexgM
e0jNTKwvCXVwLcgR9LFknSiJCxDHAqauqd4r+ZAjDU4CZ/JWdeyLuRUqwxz4kECE
S9iC79mhyo/KwoUupsZKp8RKacrhHybqMjgyZNFsVueLHjcDpYkMgrpUQU6QBJv6
pLqOPejSQg99ddJNBTJJwwffU2mrDG0CAwEAAaOCAUYwggFCMAkGA1UdEwQCMAAw
LAYJYIZIAYb4QgENBB8WHSJDRVMtQ0EgR2VuZXJhdGUgQ2VydGlmaWNhdGUiMB0G
A1UdDgQWBBTIibbUnV9kTejncwyzXb81/xqj9TCBvwYDVR0jBIG3MIG0gBQ+BSb2
ImK0FVuIzWR+sNRip+WGdKGBkKSBjTCBijELMAkGA1UEBhMCQ04xEjAQBgNVBAgT
CUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNVBAoTB1RlbmNlbnQx
DDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEfMB0GCSqGSIb3DQEJ
ARYQbW1wYXltY2hAdGVuY2VudIIJALtUlyu8AOhXMA4GA1UdDwEB/wQEAwIGwDAW
BgNVHSUBAf8EDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOBgQAHelavW3WB
2qBtcG0uEVPLYlWKMvYpO79QUaWPYWh9bywA9d2zqoM8LfWgkOJtmetNdiqh3RVf
/DrKWsLalluaLIMEHuX2chnvtT7vIO4ILijgP/4MZ9k8Jpmi3tKUfFpJVA7E4MXa
7vM5gl21FRuqB96m24tynWHjmgshc4Kk2g==
-----END CERTIFICATE-----

+ 28
- 0
addons/epay/certs/apiclient_key.pem View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCajxxHlEL1mUF
peVv0LyPzEfe4wmOogK53zz5CwYFmOpRIe3BhZ+Ragtg7Ex8blAv+7IvUquUBwNi
vFWi5PKmA49grq09MkRVQFbLPzWHz3q2epxy2xAeKXWIOo1L0FVnu5+YSUnKvvPT
DRlDqYBeLggg/x8lA6UU/DBUUPshg06bgo6mcHsYDHtIzUysLwl1cC3IEfSxZJ0o
iQsQxwKmrqneK/mQIw1OAmfyVnXsi7kVKsMc+JBAhEvYgu/ZocqPysKFLqbGSqfE
SmnK4R8m6jI4MmTRbFbnix43A6WJDIK6VEFOkASb+qS6jj3o0kIPfXXSTQUyScMH
31NpqwxtAgMBAAECggEALemSzo//SdFe2B+eeHKOJVNz4aIyXpnKFQUwTAwbZvT+
2RwvHtWkol2txDzprzUKANrq8JwQYwvo88dQXgC9gRE0Kfv2c45Mbumb1bHevWz1
KOT5z3IGc2kNFZfmSHIxySaZAQjFwXio8j2UqtL7usIaL1iwjTg4IyWPcEoTlI0Y
reRXlZY5z+VpaDFQubFytF+5zlb7ck/lPa8B6IJXZTBBQC6zBhuxXPky8uAjiza1
1C0EHcIIwA+jkVxRbV4e8e6VV4OPnjgok8rN0GPEPlJNo/Gs73vSCRNOYgz5QwTB
7JgRc4eFEXLaX7ntZxhkrOjK1kJQ8hLxYQLvygA0zQKBgQD8+PmHg59Y4c6MkYYk
Gxn8SK6QCtNns72uFi3DJAN9j7x3ZSb4PcjDao0e9BeOt2wKuX+kOyXtSbKA33o/
izeevp9UF2eNhGWgGaU7kMAgylS/V/iIN4A4UuzOyPEYSa9LYLMeHwh+OtH6skqZ
ZjRPaLyJYrhP8Ecqp1B7rmu4rwKBgQDEvdwvvpmiEbui91g2l9P1E/ik3f+VfOTR
5qKtYHYtYdkZAmg+7B6V5f8BCjx7NScS9di8J5KEOuDAc/MXD+o9jDxlxsSmAXB4
n6fqko/wHmG+Q6FXmFamO3mdj+ziKt6ykoNQWS3lzZ4KLHNC1lDwMsd6VmMMr3Ys
iGH4nYYbowKBgDc7kRfCaDc6ziMo3tXhSPIpWFvA0VmSB/cLhqBVq6FtkaOr5S9M
JhpsmDVK7B3P9Hn++Fx+QZCmh5/Vq1ZWaiVxz03H8mcWoi2ri8UOnLRMGObSKURs
gcVKbcPUYbeA1xIpIdKQygTtiM0owlrt0rwHzSpd8Ioblx47+7mVYpWnAoGBAKgu
QMZToZNoo0S5OiBZA6iyLNAKsgxA2n4QMSoSlpNO3L3DUAfR4odzN9zUukT8d+1+
WYrmLRp6FlyOAdTKFwwMEClUlA/wlQuYN3uPVBoIbretqoNtx0yM9PZa7T2dNgfi
tPv/b/vNHHdH7jPJbyEV123d4QgcCeIhp9ZWGikPAoGBAMUbx9snnBwswUae+Dv2
NkH02dv7oPQnPWKbk8b1s/LQEuisYO+34Aofx1ik5MmAZBN/3x8Cn7/i0eOKEUnd
TRsJuiiSFLYdNISDUBQ4R263uSewow9kagrk/lwQgZ/6pJSXQH9G1ycNeZxmR3dq
XevCR+GjHIwTFaYo4XOBYoNw
-----END PRIVATE KEY-----

+ 70
- 0
addons/epay/config.php View File

@@ -0,0 +1,70 @@
<?php
use addons\config\AliPayConfig;

return array (
0 =>
array (
'name' => 'wechat',
'title' => '微信',
'type' => 'array',
'content' =>
array (
),
'value' =>
array (
'appid' => 'wxbe6da4af3e529e0c',
'app_id' => 'wxbe6da4af3e529e0c',
'app_secret' => '7c1b14020e87e9e213696e870da0e549',
'miniapp_id' => '',
'mch_id' => '1329733601',
'key' => 'a6654d342eedd8e293692a3e211a5e53',
'notify_url' => '',
'cert_client' => '/epay/certs/apiclient_cert.pem',
'cert_key' => '/epay/certs/apiclient_key.pem',
'log' => '1',
),
'rule' => '',
'msg' => '',
'tip' => '微信参数配置',
'ok' => '',
'extend' => '',
),
1 =>
array (
'name' => 'alipay',
'title' => '支付宝',
'type' => 'array',
'content' =>
array (
),
'value' =>
array (
'app_id' => AliPayConfig::getByName('ali_app_id'),
'notify_url' => AliPayConfig::getByName('ali_notify_url'),
'return_url' => AliPayConfig::getByName('ali_return_url'),
'ali_public_key' => AliPayConfig::getByName('ali_public_key'),
'private_key' => AliPayConfig::getByName('ali_private_key'),
'log' => '1',
),
'rule' => 'required',
'msg' => '',
'tip' => '支付宝参数配置',
'ok' => '',
'extend' => '',
),
2 =>
array (
'name' => '__tips__',
'title' => '温馨提示',
'type' => 'array',
'content' =>
array (
),
'value' => '请注意微信支付证书路径位于/addons/epay/certs目录下,请替换成你自己的证书<br>appid:APP的appid<br>app_id:公众号的appid<br>app_secret:公众号的secret<br>miniapp_id:小程序ID<br>mch_id:微信商户ID<br>key:微信商户支付的密钥',
'rule' => '',
'msg' => '',
'tip' => '微信参数配置',
'ok' => '',
'extend' => '',
),
);

+ 229
- 0
addons/epay/controller/Api.php View File

@@ -0,0 +1,229 @@
<?php

namespace addons\epay\controller;

use addons\epay\library\Service;
use addons\epay\library\Wechat;
use Endroid\QrCode\QrCode;
use think\addons\Controller;
use think\Response;
use think\Session;
use Yansongda\Pay\Pay;

/**
* API接口控制器
*
* @package addons\epay\controller
*/
class Api extends Controller
{

protected $layout = 'default';
protected $config = [];

/**
* 默认方法
*/
public function index()
{
$this->error();
}

/**
* 外部提交
*/
public function submit()
{
$out_trade_no = $this->request->request("out_trade_no");
$title = $this->request->request("title");
$amount = $this->request->request('amount');
$type = $this->request->request('type');
$method = $this->request->request('method', 'web');
$openid = $this->request->request('openid', '');
$auth_code = $this->request->request('auth_code', '');
$notifyurl = $this->request->request('notifyurl', '');
$returnurl = $this->request->request('returnurl', '');

if (!$amount || $amount < 0) {
$this->error("支付金额必须大于0");
}

if (!$type || !in_array($type, ['alipay', 'wechat'])) {
$this->error("支付类型错误");
}

$params = [
'type' => $type,
'out_trade_no' => $out_trade_no,
'title' => $title,
'amount' => $amount,
'method' => $method,
'openid' => $openid,
'auth_code' => $auth_code,
'notifyurl' => $notifyurl,
'returnurl' => $returnurl,
];
return Service::submitOrder($params);
}

/**
* 微信支付
* @return string
*/
public function wechat()
{
$config = Service::getConfig('wechat');

$isWechat = stripos($this->request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;
$isMobile = $this->request->isMobile();
$this->view->assign("isWechat", $isWechat);
$this->view->assign("isMobile", $isMobile);

if ($isWechat) {
//发起公众号(jsapi支付)
$orderData = Session::get("wechatorderdata");
$openid = Session::get('openid');
//如果没有openid
if (!$openid) {
$wechat = new Wechat($config['wechat']['app_id'], $config['wechat']['app_secret']);
$openid = $wechat->getOpenid();
}

$orderData['method'] = 'mp';
$orderData['openid'] = $openid;
$payData = Service::submitOrder($orderData);
// $payData = json_decode($payData, true);
if (!isset($payData['appId'])) {
$this->error("创建订单失败,请返回重试");
}
$type = 'jsapi';
$this->view->assign("orderData", $orderData);
$this->view->assign("payData", $payData);
} else {
//发起PC支付(Native支付)
$body = $this->request->request("body");
$code_url = $this->request->request("code_url");
$out_trade_no = $this->request->request("out_trade_no");
$return_url = $this->request->request("return_url");
$total_fee = $this->request->request("total_fee");

$sign = $this->request->request("sign");

$data = [
'body' => $body,
'code_url' => $code_url,
'out_trade_no' => $out_trade_no,
'return_url' => $return_url,
'total_fee' => $total_fee,
];
if ($sign != md5(implode('', $data) . $config['wechat']['appid'])) {
$this->error("签名不正确");
}

if ($this->request->isAjax()) {
$pay = new Pay($config);
$result = $pay->driver('wechat')->gateway('scan')->find($out_trade_no);
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
$this->success("", "", ['trade_state' => $result['trade_state']]);
} else {
$this->error("查询失败");
}
}
$data['sign'] = $sign;
$type = 'pc';
$this->view->assign("data", $data);
}

$this->view->assign("type", $type);
$this->view->assign("title", "微信支付");
return $this->view->fetch();
}

/**
* 支付成功回调
*/
public function notifyx()
{
$type = $this->request->param('type');
$data = $this->request->request('', null, 'trim');
$config = Service::getConfig($type);
$pay = new Pay($config);
if (!$pay->driver($type)->gateway()->verify($data)) {
echo '签名错误';
return;
}

//你可以在这里你的业务处理逻辑,比如处理你的订单状态、给会员加余额等等功能
//下面这句必须要执行,且在此之前不能有任何输出
echo "success";
return;
}

/**
* 支付成功返回
*/
public function returnx()
{
$type = $this->request->param('type');
$data = $this->request->request('', null, 'trim');
$config = Service::getConfig($type);
$pay = new Pay($config);
if ($type == 'alipay' && !$pay->driver($type)->gateway()->verify($data)) {
echo '签名错误';
return;
}

//你可以在这里定义你的提示信息,但切记不可在此编写逻辑
$this->success("恭喜你!支付成功!", addon_url("epay/index/index"));

return;
}

/**
* 生成二维码
* @return Response
*/
public function qrcode()
{
$text = $this->request->get('text', 'hello world');
$size = $this->request->get('size', 250);
$padding = $this->request->get('padding', 15);
$errorcorrection = $this->request->get('errorcorrection', 'medium');
$foreground = $this->request->get('foreground', "#ffffff");
$background = $this->request->get('background', "#000000");
$logo = $this->request->get('logo');
$logosize = $this->request->get('logosize');
$label = $this->request->get('label');
$labelfontsize = $this->request->get('labelfontsize');
$labelhalign = $this->request->get('labelhalign');
$labelvalign = $this->request->get('labelvalign');

// 前景色
list($r, $g, $b) = sscanf($foreground, "#%02x%02x%02x");
$foregroundcolor = ['r' => $r, 'g' => $g, 'b' => $b];

// 背景色
list($r, $g, $b) = sscanf($background, "#%02x%02x%02x");
$backgroundcolor = ['r' => $r, 'g' => $g, 'b' => $b];

$qrCode = new QrCode();
$qrCode
->setText($text)
->setSize($size)
->setPadding($padding)
->setErrorCorrection($errorcorrection)
->setForegroundColor($foregroundcolor)
->setBackgroundColor($backgroundcolor)
->setLogoSize($logosize)
->setLabelFontPath(ROOT_PATH . 'public/assets/fonts/Times New Roman.ttf')
->setLabel($label)
->setLabelFontSize($labelfontsize)
->setLabelHalign($labelhalign)
->setLabelValign($labelvalign)
->setImageType(QrCode::IMAGE_TYPE_PNG);
//也可以直接使用render方法输出结果
//$qrCode->render();
return new Response($qrCode->get(), 200, ['Content-Type' => $qrCode->getContentType()]);
}

}

+ 112
- 0
addons/epay/controller/Index.php View File

@@ -0,0 +1,112 @@
<?php

namespace addons\epay\controller;

use addons\epay\library\Service;
use addons\unishop\model\Config;
use fast\Random;
use think\addons\Controller;
use think\Hook;
use Yansongda\Pay\Log;
use Yansongda\Pay\Pay;
use Exception;

/**
* 微信支付宝插件首页
*
* 此控制器仅用于开发展示说明和体验,建议自行添加一个新的控制器进行处理返回和回调事件,同时删除此控制器文件
*
* Class Index
* @package addons\epay\controller
*/
class Index extends Controller
{

protected $layout = 'default';

protected $config = [];

public function _initialize()
{
parent::_initialize();
}

public function index()
{
$this->view->assign("title", "FastAdmin微信支付宝整合插件");
return $this->view->fetch();
}

/**
* 体验,仅供开发测试
*/
public function experience()
{
$amount = $this->request->request('amount');
$type = $this->request->request('type');
$method = $this->request->request('method');

if (!$amount || $amount < 0) {
$this->error("支付金额必须大于0");
}

if (!$type || !in_array($type, ['alipay', 'wechat'])) {
$this->error("支付类型不能为空");
}

//订单号
$out_trade_no = date("YmdHis") . mt_rand(100000, 999999);

//订单标题
$title = 'FastAdmin测试订单';

//回调链接
$notifyurl = $this->request->root(true) . '/addons/epay/index/notifyx/paytype/' . $type;
$returnurl = $this->request->root(true) . '/addons/epay/index/returnx/paytype/' . $type . '/out_trade_no/' . $out_trade_no;

return Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method);
}

/**
* 支付成功,仅供开发测试
*/
public function notifyx()
{
$paytype = $this->request->param('paytype');
$pay = \addons\epay\library\Service::checkNotify($paytype);
if (!$pay) {
echo '签名错误';
return;
}
$data = $pay->verify();
try {
$payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
$out_trade_no = $data['out_trade_no'];

//你可以在此编写订单逻辑


} catch (Exception $e) {
}
echo $pay->success();
}

/**
* 支付返回,仅供开发测试
*/
public function returnx()
{
$paytype = $this->request->param('paytype');
$out_trade_no = $this->request->param('out_trade_no');
$pay = \addons\epay\library\Service::checkReturn($paytype);
if (!$pay) {
$this->error('签名错误');
}

//你可以在这里通过out_trade_no去验证订单状态
//但是不可以在此编写订单逻辑!!!

$this->success("请返回网站查看支付结果", addon_url("epay/index/index"));
}

}

+ 8
- 0
addons/epay/info.ini View File

@@ -0,0 +1,8 @@
name = epay
title = 微信支付宝整合
intro = 可用于整合微信、支付宝付款,快速整合FastAdmin的其它模块
author = Karson
website = https://www.fastadmin.net
version = 1.0.5
state = 1
url = /addons/epay

+ 17
- 0
addons/epay/library/OrderException.php View File

@@ -0,0 +1,17 @@
<?php

namespace addons\epay\library;


use think\Exception;

class OrderException extends Exception
{
public function __construct($message = "", $code = 0, $data = [])
{
$this->message = $message;
$this->code = $code;
$this->data = $data;
}

}

+ 306
- 0
addons/epay/library/Service.php View File

@@ -0,0 +1,306 @@
<?php

namespace addons\epay\library;

use addons\unishop\model\Config;
use Exception;
use think\Log;
use think\Request;
use think\Response;
use think\Session;
use Yansongda\Pay\Gateways\Alipay\Alipay;
use Yansongda\Pay\Pay;

/**
* 订单服务类
*
* @package addons\epay\library
*/
class Service
{

public static function submitOrder($amount, $orderid = null, $type = null, $title = null, $notifyurl = null, $returnurl = null, $method = null)
{
if (!is_array($amount)) {
$params = [
'amount' => $amount,
'orderid' => $orderid,
'type' => $type,
'title' => $title,
'notify_url' => $notifyurl,
'return_url' => $returnurl,
'method' => $method,
];
} else {
$params = $amount;
}
$type = isset($params['type']) && in_array($params['type'], ['alipay', 'wechat']) ? $params['type'] : 'wechat';
$method = isset($params['method']) ? $params['method'] : 'web';
$orderid = isset($params['orderid']) ? $params['orderid'] : date("YmdHis") . mt_rand(100000, 999999);
$amount = isset($params['amount']) ? $params['amount'] : 1;
$title = isset($params['title']) ? $params['title'] : "支付";
$auth_code = isset($params['auth_code']) ? $params['auth_code'] : '';
$openid = isset($params['openid']) ? $params['openid'] : '';

$request = request();
$notifyurl = isset($params['notify_url']) ? $params['notify_url'] : $request->root(true) . '/addons/epay/index/' . $type . 'notify';
$returnurl = isset($params['return_url']) ? $params['return_url'] : $request->root(true) . '/addons/epay/index/' . $type . 'return/out_trade_no/' . $orderid;
$html = '';
$config = Service::getConfig($type);
$config[$type]['notify_url'] = $notifyurl;
$config[$type]['return_url'] = $returnurl;

if ($type == 'alipay') {
//创建支付对象
$pay = new Pay($config);
//支付宝支付,请根据你的需求,仅选择你所需要的即可
$params = [
'out_trade_no' => $orderid,//你的订单号
'total_amount' => $amount,//单位元
'subject' => $title,
];
//如果是移动端自动切换为wap
$method = $request->isMobile() ? 'wap' : $method;

switch ($method) {
case 'web':
//电脑支付,跳转
$html = $pay->driver($type)->gateway('web')->pay($params);
Response::create($html)->send();
break;
case 'wap':
//手机网页支付,跳转
$html = $pay->driver($type)->gateway('wap')->pay($params);
Response::create($html)->send();
break;
case 'app':
//APP支付,直接返回字符串
$html = $pay->driver($type)->gateway('app')->pay($params);
break;
case 'scan':
//扫码支付,直接返回字符串
$html = $pay->driver($type)->gateway('scan')->pay($params);
break;
case 'pos':
//刷卡支付,直接返回字符串
//刷卡支付必须要有auth_code
$params['auth_code'] = $auth_code;
$html = $pay->driver($type)->gateway('pos')->pay($params);
break;
default:
//其它支付类型请参考:https://docs.pay.yansongda.cn/alipay
}
} else {
//如果是PC支付,判断当前环境,进行跳转
if ($method == 'web') {
if ((strpos($request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false)) {
Session::delete("openid");
Session::set("wechatorderdata", $params);
$url = addon_url('epay/api/wechat', [], true, true);
$result = [
"trade_type"=>"MWEB",
"mweb_url"=>$url
];
return $result;
} elseif ($request->isMobile()) {
$method = 'wap';
}
}

//创建支付对象
$pay = new Pay($config);
$params = [
'out_trade_no' => $orderid,//你的订单号
'body' => $title,
'total_fee' => $amount * 100, //单位分
];
switch ($method) {
case 'web':
//电脑支付,跳转到自定义展示页面(FastAdmin独有)
$html = $pay->driver($type)->gateway('web')->pay($params);
Response::create($html)->send();
break;
case 'mp':
//公众号支付
//公众号支付必须有openid
$params['openid'] = $openid;
$html = $pay->driver($type)->gateway('mp')->pay($params);
break;
case 'wap':
//手机网页支付,跳转
$params['spbill_create_ip'] = $request->ip(0, false);
$html = $pay->driver($type)->gateway('wap')->pay($params);
$result = [
"trade_type"=>"MWEB",
"mweb_url"=>$html,
"referer"=>Request::instance()->server('HTTP_REFERER')
];
return $result;
break;
case 'app':
//APP支付,直接返回字符串
$html = $pay->driver($type)->gateway('app')->pay($params);
break;
case 'scan':
//扫码支付,直接返回字符串
$html = $pay->driver($type)->gateway('scan')->pay($params);
break;
case 'pos':
//刷卡支付,直接返回字符串
//刷卡支付必须要有auth_code
$params['auth_code'] = $auth_code;
$html = $pay->driver($type)->gateway('pos')->pay($params);
break;
case 'miniapp':
//小程序支付,直接返回字符串
//小程序支付必须要有openid
$params['openid'] = $openid;
$html = $pay->driver($type)->gateway('miniapp')->pay($params);
break;
default:
}
}
//返回字符串
// $html = is_array($html) ? json_encode($html) : $html;
return $html;
}

/**
* @param string $orderNo 订单号
* @param string $type 支付类型 wechat alipay
* @param int $amount 退款金额
*/
public static function refund($orderNo,$type,$amount){
$config = Service::getConfig($type);
$pay = new Pay($config);
if ($type == "alipay") {
$config_biz = [
'out_trade_no' => $orderNo,
'refund_amount' => $amount,
];
$pay->driver($type)->gateway()->refund($config_biz);
} else {
$config_biz = [
'out_trade_no' => $orderNo,
'out_refund_no' => $orderNo,
'total_fee' => bcmul($amount, 100),
'refund_fee' => bcmul($amount, 100),
];
$pay->driver($type)->gateway()->refund($config_biz);
}

}

/**
* 创建支付对象
* @param string $type 支付类型
* @param array $config 配置信息
* @return bool
*/
public static function createPay($type, $config = [])
{
$type = strtolower($type);
if (!in_array($type, ['wechat', 'alipay'])) {
return false;
}
$config = self::getConfig($type);
$config = array_merge($config[$type], $config);
$pay = new Pay($config);
return $pay;
}

/**
* 验证回调是否成功
* @param string $type 支付类型
* @param array $config 配置信息
* @return bool|Pay
*/
public static function checkNotify($type, $config = [])
{
$type = strtolower($type);
if (!in_array($type, ['wechat', 'alipay'])) {
return false;
}
try {
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/".date("d"). '.log', "开始获取参数" . PHP_EOL, FILE_APPEND);

$pay = new Pay(self::getConfig($type));
$data = $type == 'wechat' ? file_get_contents("php://input") : request()->post('', null, 'trim');
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/".date("d"). '.log', json_encode($data) . PHP_EOL, FILE_APPEND);

$data = $pay->driver($type)->gateway()->verify($data);

if ($type == 'alipay') {
if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
return $pay;
}
} else {
return $pay;
}
} catch (Exception $e) {
return false;
}

return false;
}

/**
* 验证返回是否成功
* @param string $type 支付类型
* @param array $config 配置信息
* @return bool|Pay
*/
public static function checkReturn($type, $config = [])
{
$type = strtolower($type);
if (!in_array($type, ['wechat', 'alipay'])) {
return false;
}
//微信无需验证
if ($type == 'wechat') {
return true;
}
try {
$pay = new Pay(self::getConfig($type));
$data = $type == 'wechat' ? file_get_contents("php://input") : request()->get('', null, 'trim');
$data = $pay->driver($type)->gateway()->verify($data);
if ($data) {
return $pay;
}
} catch (Exception $e) {
return false;
}

return false;
}

/**
* 获取配置
* @param string $type 支付类型
* @return array|mixed
*/
public static function getConfig($type = 'wechat')
{
$config = get_addon_config('epay');
$config = isset($config[$type]) ? $config[$type] : $config['wechat'];
if ($config['log']) {
$config['log'] = [
'file' => LOG_PATH . '/epaylogs/' . $type . '-' . date("Y-m-d") . '.log',
'level' => 'debug'
];
}
if (isset($config['cert_client']) && substr($config['cert_client'], 0, 6) == '/epay/') {
$config['cert_client'] = ADDON_PATH . $config['cert_client'];
}
if (isset($config['cert_key']) && substr($config['cert_key'], 0, 6) == '/epay/') {
$config['cert_key'] = ADDON_PATH . $config['cert_key'];
}

$config['notify_url'] = empty($config['notify_url']) ? addon_url('epay/api/notifyx', [], false) . '/type/' . $type : $config['notify_url'];
$config['notify_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['notify_url']) ? request()->root(true) . $config['notify_url'] : $config['notify_url'];
$config['return_url'] = empty($config['return_url']) ? addon_url('epay/api/returnx', [], false) . '/type/' . $type : $config['return_url'];
$config['return_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['return_url']) ? request()->root(true) . $config['return_url'] : $config['return_url'];
return [$type => $config];
}

}

+ 107
- 0
addons/epay/library/Wechat.php View File

@@ -0,0 +1,107 @@
<?php

namespace addons\epay\library;

use fast\Http;
use think\Cache;
use think\Session;

/**
* 微信授权
*
*/
class Wechat
{
private $app_id = '';
private $app_secret = '';
private $scope = 'snsapi_userinfo';

public function __construct($app_id, $app_secret)
{
$this->app_id = $app_id;
$this->app_secret = $app_secret;
}

/**
* 获取微信授权链接
*
* @return string
*/
public function getAuthorizeUrl()
{
$redirect_uri = addon_url('epay/api/wechat', [], true, true);
$redirect_uri = urlencode($redirect_uri);
$state = \fast\Random::alnum();
Session::set('state', $state);
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->app_id}&redirect_uri={$redirect_uri}&response_type=code&scope={$this->scope}&state={$state}#wechat_redirect";
}

/**
* 获取微信openid
*
* @return mixed|string
*/
public function getOpenid()
{
$openid = Session::get('openid');
if (!$openid) {
if (!isset($_GET['code'])) {
$url = $this->getAuthorizeUrl();

Header("Location: $url");
exit();
} else {
$state = Session::get('state');
if ($state == $_GET['state']) {
$code = $_GET['code'];
$token = $this->getAccessToken($code);
$openid = isset($token['openid']) ? $token['openid'] : '';
if ($openid) {
Session::set("openid", $openid);
}
}
}
}
return $openid;
}

/**
* 获取授权token网页授权
*
* @param string $code
* @return mixed|string
*/
public function getAccessToken($code = '')
{
$params = [
'appid' => $this->app_id,
'secret' => $this->app_secret,
'code' => $code,
'grant_type' => 'authorization_code'
];
$ret = Http::sendRequest('https://api.weixin.qq.com/sns/oauth2/access_token', $params, 'GET');
if ($ret['ret']) {
$ar = json_decode($ret['msg'], true);
return $ar;
}
return [];
}

public function getJsticket()
{
$jsticket = Session::get('jsticket');
if (!$jsticket) {
$token = $this->getAccessToken($code);
$params = [
'access_token' => 'token',
'type' => 'jsapi',
];
$ret = Http::sendRequest('https://api.weixin.qq.com/cgi-bin/ticket/getticket', $params, 'GET');
if ($ret['ret']) {
$ar = json_decode($ret['msg'], true);
return $ar;
}
}
return $jsticket;
}
}

+ 63
- 0
addons/epay/library/Yansongda/Pay/Contracts/GatewayInterface.php View File

@@ -0,0 +1,63 @@
<?php

namespace Yansongda\Pay\Contracts;

interface GatewayInterface
{
/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return mixed
*/
public function pay(array $config_biz);

/**
* refund a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array|string $config_biz
*
* @return array|bool
*/
public function refund($config_biz);

/**
* close a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array|string $config_biz
*
* @return array|bool
*/
public function close($config_biz);

/**
* find a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $out_trade_no
*
* @return array|bool
*/
public function find($out_trade_no);

/**
* verify notify.
*
* @author yansongda <me@yansongda.cn>
*
* @param mixed $data
* @param string $sign
* @param bool $sync
*
* @return array|bool
*/
public function verify($data, $sign = null, $sync = false);
}

+ 7
- 0
addons/epay/library/Yansongda/Pay/Exceptions/Exception.php View File

@@ -0,0 +1,7 @@
<?php

namespace Yansongda\Pay\Exceptions;

class Exception extends \Exception
{
}

+ 28
- 0
addons/epay/library/Yansongda/Pay/Exceptions/GatewayException.php View File

@@ -0,0 +1,28 @@
<?php

namespace Yansongda\Pay\Exceptions;

class GatewayException extends Exception
{
/**
* error raw data.
*
* @var array
*/
public $raw = [];

/**
* [__construct description].
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $message
* @param string|int $code
*/
public function __construct($message, $code, $raw = [])
{
parent::__construct($message, intval($code));

$this->raw = $raw;
}
}

+ 7
- 0
addons/epay/library/Yansongda/Pay/Exceptions/InvalidArgumentException.php View File

@@ -0,0 +1,7 @@
<?php

namespace Yansongda\Pay\Exceptions;

class InvalidArgumentException extends \InvalidArgumentException
{
}

+ 292
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/Alipay.php View File

@@ -0,0 +1,292 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

use addons\config\AliPayConfig;
use Yansongda\Pay\Contracts\GatewayInterface;
use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidArgumentException;
use Yansongda\Pay\Support\Config;
use Yansongda\Pay\Traits\HasHttpRequest;

abstract class Alipay implements GatewayInterface
{
use HasHttpRequest;

/**
* @var string
*/
protected $gateway = 'https://openapi.alipay.com/gateway.do?charset=UTF-8';

/**
* alipay global config params.
*
* @var array
*/
protected $config;

/**
* user's config params.
*
* @var \Yansongda\Pay\Support\Config
*/
protected $user_config;

/**
* [__construct description].
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config [description]
*/
public function __construct(array $config)
{
$this->user_config = new Config($config);

if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

$this->config = [
'app_id' => $this->user_config->get('app_id'),
'method' => '',
'format' => 'JSON',
'charset' => 'UTF-8',
'sign_type' => 'RSA2',
'version' => '1.0',
'notify_url' => AliPayConfig::getByName('ali_notify_url'),
'return_url' => AliPayConfig::getByName('ali_return_url'),
'timestamp' => date('Y-m-d H:i:s'),
'sign' => '',
'biz_content' => '',
];
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return mixed
*/
public function pay(array $config_biz)
{
$config_biz['product_code'] = $this->getProductCode();

$this->config['method'] = $this->getMethod();
$this->config['biz_content'] = json_encode($config_biz);
$this->config['sign'] = $this->getSign();
}

/**
* refund a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param mixed $config_biz
*
* @return array|bool
*/
public function refund($config_biz, $refund_amount = null)
{
if (!is_array($config_biz)) {
$config_biz = [
'out_trade_no' => $config_biz,
'refund_amount' => $refund_amount,
];
}

return $this->getResult($config_biz, 'alipay.trade.refund');
}

/**
* close a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array|string $config_biz
*
* @return array|bool
*/
public function close($config_biz)
{
if (!is_array($config_biz)) {
$config_biz = [
'out_trade_no' => $config_biz,
];
}

return $this->getResult($config_biz, 'alipay.trade.close');
}

/**
* find a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $out_trade_no
*
* @return array|bool
*/
public function find($out_trade_no = '')
{
$config_biz = [
'out_trade_no' => $out_trade_no,
];

return $this->getResult($config_biz, 'alipay.trade.query');
}

/**
* verify the notify.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $data
* @param string $sign
* @param bool $sync
*
* @return array|bool
*/
public function verify($data, $sign = null, $sync = false)
{
return $data;
// if (is_null($this->user_config->get('ali_public_key'))) {
// throw new InvalidArgumentException('Missing Config -- [ali_public_key]');
// }
//
// $sign = is_null($sign) ? $data['sign'] : $sign;
//
// $res = "-----BEGIN PUBLIC KEY-----\n".
// wordwrap($this->user_config->get('ali_public_key'), 64, "\n", true).
// "\n-----END PUBLIC KEY-----";
//
// $toVerify = $sync ? json_encode($data) : $this->getSignContent($data, true);
// return openssl_verify($toVerify, base64_decode($sign), $res, OPENSSL_ALGO_SHA256) === 1 ? $data : false;
}

/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
abstract protected function getMethod();

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
abstract protected function getProductCode();

/**
* build pay html.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function buildPayHtml()
{
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gateway."' method='POST'>";
foreach ($this->config as $key => $val) {
$val = str_replace("'", '&apos;', $val);
$sHtml .= "<input type='hidden' name='".$key."' value='".$val."'/>";
}
$sHtml .= "<input type='submit' value='ok' style='display:none;'></form>";
$sHtml .= "<script>document.forms['alipaysubmit'].submit();</script>";

return $sHtml;
}

/**
* get alipay api result.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
* @param string $method
*
* @return array|bool
*/
protected function getResult($config_biz, $method)
{
$this->config['biz_content'] = json_encode($config_biz);
$this->config['method'] = $method;
$this->config['sign'] = $this->getSign();

$this->config = array_filter($this->config, function ($value) {
return $value !== '' && !is_null($value);
});

$method = str_replace('.', '_', $method).'_response';

$data = json_decode($this->post($this->gateway, $this->config), true);

if (!isset($data[$method]['code']) || $data[$method]['code'] !== '10000') {
throw new GatewayException(
'get result error:'.$data[$method]['msg'].' - '.$data[$method]['sub_code'],
$data[$method]['code'],
$data);
}

return $this->verify($data[$method], $data['sign'], true);
}

/**
* get sign.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getSign()
{
if (is_null($this->user_config->get('private_key'))) {
throw new InvalidArgumentException('Missing Config -- [private_key]');
}

$res = "-----BEGIN RSA PRIVATE KEY-----\n".
wordwrap($this->user_config->get('private_key'), 64, "\n", true).
"\n-----END RSA PRIVATE KEY-----";

openssl_sign($this->getSignContent($this->config), $sign, $res, OPENSSL_ALGO_SHA256);

return base64_encode($sign);
}

/**
* get signContent that is to be signed.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $toBeSigned
* @param bool $verify
*
* @return string
*/
protected function getSignContent(array $toBeSigned, $verify = false)
{
ksort($toBeSigned);

$stringToBeSigned = '';
foreach ($toBeSigned as $k => $v) {
if ($verify && $k != 'sign' && $k != 'sign_type') {
$stringToBeSigned .= $k.'='.$v.'&';
}
if (!$verify && $v !== '' && !is_null($v) && $k != 'sign' && '@' != substr($v, 0, 1)) {
$stringToBeSigned .= $k.'='.$v.'&';
}
}
$stringToBeSigned = substr($stringToBeSigned, 0, -1);
unset($k, $v);

return $stringToBeSigned;
}
}

+ 46
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/AppGateway.php View File

@@ -0,0 +1,46 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class AppGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getMethod()
{
return 'alipay.trade.app.pay';
}

/**
* get productCode method.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return 'QUICK_MSECURITY_PAY';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
parent::pay($config_biz);

return http_build_query($this->config);
}
}

+ 47
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/PosGateway.php View File

@@ -0,0 +1,47 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class PosGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getMethod()
{
return 'alipay.trade.pay';
}

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return 'FACE_TO_FACE_PAYMENT';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
* @param string $scene
*
* @return array|bool
*/
public function pay(array $config_biz = [], $scene = 'bar_code')
{
$config_biz['scene'] = $scene;

return $this->getResult($config_biz, $this->getMethod());
}
}

+ 44
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/ScanGateway.php View File

@@ -0,0 +1,44 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class ScanGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getMethod()
{
return 'alipay.trade.precreate';
}

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return '';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array|bool
*/
public function pay(array $config_biz = [])
{
return $this->getResult($config_biz, $this->getMethod());
}
}

+ 44
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/TransferGateway.php View File

@@ -0,0 +1,44 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class TransferGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getMethod()
{
return 'alipay.fund.trans.toaccount.transfer';
}

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return '';
}

/**
* transfer amount to account.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array|bool
*/
public function pay(array $config_biz = [])
{
return $this->getResult($config_biz, $this->getMethod());
}
}

+ 48
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/WapGateway.php View File

@@ -0,0 +1,48 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class WapGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @version 2017-08-10
*
* @return string [description]
*/
protected function getMethod()
{
return 'alipay.trade.wap.pay';
}

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return 'QUICK_WAP_WAY';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
parent::pay($config_biz);

return $this->buildPayHtml();
}
}

+ 46
- 0
addons/epay/library/Yansongda/Pay/Gateways/Alipay/WebGateway.php View File

@@ -0,0 +1,46 @@
<?php

namespace Yansongda\Pay\Gateways\Alipay;

class WebGateway extends Alipay
{
/**
* get method config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getMethod()
{
return 'alipay.trade.page.pay';
}

/**
* get productCode config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getProductCode()
{
return 'FAST_INSTANT_TRADE_PAY';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
parent::pay($config_biz);

return $this->buildPayHtml();
}
}

+ 50
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/AppGateway.php View File

@@ -0,0 +1,50 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class AppGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'APP';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('appid'))) {
throw new InvalidArgumentException('Missing Config -- [appid]');
}

$this->config['appid'] = $this->user_config->get('appid');

$payRequest = [
'appid' => $this->user_config->get('appid'),
'partnerid' => $this->user_config->get('mch_id'),
'prepayid' => $this->preOrder($config_biz)['prepay_id'],
'timestamp' => strval(time()),
'noncestr' => $this->createNonceStr(),
'package' => 'Sign=WXPay',
];
$payRequest['sign'] = $this->getSign($payRequest);

return $payRequest;
}
}

+ 82
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/GroupredpackGateway.php View File

@@ -0,0 +1,82 @@
<?php

/**
* 发放裂变红包
* Class GroupredpackGateway
* Date: 2017/12/21
* Time: 19:23
* Com:萌点云科技(深圳)有限公司.
*
* Author:陈老司机
*
* Email:690712575@qq.com
*/

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidArgumentException;

class GroupredpackGateway extends Wechat
{
/**
* @var string
*/
protected $gateway_transfer = 'mmpaymkttransfers/sendgroupredpack';

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return mixed
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}
unset($this->config['sign_type']);
unset($this->config['trade_type']);
unset($this->config['notify_url']);
unset($this->config['app_id']);
unset($this->config['appid']);
$this->config = array_merge($this->config, $config_biz);
$this->config['sign'] = $this->getSign($this->config);
$data = $this->fromXml($this->post(
$this->endpoint.$this->gateway_transfer,
$this->toXml($this->config),
[
'cert' => $this->user_config->get('cert_client', ''),
'ssl_key' => $this->user_config->get('cert_key', ''),
]
));
if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS' || $data['result_code'] !== 'SUCCESS') {
$error = 'getResult error:'.$data['return_msg'];
$error .= isset($data['err_code_des']) ? ' - '.$data['err_code_des'] : '';
}

if (isset($error)) {
throw new GatewayException(
$error,
20000,
$data);
}

return $data;
}

/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return '';
}
}

+ 49
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/MiniappGateway.php View File

@@ -0,0 +1,49 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class MiniappGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string [description]
*/
protected function getTradeType()
{
return 'JSAPI';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('miniapp_id'))) {
throw new InvalidArgumentException('Missing Config -- [miniapp_id]');
}

$this->config['appid'] = $this->user_config->get('miniapp_id');

$payRequest = [
'appId' => $this->user_config->get('miniapp_id'),
'timeStamp' => strval(time()),
'nonceStr' => $this->createNonceStr(),
'package' => 'prepay_id='.$this->preOrder($config_biz)['prepay_id'],
'signType' => 'MD5',
];
$payRequest['paySign'] = $this->getSign($payRequest);

return $payRequest;
}
}

+ 47
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/MpGateway.php View File

@@ -0,0 +1,47 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class MpGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'JSAPI';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

$payRequest = [
'appId' => $this->user_config->get('app_id'),
'timeStamp' => strval(time()),
'nonceStr' => $this->createNonceStr(),
'package' => 'prepay_id='.$this->preOrder($config_biz)['prepay_id'],
'signType' => 'MD5',
];
$payRequest['paySign'] = $this->getSign($payRequest);

return $payRequest;
}
}

+ 46
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/PosGateway.php View File

@@ -0,0 +1,46 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class PosGateway extends Wechat
{
/**
* @var string
*/
protected $gateway_order = 'pay/micropay';

/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'MICROPAY';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

unset($this->config['trade_type']);
unset($this->config['notify_url']);

return $this->preOrder($config_biz);
}
}

+ 86
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/RedpackGateway.php View File

@@ -0,0 +1,86 @@
<?php

/**
* 发放普通红包
* Class RedPackGateway
* Date: 2017/12/21
* Time: 19:23
* Com:萌点云科技(深圳)有限公司.
*
* Author:陈老司机
*
* Email:690712575@qq.com
*/

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidArgumentException;

class RedpackGateway extends Wechat
{
/**
* @var string
*/
protected $gateway_transfer = 'mmpaymkttransfers/sendredpack';

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return mixed
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}
unset($this->config['sign_type']);
unset($this->config['trade_type']);
unset($this->config['notify_url']);
unset($this->config['app_id']);
unset($this->config['appid']);

$this->config = array_merge($this->config, $config_biz);

$this->config['sign'] = $this->getSign($this->config);

$data = $this->fromXml($this->post(
$this->endpoint.$this->gateway_transfer,
$this->toXml($this->config),
[
'cert' => $this->user_config->get('cert_client', ''),
'ssl_key' => $this->user_config->get('cert_key', ''),
]
));

if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS' || $data['result_code'] !== 'SUCCESS') {
$error = 'getResult error:'.$data['return_msg'];
$error .= isset($data['err_code_des']) ? ' - '.$data['err_code_des'] : '';
}

if (isset($error)) {
throw new GatewayException(
$error,
20000,
$data);
}

return $data;
}

/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return '';
}
}

+ 38
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/ScanGateway.php View File

@@ -0,0 +1,38 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class ScanGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'NATIVE';
}

/**
* pay a order using modelTWO.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

return $this->preOrder($config_biz)['code_url'];
}
}

+ 78
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/TransferGateway.php View File

@@ -0,0 +1,78 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidArgumentException;

class TransferGateway extends Wechat
{
/**
* @var string
*/
protected $gateway_transfer = 'mmpaymkttransfers/promotion/transfers';

/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return '';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

$config_biz['mch_appid'] = $this->config['appid'];
$config_biz['mchid'] = $this->config['mch_id'];

unset($this->config['appid']);
unset($this->config['mch_id']);
unset($this->config['sign_type']);
unset($this->config['trade_type']);
unset($this->config['notify_url']);

$this->config = array_merge($this->config, $config_biz);

$this->config['sign'] = $this->getSign($this->config);

$data = $this->fromXml($this->post(
$this->endpoint.$this->gateway_transfer,
$this->toXml($this->config),
[
'cert' => $this->user_config->get('cert_client', ''),
'ssl_key' => $this->user_config->get('cert_key', ''),
]
));

if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS' || $data['result_code'] !== 'SUCCESS') {
$error = 'getResult error:'.$data['return_msg'];
$error .= isset($data['err_code_des']) ? ' - '.$data['err_code_des'] : '';
}

if (isset($error)) {
throw new GatewayException(
$error,
20000,
$data);
}

return $data;
}
}

+ 41
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/WapGateway.php View File

@@ -0,0 +1,41 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class WapGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'MWEB';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

$data = $this->preOrder($config_biz);

return is_null($this->user_config->get('return_url')) ? $data['mweb_url'] : $data['mweb_url'].
'&redirect_url='.urlencode($this->user_config->get('return_url'));
}
}

+ 69
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/WebGateway.php View File

@@ -0,0 +1,69 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Exceptions\InvalidArgumentException;

class WebGateway extends Wechat
{
/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function getTradeType()
{
return 'NATIVE';
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return string
*/
public function pay(array $config_biz = [])
{
if (is_null($this->user_config->get('app_id'))) {
throw new InvalidArgumentException('Missing Config -- [app_id]');
}

$code_url = $this->preOrder($config_biz)['code_url'];
$params = [
'body' => $config_biz['body'],
'code_url' => $code_url,
'out_trade_no' => $config_biz['out_trade_no'],
'return_url' => $this->user_config->get('return_url'),
'total_fee' => $config_biz['total_fee'],
];
$params['sign'] = md5(implode('', $params) . $this->user_config->get('app_id'));
$endpoint = addon_url("epay/api/wechat");

return $this->buildPayHtml($endpoint, $params);
}

/**
* build pay html.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
protected function buildPayHtml($endpoint, $params)
{
$sHtml = "<form id='alipaysubmit' name='wechatsubmit' action='" . $endpoint . "' method='POST'>";
foreach ($params as $key => $val) {
$val = str_replace("'", '&apos;', $val);
$sHtml .= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>";
}
$sHtml .= "<input type='submit' value='ok' style='display:none;'></form>";
$sHtml .= "<script>document.forms['wechatsubmit'].submit();</script>";

return $sHtml;
}
}

+ 354
- 0
addons/epay/library/Yansongda/Pay/Gateways/Wechat/Wechat.php View File

@@ -0,0 +1,354 @@
<?php

namespace Yansongda\Pay\Gateways\Wechat;

use Yansongda\Pay\Contracts\GatewayInterface;
use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidArgumentException;
use Yansongda\Pay\Support\Config;
use Yansongda\Pay\Traits\HasHttpRequest;

abstract class Wechat implements GatewayInterface
{
use HasHttpRequest;

/**
* @var string
*/
protected $endpoint = 'https://api.mch.weixin.qq.com/';

/**
* @var string
*/
protected $gateway_order = 'pay/unifiedorder';

/**
* @var string
*/
protected $gateway_query = 'pay/orderquery';

/**
* @var string
*/
protected $gateway_close = 'pay/closeorder';

/**
* @var string
*/
protected $gateway_refund = 'secapi/pay/refund';

/**
* @var array
*/
protected $config;

/**
* @var \Yansongda\Pay\Support\Config
*/
protected $user_config;

/**
* [__construct description].
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config
*/
public function __construct(array $config)
{
$this->user_config = new Config($config);

$this->config = [
'appid' => $this->user_config->get('app_id', ''),
'mch_id' => $this->user_config->get('mch_id', ''),
'nonce_str' => $this->createNonceStr(),
'sign_type' => 'MD5',
'notify_url' => $this->user_config->get('notify_url', ''),
'trade_type' => $this->getTradeType(),
];

if ($endpoint = $this->user_config->get('endpoint_url')) {
$this->endpoint = $endpoint;
}
}

/**
* pay a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return mixed
*/
abstract public function pay(array $config_biz = []);

/**
* refund.
*
* @author yansongda <me@yansongda.cn>
*
* @return string|bool
*/
public function refund($config_biz = [])
{
if (isset($config_biz['miniapp'])) {
$this->config['appid'] = $this->user_config->get('miniapp_id');
unset($config_biz['miniapp']);
}

$this->config = array_merge($this->config, $config_biz);

$this->unsetTradeTypeAndNotifyUrl();

return $this->getResult($this->gateway_refund, true);
}

/**
* close a order.
*
* @author yansongda <me@yansongda.cn>
*
* @return array|bool
*/
public function close($out_trade_no = '')
{
$this->config['out_trade_no'] = $out_trade_no;

$this->unsetTradeTypeAndNotifyUrl();

return $this->getResult($this->gateway_close);
}

/**
* find a order.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $out_trade_no
*
* @return array|bool
*/
public function find($out_trade_no = '')
{
$this->config['out_trade_no'] = $out_trade_no;

$this->unsetTradeTypeAndNotifyUrl();

return $this->getResult($this->gateway_query);
}

/**
* verify the notify.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $data
* @param string $sign
* @param bool $sync
*
* @return array|bool
*/
public function verify($data, $sign = null, $sync = false)
{
$data = $this->fromXml($data);

$sign = is_null($sign) ? $data['sign'] : $sign;

return $this->getSign($data) === $sign ? $data : false;
}

/**
* get trade type config.
*
* @author yansongda <me@yansongda.cn>
*
* @return string
*/
abstract protected function getTradeType();

/**
* pre order.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $config_biz
*
* @return array
*/
protected function preOrder($config_biz = [])
{
$this->config = array_merge($this->config, $config_biz);

return $this->getResult($this->gateway_order);
}

/**
* get api result.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $path
* @param bool $cert
*
* @return array
*/
protected function getResult($path, $cert = false)
{
$this->config['sign'] = $this->getSign($this->config);

if ($cert) {
$data = $this->fromXml($this->post(
$this->endpoint.$path,
$this->toXml($this->config),
[
'cert' => $this->user_config->get('cert_client', ''),
'ssl_key' => $this->user_config->get('cert_key', ''),
]
));
} else {
$data = $this->fromXml($this->post($this->endpoint.$path, $this->toXml($this->config)));
}

if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS' || $data['result_code'] !== 'SUCCESS') {
$error = 'getResult error:'.$data['return_msg'];
$error .= isset($data['err_code_des']) ? ' - '.$data['err_code_des'] : '';
}

if (!isset($error) && $this->getSign($data) !== $data['sign']) {
$error = 'getResult error: return data sign error';
}

if (isset($error)) {
throw new GatewayException(
$error,
20000,
$data);
}

return $data;
}

/**
* sign.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $data
*
* @return string
*/
protected function getSign($data)
{
if (is_null($this->user_config->get('key'))) {
throw new InvalidArgumentException('Missing Config -- [key]');
}

ksort($data);

$string = md5($this->getSignContent($data).'&key='.$this->user_config->get('key'));

return strtoupper($string);
}

/**
* get sign content.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $data
*
* @return string
*/
protected function getSignContent($data)
{
$buff = '';

foreach ($data as $k => $v) {
$buff .= ($k != 'sign' && $v != '' && !is_array($v)) ? $k.'='.$v.'&' : '';
}

return trim($buff, '&');
}

/**
* create random string.
*
* @author yansongda <me@yansongda.cn>
*
* @param int $length
*
* @return string
*/
protected function createNonceStr($length = 16)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}

return $str;
}

/**
* convert to xml.
*
* @author yansongda <me@yansongda.cn>
*
* @param array $data
*
* @return string
*/
protected function toXml($data)
{
if (!is_array($data) || count($data) <= 0) {
throw new InvalidArgumentException('convert to xml error!invalid array!');
}

$xml = '<xml>';
foreach ($data as $key => $val) {
$xml .= is_numeric($val) ? '<'.$key.'>'.$val.'</'.$key.'>' :
'<'.$key.'><![CDATA['.$val.']]></'.$key.'>';
}
$xml .= '</xml>';

return $xml;
}

/**
* convert to array.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $xml
*
* @return array
*/
protected function fromXml($xml)
{
if (!$xml) {
throw new InvalidArgumentException('convert to array error !invalid xml');
}

libxml_disable_entity_loader(true);

return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA), JSON_UNESCAPED_UNICODE), true);
}

/**
* delete trade_type and notify_url.
*
* @author yansongda <me@yansongda.cn>
*
* @return bool
*/
protected function unsetTradeTypeAndNotifyUrl()
{
unset($this->config['notify_url']);
unset($this->config['trade_type']);

return true;
}
}

+ 134
- 0
addons/epay/library/Yansongda/Pay/Pay.php View File

@@ -0,0 +1,134 @@
<?php

namespace Yansongda\Pay;

use Yansongda\Pay\Exceptions\InvalidArgumentException;
use Yansongda\Pay\Support\Config;

class Pay
{
/**
* @var \Yansongda\Pay\Support\Config
*/
private $config;

/**
* @var string
*/
private $drivers;

/**
* @var \Yansongda\Pay\Contracts\GatewayInterface
*/
private $gateways;

/**
* construct method.
*
* @author JasonYan <me@yansongda.cn>
*
* @param array $config
*/
public function __construct(array $config = [])
{
$this->config = new Config($config);
}

/**
* set pay's driver.
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $driver
*
* @return Pay
*/
public function driver($driver)
{
if (is_null($this->config->get($driver))) {
throw new InvalidArgumentException("Driver [$driver]'s Config is not defined.");
}

$this->drivers = $driver;

return $this;
}

/**
* set pay's gateway.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $gateway
*
* @return \Yansongda\Pay\Contracts\GatewayInterface
*/
public function gateway($gateway = 'web')
{
if (!isset($this->drivers)) {
throw new InvalidArgumentException('Driver is not defined.');
}

$this->gateways = $this->createGateway($gateway);

return $this->gateways;
}

/**
* create pay's gateway.
*
* @author yansongda <me@yansongda.cn>
*
* @param string $gateway
*
* @return \Yansongda\Pay\Contracts\GatewayInterface
*/
protected function createGateway($gateway)
{
if (!file_exists(__DIR__ . '/Gateways/' . ucfirst($this->drivers) . '/' . ucfirst($gateway) . 'Gateway.php')) {
throw new InvalidArgumentException("Gateway [$gateway] is not supported.");
}

$gateway = __NAMESPACE__ . '\\Gateways\\' . ucfirst($this->drivers) . '\\' . ucfirst($gateway) . 'Gateway';

return $this->build($gateway);
}

/**
* build pay's gateway.
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $gateway
*
* @return \Yansongda\Pay\Contracts\GatewayInterface
*/
protected function build($gateway)
{
return new $gateway($this->config->get($this->drivers));
}

public function verify()
{
if ($this->drivers == 'wechat') {
return $this->gateway()->verify(file_get_contents("php://input"));
} else {
$request = request();
$data = $request->get('app_id') && $request->get('out_trade_no') ? $request->get('', null, 'trim') : $request->post('', null, 'trim');
return $this->gateway()->verify($data);
}
}

public function success()
{
if ($this->drivers == 'wechat') {
echo '<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>';
} else {
echo 'success';
}
return;
}
}

+ 147
- 0
addons/epay/library/Yansongda/Pay/Support/Config.php View File

@@ -0,0 +1,147 @@
<?php

namespace Yansongda\Pay\Support;

use ArrayAccess;
use Yansongda\Pay\Exceptions\InvalidArgumentException;

class Config implements ArrayAccess
{
/**
* @var array
*/
protected $config;

/**
* Config constructor.
*
* @param array $config
*/
public function __construct(array $config = [])
{
$this->config = $config;
}

/**
* get a config.
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $key
* @param string $default
*
* @return mixed
*/
public function get($key = null, $default = null)
{
$config = $this->config;

if (is_null($key)) {
return $config;
}

if (isset($config[$key])) {
return $config[$key];
}

foreach (explode('.', $key) as $segment) {
if (!is_array($config) || !array_key_exists($segment, $config)) {
return $default;
}
$config = $config[$segment];
}

return $config;
}

/**
* set a config.
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $key
* @param array $value
*/
public function set(string $key, $value)
{
if ($key == '') {
throw new InvalidArgumentException('Invalid config key.');
}

// 只支持三维数组,多余无意义
$keys = explode('.', $key);
switch (count($keys)) {
case '1':
$this->config[$key] = $value;
break;
case '2':
$this->config[$keys[0]][$keys[1]] = $value;
break;
case '3':
$this->config[$keys[0]][$keys[1]][$keys[2]] = $value;
break;

default:
throw new InvalidArgumentException('Invalid config key.');
}

return $this->config;
}

/**
* [offsetExists description].
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $offset
*
* @return bool
*/
public function offsetExists($offset)
{
return array_key_exists($offset, $this->config);
}

/**
* [offsetGet description].
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $offset
*
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}

/**
* [offsetSet description].
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $offset
* @param string $value
*
* @return array
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}

/**
* [offsetUnset description].
*
* @author JasonYan <me@yansongda.cn>
*
* @param string $offset
*
* @return array
*/
public function offsetUnset($offset)
{
$this->set($offset, null);
}
}

+ 119
- 0
addons/epay/library/Yansongda/Pay/Traits/HasHttpRequest.php View File

@@ -0,0 +1,119 @@
<?php

/*
* (c) overtrue <i@overtrue.me>
*
* Modified By yansongda <me@yansongda.cn>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Yansongda\Pay\Traits;

use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;

trait HasHttpRequest
{
/**
* Make a get request.
*
* @param string $endpoint
* @param array $query
* @param array $headers
*
* @return array
*/
protected function get($endpoint, $query = [], $headers = [])
{
return $this->request('get', $endpoint, [
'headers' => $headers,
'query' => $query,
]);
}

/**
* Make a post request.
*
* @param string $endpoint
* @param mixed $params
* @param array $options
*
* @return string
*/
protected function post($endpoint, $params = [], ...$options)
{
$options = isset($options[0]) ? $options[0] : [];

if (!is_array($params)) {
$options['body'] = $params;
} else {
$options['form_params'] = $params;
}

return $this->request('post', $endpoint, $options);
}

/**
* Make a http request.
*
* @param string $method
* @param string $endpoint
* @param array $options http://docs.guzzlephp.org/en/latest/request-options.html
*
* @return array
*/
protected function request($method, $endpoint, $options = [])
{
return $this->unwrapResponse($this->getHttpClient($this->getBaseOptions())->{$method}($endpoint, $options));
}

/**
* Return base Guzzle options.
*
* @return array
*/
protected function getBaseOptions()
{
$options = [
'base_uri' => method_exists($this, 'getBaseUri') ? $this->getBaseUri() : '',
'timeout' => property_exists($this, 'timeout') ? $this->timeout : 5.0,
];

return $options;
}

/**
* Return http client.
*
* @param array $options
*
* @return \GuzzleHttp\Client
*/
protected function getHttpClient(array $options = [])
{
return new Client($options);
}

/**
* Convert response contents to json.
*
* @param \Psr\Http\Message\ResponseInterface $response
*
* @return array
*/
protected function unwrapResponse(ResponseInterface $response)
{
$contentType = $response->getHeaderLine('Content-Type');
$contents = $response->getBody()->getContents();

if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) {
return json_decode($contents, true);
} elseif (false !== stripos($contentType, 'xml')) {
return json_decode(json_encode(simplexml_load_string($contents)), true);
}

return $contents;
}
}

+ 86
- 0
addons/epay/view/api/wechat.html View File

@@ -0,0 +1,86 @@
<link rel="stylesheet" href="__ADDON__/css/wechat.css" />

{if $type=='jsapi'}
<div class="container">
<div class="row" style="margin-top:20px;">
<div class="col-xs-12">
<button type="button" class="btn btn-success btn-lg btn-block">正在发起微信支付</button>
<button type="button" class="btn btn-default btn-lg btn-block" onclick="location.href='{$orderData.returnurl}'">如果页面未自动跳转</button>
</div>
</div>
</div>
<script>
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {$payData|json_encode},
function(res){
if (res.err_msg == "get_brand_wcpay_request:ok") {
layer.msg('支付成功!');
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
layer.msg('您取消了支付');
} else if (res.err_msg == "get_brand_wcpay_request:fail") {
layer.msg('支付失败');
}
setTimeout(function () {
location.href = '{$orderData.returnurl}';
}, 1500);
});
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
</script>
{elseif $type=='pc' /}
<div class="container">
<div class="wechat">
<div class="row">
<div class="col-xs-12 col-sm-12">
<h2>
<img src="__ADDON__/images/logo-wechat.png" alt="" height="32" class="pull-left" style="margin-right:5px;"> 微信支付
<div class="wechat-time">
请在 <span>60</span> 秒内完成支付
</div>
</h2>

<div class="row">
<div class="col-xs-12 col-sm-5">
<div class="wechat-body">
<div class="wechat-order clearfix">
<p>订单标题:<em>{$data.body}</em></p>
<p>订单编号:<em>{$data.out_trade_no}</em></p>
<p>订单价格:<em class="wechat-price">¥{$data.total_fee/100}</em> 元</p>
</div>
<div class="wechat-qrcode">
<img src="{:addon_url('epay/api/qrcode',[],false)}?text={$data.code_url}">
<div class="expired hidden"></div>
<div class="paid hidden"></div>
</div>
<div class="wechat-tips">
<p>请使用微信扫一扫<br>扫描二维码支付</p>
</div>
</div>
</div>
<div class="col-sm-1"></div>
<div class="col-sm-6 hidden-xs">
<div class="wechat-scan">
<img src="__ADDON__/images/tips.png" class="img-responsive" alt=""/>
</div>
</div>
</div>
</div>
</div>
</div>

</div>

<script>
var queryParams = {$data|json_encode};
</script>
{/if}

+ 212
- 0
addons/epay/view/index/index.html View File

@@ -0,0 +1,212 @@
<!-- Header Carousel -->
<header id="myCarousel" class="carousel slide">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
<li data-target="#myCarousel" data-slide-to="3"></li>
</ol>

<!-- Wrapper for slides -->
<div class="carousel-inner">
<div class="item active">
<a href="https://www.fastadmin.net/store/epay.html" target="_blank">
<div class="fill"
style="background-image:url('https://bg.fastadmin.net?text=random&color=9b59b6');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">微信支付宝整合插件</h1>
<h2 class="display-4 text-white">打通微信、支付宝付款功能,支持CMS、余额充值、知识问答插件</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/cms.html" target="_blank">
<div class="fill"
style="background-image:url('https://bg.fastadmin.net?text=random&color=3498db');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">CMS内容管理系统(含小程序)</h1>
<h2 class="display-4 text-white">简单强大的内容管理系统,支持付费阅读、可自定义内容模型、标签、伪静态、区块、个性化模板等功能<br>包含完整的小程序CMS客户端,拥有完善的资讯模块、产品模块、评论模块、会员模块
</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/ask.html" target="_blank">
<div class="fill"
style="background-image:url('https://bg.fastadmin.net?text=random&color=3498db');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">知识问答系统</h1>
<h2 class="display-4 text-white">简单强大的问答社区,拥有强大的问答模块、付费问答、话题归类、付费阅读</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/blog.html" target="_blank">
<div class="fill"
style="background-image:url('https://bg.fastadmin.net?text=random&color=2ecc71');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">简单博客(含小程序)</h1>
<h2 class="display-4 text-white">响应式博客插件,包含日志、评论、分类、归档,包含完善的后台管理和前台功能<br/>包含完整的小程序博客客户端,拥有博客日志列表、日志详情、评论等功能
</h2>
</div>
</div>
</a>
</div>
<div class="item">
<a href="https://www.fastadmin.net/store/docs.html" target="_blank">
<div class="fill"
style="background-image:url('https://bg.fastadmin.net?text=random&color=9c88ff');"></div>
<div class="carousel-body">
<div class="container">
<h1 class="display-1 text-white">Markdown文档生成插件</h1>
<h2 class="display-4 text-white">将Github或本地Git环境中的Markdown文件解析并生成HTML,可在线浏览或导出为HTML离线浏览</h2>
</div>
</div>
</a>
</div>
</div>
</header>

<!-- Page Content -->
<div class="container">

<div class="row">
<div class="col-lg-12">
<h2 class="page-header">
开始接入
</h2>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-check"></i> 准备工作</h4>
</div>
<div class="panel-body">
<p><a href="https://b.alipay.com/" target="_blank">申请支付宝相应的支付产品,并获取相关配置</a></p>
<p><a href="https://pay.weixin.qq.com" target="_blank">申请微信相应的支付产品,并获取相关配置</a></p>
<p>插件管理中配置相应的微信或支付宝参数</p>
<a href="https://www.fastadmin.net/store/epay.html" target="_blank" class="btn btn-success"><i class="fa fa-download"></i> 下载插件</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-gift"></i> 开发工作</h4>
</div>
<div class="panel-body">
<p>在你的PHP代码中调用相关代码进行支付,请参考控制器代码</p>
<p>目前FastAdmin中已经支持
<a href="https://www.fastadmin.net/store/cms.html" target="_blank">CMS内容管理系统</a>、
<a href="https://www.fastadmin.net/store/recharge.html" target="_blank">会员充值插件</a>、
<a href="https://www.fastadmin.net/store/ask.html" target="_blank">知识问答系统</a>
支持无缝接入此插件</p>
<a href="https://www.fastadmin.net/store/epay.html" target="_blank" class="btn btn-success"><i class="fa fa-list"></i> 查看文档</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-fw fa-compass"></i> 立即体验</h4>
</div>
<div class="panel-body">
<p>请选择对应的支付金额和支付方式</p>
<p>
<span class="input-group">
<input type="number" name="amount" step="2" value="{:mt_rand(1, 99)/100}"
class="form-control" placeholder="请输入一个随机金额"/>
<span class="input-group-addon" style="padding:0;width:100px;">
<select class="form-control" name="method" id="method" style="border:none;height: 32px;">
<option value="web">PC网页支付</option>
<option value="wap">H5手机网页支付</option>
<option value="app">APP支付</option>
<option value="scan">扫码支付</option>
<option value="mp">公众号支付(不支持支付宝)</option>
<option value="miniapp">小程序支付(不支持支付宝)</option>
</select>
</span>
</span>
</p>
<button data-type="alipay" class="btn btn-info btn-experience"><i class="fa fa-money"></i> 支付宝支付</button>
<button data-type="wechat" class="btn btn-success btn-experience"><i class="fa fa-wechat"></i> 微信支付</button>
</div>
</div>
</div>
</div>
<!-- /.row -->

<div class="row addonlist">
<div class="col-lg-12">
<h2 class="page-header">模块&插件</h2>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/blog.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/blog.png"
alt="">
<p>简单博客(含小程序)</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/cms.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/cms.png"
alt="">
<p>CMS内容管理系统(含小程序)</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/ask.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/ask.png" alt="">
<p>知识付费问答社区</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/docs.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/docs.png"
alt="">
<p>文档生成模块</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/filemanager.html" target="_blank">
<img class="img-responsive img-addon img-hover"
src="https://cdn.fastadmin.net/uploads/addons/filemanager.png" alt="">
<p>文件管理器插件</p>
</a>
</div>
<div class="col-md-4 col-sm-6">
<a href="https://www.fastadmin.net/store/qiniu.html" target="_blank">
<img class="img-responsive img-addon img-hover" src="https://cdn.fastadmin.net/uploads/addons/qiniu.png"
alt="">
<p>七牛上传插件</p>
</a>
</div>
</div>
<!-- /.row -->

<hr>

<!-- Call to Action Section -->
<div class="well">
<div class="row">
<div class="col-md-8">
<p>感谢你对FastAdmin的支持!如果你在使用FastAdmin开发插件的过程中有任何疑问或需要寻求帮助,请前往FastAdmin交流社区与小伙伴们一起交流。</p>
</div>
<div class="col-md-4">
<a class="btn btn-lg btn-default btn-block" href="https://forum.fastadmin.net"
target="_blank">立即前往社区</a>
</div>
</div>
</div>

<hr>

</div>

+ 115
- 0
addons/epay/view/layout/default.html View File

@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">

<head>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">

<title>{$title} - FastAdmin</title>

<!-- Bootstrap Core CSS -->
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

<!-- Custom CSS -->
<link href="__ADDON__/css/common.css" rel="stylesheet">

<!-- Plugin CSS -->
<link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.org/simple-line-icons/2.4.1/css/simple-line-icons.min.css" rel="stylesheet">

<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->

</head>

<body>

<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{:addon_url('epay/index/index')}">FastAdmin</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
</li>
{if $user}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">欢迎你! {$user.nickname}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="{:url('index/user/index')}">会员中心</a>
</li>
<li>
<a href="{:url('index/user/profile')}">个人资料</a>
</li>
<li>
<a href="{:url('index/user/logout')}">退出登录</a>
</li>
</ul>
</li>
{else /}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">会员中心 <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="{:url('index/user/login')}">登录</a>
</li>
<li>
<a href="{:url('index/user/register')}">注册</a>
</li>
</ul>
</li>
{/if}
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>

{__CONTENT__}

<div class="container">
<!-- Footer -->
<footer>
<div class="row">
<div class="col-lg-12">
<hr>
<p>Copyright &copy; <a href="https://www.fastadmin.net">FastAdmin</a> 2017-1019</p>
</div>
</div>
</footer>

</div>
<!-- /.container -->

<!-- jQuery -->
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>

<!-- Bootstrap Core JavaScript -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

<script src="__CDN__/assets/libs/fastadmin-layer/dist/layer.js"></script>

<script src="__ADDON__/js/common.js"></script>

</body>

</html>

+ 308
- 0
addons/nzf/AliPay.php View File

@@ -0,0 +1,308 @@
<?php
/**
*
* ============================================================================
* * 版权�?�? 运游�? * *
* 网站地址: http://www.zhizhuchuxing.com
* ----------------------------------------------------------------------------
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改�?
* 使用;不允许对程序代码以任何形式任何目的的再发布�?
* ============================================================================
* Author By: 倪宗�?
* PhpStorm AliPayService.php
* Create By 2016/12/12 14:32 $
*/


namespace addons\nzf;



use addons\config\AliPayConfig;

class AliPay
{
private static $gatewayUrl = "https://openapi.alipay.com/gateway.do";
/**
* Des:扫描支付
* Name: unifiedOrderByOrderIdForSao
* @param $par
* @return array
* @author 倪宗锋
*/
public function unifiedOrderByOrderIdForSao($par)
{
$aliPay = new AliPay();
//交易参数
$params['body'] = $par['name'];
$params['subject'] = $par['name'];
$params['order_id'] = $par['order_id'];
$params['price'] = $par['total_fee'];
$params['timeout_express'] = '1m';
$params['goType'] = 3;
$params['method'] = 'alipay.trade.precreate';
$getUrl = $aliPay->getAliPayUrl($params);
$url = '/fx/?r=weChat/we-chat/q-code&qCode=' . urlencode($getUrl['data']['codUrl']) . '&_math=' . rand(100, 999);
return Util::returnArrSu('', array('codUrl' => $url, 'price' => $par['total_fee']));
}

/**
* Function Description:支付宝web支付
* Function Name: webPay
* @param $param array
* @return array
*
* @author nzf
*/
public function webPay($param)
{
//交易参数
$params['body'] = $param['name'];
$params['subject'] = $param['name'];
$params['order_id'] = $param['order_id'];
$params['price'] = $param['total_fee'];
$params['timeout_express'] = '1m';
$params['goType'] = 2;
$params['method'] = 'alipay.trade.wap.pay';
$return = static::getAliPayUrl($params);
return $return;
}

/********************通用方法**************************/
/**
* Function Description:获取阿里支付pay
* Function Name: getAliPayUrl
* @param $params array
*
* @return array
*
* @author 倪宗�?
*/
private static function getAliPayUrl($params)
{
$sysParams = self::getSysParams();
$sysParams["method"] = $params['method'];
//交易参数
$body['productCode'] = 'QUICK_WAP_PAY';
$body['body'] = $params['body'];
$body['subject'] = $params['subject'];
$body['out_trade_no'] = $params['order_id'];
$body['total_amount'] = $params['price'];
$body['timeout_express'] = "1m";

$sysParams['biz_content'] = json_encode($body);
if ($params['goType'] == 1) {//如果是页面跳�?
$sysParams['sign'] = urlencode(static::getSign($sysParams));
$paramString = static::getSignContent($sysParams);
$requestUrl = static::$gatewayUrl . "?" . $paramString;
return Util::returnArrSu('', ['payData' => $requestUrl]);
} elseif ($params['goType'] == 2) {//如果是参数返�?
$sysParams['sign'] = static::getSign($sysParams);
$result = self::buildRequestForm($sysParams);
return Util::returnArrSu('', ['payData' => $result]);
} else {
$sysParams['sign'] = urlencode(static::getSign($sysParams));
$paramString = static::getSignContent($sysParams);
$requestUrl = static::$gatewayUrl . "?" . $paramString;
$curl = new CurlInterface('', 5);
$result = $curl->execute($requestUrl, 'GET');
$result = json_decode($result, true);
$return['codUrl'] = '';
if ($result['alipay_trade_precreate_response']['code'] == '10000') {
$return['codUrl'] = $result['alipay_trade_precreate_response']['qr_code'];
}
return Util::returnArrSu('', $return);
}
}

/**
* Function Description:取消订单
* Function Name: cancelOrder
* @param $params
*
* @return array
*
* @author 倪宗�?
*/
public static function cancelOrder($params)
{
$sysParams = self::getSysParams();
$sysParams["method"] = 'alipay.trade.refund';
$body = array(
'out_trade_no' => $params['order_id'],//订单�?
'refund_amount' => $params['refund_fee'],//退款金额
'refund_reason' => $params['memo'],
'out_request_no' => $params['order_id'] . '-' . date('YmdHis') . rand(100, 999)//�?款原�?
);
unset($sysParams["notify_url"]);
unset($sysParams["return_url"]);
$sysParams['biz_content'] = json_encode($body);
$sysParams['sign'] = static::getSign($sysParams);
$sysParams['sign'] = urlencode(static::getSign($sysParams));
$paramString = static::getSignContent($sysParams);
$requestUrl = static::$gatewayUrl."?".$paramString;
//调用款接
$curlInterface = new CurlInterface($sysParams, 5);
$result = $curlInterface->execute($requestUrl, 'GET');
$result = json_decode(mb_convert_encoding($result, 'utf-8'), true);
if (isset($result['alipay_trade_refund_response']) && $result['alipay_trade_refund_response']['code'] == '10000') {
return Util::returnArrSu();
}
return Util::returnArrEr('退款失败!');
}

/**
* Function Description:获取系统通用参数
* Function Name: getSysParams
* @param $app_id string
* @param $order_id string
* @return mixed
*
* @author 倪宗�?
*/
private static function getSysParams()
{
//组装系统参数
$sysParams["app_id"] = AliPayConfig::getByName('ali_app_id');
$sysParams["version"] = '1.0';
$sysParams["format"] = 'json';
$sysParams["sign_type"] = 'RSA2';

$sysParams["timestamp"] = date("Y-m-d H:i:s");
$sysParams["alipay_sdk"] = 'alipay-sdk-php-20160411';
$sysParams["prod_code"] = '';
$sysParams["notify_url"] = AliPayConfig::getByName('ali_notify_url');
$sysParams["return_url"] = AliPayConfig::getByName('ali_return_url');
$sysParams["charset"] = "utf-8";
return $sysParams;
}

/**
* Function Description:建立请求,以表单HTML形式构�?�(默认�?
* Function Name: buildRequestForm
* @param $para_temp
*
* @return string 提交表单HTML文本
*
* @author 倪宗�?
*/
protected static function buildRequestForm($para_temp)
{
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='" . static::$gatewayUrl . "?charset=utf-8' method='get'>";
while (list ($key, $val) = each($para_temp)) {
if (false === static::checkEmpty($val)) {
$val = str_replace("'", "&apos;", $val);
$sHtml .= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>";
}
}
return $sHtml;
}

/**
* Function Description:获取签名
* Function Name: getSign
* @param $params
* @param $app_id
* @return string
*
* @author 倪宗�?
*/
public static function getSign($params)
{
if (isset($params['sign'])) {
unset($params['sign']);
}
$content = self::getSignContent($params);
$priKey = AliPayConfig::getByName('ali_private_key');
// $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
// wordwrap($priKey, 64, "\n", true) .
// "\n-----END RSA PRIVATE KEY-----";
// openssl_sign($content, $sign, $res);
// $sign = base64_encode($sign);
// return $sign;

$res = "-----BEGIN RSA PRIVATE KEY-----\n".
wordwrap($priKey, 64, "\n", true).
"\n-----END RSA PRIVATE KEY-----";

openssl_sign($content, $sign, $res, OPENSSL_ALGO_SHA256);

return base64_encode($sign);
}


/**
* Function Description:将数组转换为符合阿里支付的路由参�?
* Function Name: getSignContent
* @param $params
*
* @return string
*
* @author 倪宗�?
*/
public static function getSignContent($params)
{
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k => $v) {
if (false === self::checkEmpty($v) && "@" != substr($v, 0, 1)) {
// 转换成目标字符集
$v = self::characet($v, 'utf-8');

if ($i == 0) {
$stringToBeSigned.="$k"."="."$v";
} else {
$stringToBeSigned.="&"."$k"."=".$v;
}
$i++;
}
}
unset ($k, $v);
return $stringToBeSigned;
}

/**
* Function Description:校验$value是否非空
* Function Name: checkEmpty
* @param $value
*
* @return bool
*
* @author 倪宗�?
*/
private static function checkEmpty($value)
{
if (!isset($value)) {
return true;
}
if ($value === null) {
return true;
}
if (trim($value) === "") {
return true;
}
return false;
}

/**
* Function Description:转换字符集编�?
* Function Name: characet
* @param $data
* @param $targetCharset
*
* @return string
*
* @author 倪宗�?
*/
private static function characet($data, $targetCharset)
{
if (!empty($data)) {
$fileType = 'utf-8';
if (strcasecmp($fileType, $targetCharset) != 0) {
$data = mb_convert_encoding($data, $targetCharset);
}
}
return $data;
}
}

+ 466
- 0
addons/nzf/CurlInterface.php View File

@@ -0,0 +1,466 @@
<?php
/**
* 接口调用
* ============================================================================
* * 版权所有 蜘蛛行 * *
* 网站地址: http://www.zhizhuchuxing.com
* ----------------------------------------------------------------------------
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
* 使用;不允许对程序代码以任何形式任何目的的再发布。
* ============================================================================
* Author By: 倪宗锋
* PhpStorm CurlInterface.php
* Create By 2016/11/10 13:20 $
*/


namespace addons\nzf;
class CurlInterface
{
protected $url = null;
protected $verb = 'GET';
protected $body = '';
protected $requestLength = 0;
protected $baseUrl = null;
protected $timeOut = 200;
protected $clientId = 1;//站点类型 1 微信
protected $responseBody = null;//接收到的返回值
protected $notReturn = false; //是否有返回值
protected $siteConfig = null; //配置参数
protected $curlGetInfo = null;//交易概要
private $logMessage = ''; //日志内容
private $curlOptHeader = 0; //是否返回头部信息
private $bodyType = 1;
private $cert = false;//是否使用证书
private $certPem;
private $keyPem;

/****************============类的初始化=============*******************/

/**
* @param null $body 2:xml
* @param int $type 1:json 2:xml 3 发送原数据接收xml 4 发送原数据 接收json 5:都是原数据
*/
public function __construct($body = null, $type = 1)
{
$this->setBody($body, $type);
$this->setBaseUrl();
}

/*****************==========参数设置函数开始=========******************/
/**
* Function Description:设置是否返回头部信息
* Function Name: setCurlOptHeader
* @param $curlOptHeader
*
*
* @author 倪宗锋
*/
public function setCurlOptHeader($curlOptHeader)
{
$this->curlOptHeader = $curlOptHeader;
}

/**
* Function Description:获取交易概要
* Function Name: getCurlGetInfo
*
* @return null
*
* @author 倪宗锋
*/
public function getCurlGetInfo()
{
return $this->curlGetInfo;
}

/**
* Function Description:获取返回值报文
* Function Name: getResponseBody
*
* @return null
*
* @author 倪宗锋
*/
public function getResponseBody()
{
return $this->responseBody;
}

/**
* Function Description:获取全路径地址
* Function Name: getUrl
*
* @return null
*
* @author 倪宗锋
*/
public function getUrl()
{
return $this->url;
}

/**
* Function Description:设置路径 在baseUrl基础上
* Function Name: setUrl
* @param $url
*
*
* @author 倪宗锋
*/
public function setUrl($url)
{
$this->url = $this->baseUrl . $url;
}

/**
* Function Description:设置过期时间
* Function Name: setTimeOut
* @param $timeOut
*
*
* @author 倪宗锋
*/
public function setTimeOut($timeOut)
{
$this->timeOut = $timeOut;
}

/**
* Function Description:设置传值方式
* Function Name: setVerb
* @param $verb
*
*
* @author 倪宗锋
*/
public function setVerb($verb)
{
$this->verb = $verb;
}

/**
* Function Description:设置baseUrl
* Function Name: setBaseUrl
* @param $baseUrl string
*
* @author 倪宗锋
*/
public function setBaseUrl($baseUrl = '')
{
$this->baseUrl = $baseUrl;
}

/**
* Function Description:获取BaseUrl
* Function Name: getBaseUrl
*
* @return null
*
* @author 倪宗锋
*/
public function getBaseUrl()
{
return $this->baseUrl;
}

/**
* Function Description:设置是否有返回值
* Function Name: setNotReturn
* @param $str
*
*
* @author 倪宗锋
*/
public function setNotReturn($str)
{
$this->notReturn = $str;
}

/**
* Function Description:设置请求报文 $body 必须是个数组
* Function Name: setBody
* @param $body
* @param $type int 1:json 2:xml 3 发送原数据接收xml 4 发送原数据 接收json 5:都是原数据
*
* @author 倪宗锋
*/
public function setBody($body, $type = 1)
{
$this->body = '';
if (is_array($body)) {
if ($type == 1) {
$this->body = json_encode($body);
$this->requestLength = strlen($this->body);
} elseif ($type == 2) {
$this->body = '<?xml version="1.0" encoding="UTF-8"?>' . Util::arraysToXml(['response' => $body]);
$this->requestLength = strlen($this->body);
} elseif (in_array($type, array(3, 4, 5))) {
$this->body = $body;
}
} else {
$this->body = $body;
}
$this->bodyType = $type;
}

/**
* Function Description:设置ssl类型
* Function Name: setCert
* @param $certArr array
*
*
* @author 倪宗锋
*/
public function setCert($certArr)
{
$this->cert = true;
$this->certPem = $certArr['SSLCERT_PATH'];
$this->keyPem = $certArr['SSLKEY_PATH'];
}

/*****************==========参数设置函数结束=========******************/
/*****************==========调用接口并返回结果===开始======******************/

/**
* Function Description:执行交易
* Function Name: execute
* @param $url string sap地址
* @param $verb string 请求方式 post|get
* @return array
* @author nizongfeng
* Modify Date:2016.11.10
*/
public function execute($url, $verb = 'GET')
{
$url = preg_replace('# #','%20',$url);
$this->verb = $verb;
$this->url = $this->baseUrl . $url;

$this->logMessage .= date('Y-m-d H:i:s') . " Url : {$this->url}";
$this->logMessage .= ' Method:' . $this->verb . PHP_EOL;
if (is_array($this->body)) {
$this->logMessage .= "sendContent: " . json_encode($this->body) . PHP_EOL;
} else {
$this->logMessage .= "sendContent: {$this->body}" . PHP_EOL;
}

$ch = curl_init($this->url);
try {
switch (strtoupper($this->verb)) {
case 'GET':
$this->executeGet($ch);
break;
case 'POST':
$this->executePost($ch);
break;
case 'PUT':
$this->executePut($ch);
break;
case 'DELETE':
$this->executeDelete($ch);
break;
default:
$this->logMessage .= "current verb: {$this->verb}, is an invalid REST verb." . PHP_EOL;
break;
}
} catch (\Exception $e) {
$this->logMessage .= $e->getMessage() . PHP_EOL;
}
curl_close($ch);
$ch = null;
return $this->getResult();
}

/**
* Function Description:获取返回数据
* Function Name: getResult
*
* @return array|mixed
*
* @author nizongfeng
* Modify Date:2016.11.10
*/
public function getResult()
{
if (in_array($this->bodyType, array(1, 4))) {
$return = json_decode($this->responseBody, true);
} elseif (in_array($this->bodyType, array(2, 3))) {
$return = Util::xmlToArray($this->responseBody);
} elseif ($this->bodyType == 5) {
$return = $this->responseBody;
} else {
$return = '';
}
//file_put_contents(APP_PATH . '/runtime/curl/' . date('Y-m-d') . '.log', $this->logMessage . PHP_EOL, FILE_APPEND);
return $return;
}

/*******************=====GET传值=====********************/
/**
* Function Description:GET传值
* Function Name: executeGet
* @param $ch
*
* @return void
*
* @author nizongfeng 2016.11.10
*/
protected function executeGet($ch)
{
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$this->doExecute($ch);
}

/*******************=====POST传值=====********************/
/**
* Function Description:POST传值
* Function Name: executePost
* @param $ch
*
* @return void
*
* @author nizongfeng 2016.11.10
*/
protected function executePost($ch)
{
// curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_POST, true);
if (is_array($this->body)) {
$cnt = $this->getmaxdim($this->body);
if ($cnt > 1) {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($this->body));
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
}
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$this->doExecute($ch);
}

/*******************=====PUT传值=====********************/
/**
* Function Description:PUT传值
* Function Name: executePut
* @param $ch
*
*
* @author 倪宗锋
*/
protected function executePut($ch)
{
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
$this->doExecute($ch);
}

/*******************=====DELETE传值=====********************/
/**
* Function Description:DELETE传值
* Function Name: executeDelete
* @param $ch
*
*
* @author 倪宗锋
*/
protected function executeDelete($ch)
{
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->body);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
$this->doExecute($ch);
}

/*******************=====传值及接收=====********************/
/**
* Function Description: 传值及接受数据
* Function Name: doExecute
* @param $curlHandle
*
* @return void
*
* @author nizongfeng 2015.12.08
*/
protected function doExecute(&$curlHandle)
{

if ($this->verb != 'get') {
$this->setCurlOpts($curlHandle);
}
curl_setopt($curlHandle, CURLOPT_HEADER, $this->curlOptHeader);
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curlHandle, CURLOPT_TIMEOUT, $this->timeOut);

//记录报文发送时间
$sendTime = microtime(true);
$this->responseBody = curl_exec($curlHandle);
//记录报文返回时间
$responseTime = microtime(true);
$timeIncrement = round(floatval($responseTime - $sendTime), 3);
//记录返回的报文信息
$this->logMessage .= "response: {$this->responseBody}" . PHP_EOL;
$curlInfo = curl_getinfo($curlHandle);
$this->curlGetInfo = $curlInfo;
if (empty($curlInfo['primary_port'])) {
$curlInfo['primary_port'] = '';
}
$curlInfoStr = '';
if (isset($_SERVER['SERVER_ADDR']) && $_SERVER['SERVER_PORT']) {
$curlInfoStr = " toIP {$curlInfo['primary_ip']}:{$curlInfo['primary_port']}";
$curlInfoStr .= " selfIP {$_SERVER['SERVER_ADDR']} {$_SERVER['SERVER_PORT']}";
}
//记录通信信息及性能指标
$this->logMessage .= "Info: " . json_encode($curlInfoStr) . PHP_EOL;
$this->logMessage .= "sendTime: " . date('H:i:s', $sendTime) . " , responseTime: ";
$this->logMessage .= date('H:i:s', $responseTime) . " , timeIncrement:" . $timeIncrement . 's'
. PHP_EOL;
$curlError = curl_error($curlHandle);
if ($curlError) {
$this->logMessage .= "Error: " . $curlError . PHP_EOL;
}
}

/*******************=====头部设置=====********************/
/**
* Function Description:头部设置
* Function Name: setCurlOpts
* @param $curlHandle
*
*
* @author 倪宗锋
*/
protected function setCurlOpts(&$curlHandle)
{
if ($this->cert == 1) {
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
curl_setopt($curlHandle, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curlHandle, CURLOPT_SSLCERT, $this->certPem);
curl_setopt($curlHandle, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curlHandle, CURLOPT_SSLKEY, $this->keyPem);
}

}
/*****************==========调用接口并返回结果===结束======******************/
//获取数组是几维数组
private function getmaxdim($vDim)
{
if (!is_array($vDim)) return 0;
else {
$max1 = 0;
foreach ($vDim as $item1) {
$t1 = $this->getmaxdim($item1);
if ($t1 > $max1) $max1 = $t1;
}
return $max1 + 1;
}
}

}

?>

+ 98
- 0
addons/nzf/PayService.php View File

@@ -0,0 +1,98 @@
<?php
/**
*
* ============================================================================
* * 版权所有 蜘蛛出行 * *
* 网站地址: http://www.zhizhuchuxing.com
* ----------------------------------------------------------------------------
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
* 使用;不允许对程序代码以任何形式任何目的的再发布。
* ============================================================================
* Author By: 倪宗锋
* PhpStorm PayService.php
* Create By 2017/3/3 19:53 $
*/

namespace addons\nzf;

class PayService
{
/**
* Des:扫码支付
* Name: sao
* @param $params array order_id:订单ID name:订单名称 total_fee:总金额-元
* @param int $type 3、微信4、支付宝
* @return array
* @author 倪宗锋
*/
public static function sao($params, $type = 1)
{
if ($type == 3) {
$pay = new WeChatPay();//微信支付类
} else {
$pay = new AliPay();//支付宝支付类
}
$return = $pay->unifiedOrderByOrderIdForSao($params);
return $return;
}

/**
* Des:取消订单
* Name: cancel
* @param $params array order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额
* @param int $type 3、微信 4、支付宝
* @return array
* @author 倪宗锋
*/
public static function cancel($params, $type)
{
if ($type == 3) {//微信支付
$pay = new WeChatPay();
$return = $pay->cancelOrder($params);
} else {//阿里支付
$pay = new AliPay();
$return = $pay->cancelOrder($params);
}
return $return;
}

/**
* Des: 直接付款
* Name: pay
* @param $params array
* $order_id string 订单表 订单ID
* $name string 产品名称
* $total_fee int 总金额 单位元
* $openid string 用户opendid
* @param $type 1微信 2支付宝
*
* @return array
* @author 倪宗锋
*/
public static function pay($params,$type = 1)
{
if($type == 1) {
$pay = new WeChatPay();//微信支付类
}else {
$pay = new AliPay();//支付宝支付类
}
$return = $pay->webPay($params);
return $return['data']['payData'];
}


/**
* Des: 支付 目前只支持微信直接支付
* Name: pay
* @param $orderId string 订单ID
*
* @return array
* @author 倪宗锋
*/
public static function checkIsPay($orderId)
{
$pay = new WeChatPay();
$return = $pay->checkIsPay($orderId);
return $return;
}
}

+ 343
- 0
addons/nzf/Util.php View File

@@ -0,0 +1,343 @@
<?php
/**
* 全局通用方法集合
* ============================================================================
* * 版权所有 蜘蛛出行 * *
* 网站地址: http://www.zhizhuchuxing.com
* ----------------------------------------------------------------------------
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
* 使用;不允许对程序代码以任何形式任何目的的再发布。
* ============================================================================
* Author By: 倪宗锋
* PhpStorm Util.php
* Create By 2017/2/22 19:44 $
*/

namespace addons\nzf;

class Util
{

/**
* Function Description:返回成功Json数据到
* Function Name: returnSu
* @param string $msg 提示信息
* @param string $url 跳转地址
* @param string|array $data 需要传递的数据
* @param string $code 错误码
*
* @return string
*
* @author 倪宗锋
*/
public static function returnJsSu($msg = '', $data = '', $url = '', $code = '')
{
$return = array();
$return['flag'] = true;
$return['msg'] = $msg;
$return['url'] = $url;
$return['code'] = $code;
$return['data'] = $data;
return json_encode($return);
}

/**
* Function Description:返回成功Json数据
* Function Name: returnEr
* @param string $msg 提示信息
* @param string $url 跳转地址
* @param string|array $data 需要传递的数据
* @param string $code 错误码
*
* @return string
*
* @author 倪宗锋
*/
public static function returnJsEr($msg = '', $data = '', $url = '', $code = '')
{
$return = array();
$return['flag'] = false;
$return['msg'] = $msg;
$return['url'] = $url;
$return['code'] = $code;
$return['data'] = $data;
return json_encode($return);
}

/**
* Function Description:返回成功数组数据
* Function Name: returnArrSu
* @param string $msg 提示信息
* @param string $url 跳转地址
* @param string|array $data 需要传递的数据
* @param string $code 错误码
*
* @return array
*
* @author 倪宗锋
*/
public static function returnArrSu($msg = '', $data = '', $url = '', $code = '')
{
$return = array();
$return['flag'] = true;
$return['msg'] = $msg;
$return['url'] = $url;
$return['code'] = $code;
$return['data'] = $data;
return $return;
}

/**
* Function Description:返回错误数组数据
* Function Name: returnArrEr
* @param string $msg 提示信息
* @param string $url 跳转地址
* @param string|array $data 需要传递的数据
* @param string $code 错误码
*
* @return array
*
* @author 倪宗锋
*/
public static function returnArrEr($msg = '', $data = '', $url = '', $code = '')
{
$return = array();
$return['flag'] = false;
$return['msg'] = $msg;
$return['url'] = $url;
$return['code'] = $code;
$return['data'] = $data;
return $return;
}



/**
* Function Description:json转换为xml
* Function Name: jsonToXml
* @param $json
*
* @return bool|string
*
* @author 倪宗锋
*/
public static function jsonToXml($json)
{
if (empty($json)) {
return false;
}
$array = json_decode($json);
$xml = '';
$xml .= '<?xml version="1.0" encoding="UTF-8"?>' . self::arraysToXml(['response' => $array]);
return $xml;
}


/**
* Function Description:数组转换成xml
* Function Name: arrayToXml
* @param $array
* @param $key
* @return string
*
* @author 倪宗锋
*/
public static function arraysToXml($array, $key = '')
{
$string = '';
if (count($array) == 0) {
return '';
}
foreach ($array as $k => $v) {
if (is_array($v) && isset($v['0'])) {
$string .= self::arraysToXml($v, $k);//是数组或者对像就的递归调用
} else {
if ($key != '') {
$k = $key;
}
$string .= '<' . $k . '>';
if (is_array($v) || is_object($v)) {//判断是否是数组,或者,对像
$string .= self::arraysToXml($v);//是数组或者对像就的递归调用
} elseif (is_numeric($v)) {
$string .= $v;
} elseif ($v != '') {
$string .= '<![CDATA[' . $v . ']]>';
} else {
$string .= '';
}
$string .= '</' . $k . '>';
}
}
return $string;
}

/**
* Function Description:xml转换为json
* Function Name: xml_to_json
* @param $source
*
* @return string
*
* @author 倪宗锋
*/
public static function xmlToJson($source)
{
if (is_file($source)) { //传的是文件,还是xml的string的判断
$xml_array = simplexml_load_file($source);
} else {
$xml_array = simplexml_load_string(trim($source));
}
$json = json_encode($xml_array, true);
return $json;
}

/**
* Function Description:xml转换成数组
* Function Name: xmlToArray
* @param $source
*
* @return mixed
*
* @author 倪宗锋
*/
public static function xmlToArray($source)
{
libxml_disable_entity_loader(true);
$getResult = json_decode(json_encode(simplexml_load_string(trim($source), 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $getResult;
}

/** Function Description:加密解密函数
* Function Name: authCode
* @param $string
* @param string $operation
* @param int $expiry
* @return string|array
* @author 倪宗锋
*/
static function authCode($string, $operation = 'DECODE', $expiry = 0)
{
$key = 'udM5A8S50eg8veH15dd0m601de7073N8Bcn7d1I8Res7C7o7z274D6y342I4C7t7';
$ckey_length = 4; // 随机密钥长度 取值 0-32;
// 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
// 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
// 当此值为 0 时,则不产生随机密钥

$key = md5($key);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

$cryptkey = $keya . md5($keya . $keyc);
$key_length = strlen($cryptkey);

$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
$string_length = strlen($string);

$result = '';
$box = range(0, 255);

$rndkey = array();
for ($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}

for ($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}

for ($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}

if ($operation == 'DECODE') {
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc . str_replace('=', '', base64_encode($result));
}

}



/**
* 获取客户端IP地址
* @return mixed
*/
public static function getclientip()
{
static $realip = NULL;

if ($realip !== NULL) {
return $realip;
}
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { //但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取。
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
/* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
foreach ($arr AS $ip) {
$ip = trim($ip);
if ($ip != 'unknown') {
$realip = $ip;
break;
}
}
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是"超级匿名代理",则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$realip = $_SERVER['HTTP_CLIENT_IP'];
} else {
if (isset($_SERVER['REMOTE_ADDR'])) { //正在浏览当前页面用户的 IP 地址
$realip = $_SERVER['REMOTE_ADDR'];
} else {
$realip = '0.0.0.0';
}
}
} else {
//getenv环境变量的值
if (getenv('HTTP_X_FORWARDED_FOR')) {//但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的 IP 地址,而不是真正的客户端 IP 地址。要想透过代理服务器取得客户端的真实 IP 地址
$realip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('HTTP_CLIENT_IP')) { //获取客户端IP
$realip = getenv('HTTP_CLIENT_IP');
} else {
$realip = getenv('REMOTE_ADDR'); //正在浏览当前页面用户的 IP 地址
}
}
preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
$realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';
return $realip;
}

/**
* Des:获取浏览器机器类型
* Name: get_device_type
* @return string
* @author 倪宗锋
*/
public static function get_device_type()
{
//全部变成小写字母
$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
$type = 'other';
//分别进行判断
if (strpos($agent, 'iphone') || strpos($agent, 'ipad')) {
$type = 'ios';
}

if (strpos($agent, 'android')) {
$type = 'android';
}
return $type;
}

}

+ 337
- 0
addons/nzf/WeChatPay.php View File

@@ -0,0 +1,337 @@
<?php

namespace addons\nzf;

use addons\unishop\model\Config;

/**
* Class WxPayService
* 微信交易接口调用核心
* @package Base\Tool
*/
class WeChatPay
{
public $unifiedOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//统一下单API
/************************手机浏览器内web支付**************************************/
/**
*
*/
public function H5Pay($params)
{
if (empty($params['notify_url'])) {
$params['notify_url'] = Config::getByName('notify_url')['value'];
}
$data = array(
'name' => $params['name'],//名称
'order_id' => (string)$params['order_id'] . '_' . rand(1000, 9999),//支付ID
'total_fee' => (string)$params['total_fee'] * 100,//总金
'notify_url' => $params['notify_url'],//支付回调接口
'trade_type' => 'MWEB',//用户的OPENID
'scene_info' => [
'h5_info' => [
'type' => 'Wap',
'wap_url' => Config::getByName('name')['value'],
'wap_name' => Config::getByName('name')['value']
]
]
);
$getpay = $this->unifiedOrderForWeChat($data);//统一下单API
if ($getpay['flag'] == false) {
return $getpay;
}
if (empty($getpay['data']['mweb_url'])) {
return Util::returnArrEr('预支付会话异常!');
}
return Util::returnArrSu('', ['pay_url' => $getpay['data']['mweb_url']]);
}
/************************微信浏览器内web支付**************************************/
/**
* Function Description:去微信下单并获取返回
* Function Name: unifiedOrderByOrderId
* @param $params array
* $order_id string 订单表 订单ID
* $name string 产品名称
* $total_fee int 总金额 单位分
* $openid string 用户opendid
* @return array
*
* @author nzf
*/
public function webPay($params)
{
if (empty($params['notify_url'])) {
$params['notify_url'] = Config::getByName('notify_url')['value'];;
}
$data = array(
'name' => $params['name'],//名称
'order_id' => (string)$params['order_id'] . '_' . rand(1000, 9999),//支付ID
'total_fee' => (string)$params['total_fee'] * 100,//总金
'notify_url' => $params['notify_url'],//支付回调接口
'openid' => $params['openid']//用户的OPENID
);
$getPrepayId = $this->unifiedOrderForWeChat($data);//统一下单API
if ($getPrepayId['flag'] == false) {
return $getPrepayId;
}
//设置成功返回的结果数
$return = array(
'appId' => Config::getByName('app_id')['value'],//微信�?放平台审核�?�过的应用APPID
'package' => 'prepay_id=' . $getPrepayId['data']['prepay_id'],//微信返回的支付交易会话ID
'nonceStr' => self::getNonceStr(),//随机字符�?
'signType' => 'MD5',
'timeStamp' => strval(time()),//当前时间�?
);
$return['paySign'] = self::getSign($return);
return Util::returnArrSu('', array('payData' => $return, 'price' => $params['total_fee']));
}

/**
* Function Description:统一下单API
* Function Name: unifiedOrder
* @param $params array
* attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数
* line_name 线路名称
* order_id 订单ID
* total_fee 总金
* notify_url 回调地址
*
* @return array
*
* @author nzf
*/
public function unifiedOrderForWeChat($params)
{
$data = array(
'appid' => Config::getByName('app_id')['value'],//微信开放平台审核过的应用APPID
'attach' => empty($params['attach']) ? '' : $params['attach'],
'body' => $params['name'],//产品名称
'mch_id' => Config::getByName('mch_id')['value'],//商户微信支付分配的商户号
'nonce_str' => $this->getNonceStr(),//随机字符
'notify_url' => $params['notify_url'],//通知地址
'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip
'total_fee' => $params['total_fee'],//订单总金额,单位为分
'trade_type' => empty($params['trade_type']) ? 'JSAPI' : $params['trade_type'],//交易类型
);
if (empty($params['openid']) == false) {//存在openid
$data['openid'] = $params['openid'];
}
if (isset($params['scene_info'])) {
$data['scene_info'] = json_encode($params['scene_info']);
}
$data['sign'] = $this->getSign($data);//交易签名
$curl = new CurlInterface($data, 2);//函数
$curl->setBaseUrl($this->unifiedOrderUrl);
$result = $curl->execute('', 'POST');
if (empty($result['prepay_id'])) {
return Util::returnArrEr('预支付交易会话异常!');
}
return Util::returnArrSu('', array('prepay_id' => $result['prepay_id'], 'mweb_url' => empty($result['mweb_url']) ? '' : $result['mweb_url']));
}
/************************扫描支付**************************************/

/**
* Function Description:去微信下单并获取返回
* Function Name: unifiedOrderByOrderId
* @param $par
* @return array
*
* @author nzf
*/
public function unifiedOrderByOrderIdForSao($par)
{
$notify_url = Config::getByName('notify_url')['value'];
$data = array(
'name' => $par['name'],//线路名称
'order_id' => (string)$par['order_id'] . '_' . rand(100, 999),//订单ID
'total_fee' => $par['total_fee'] * 100,//总金
'notify_url' => $notify_url
);
$codUrl = $this->unifiedOrderForSao($data);//统一下单API
if ($codUrl['flag'] == false) {
return $codUrl;
}
//设置成功返回的结果数�?
$url = '/fx/?r=weChat/we-chat/q-code&qCode=' . urlencode($codUrl['data']['code_url']) . '&_math=' . rand(100, 999);
return Util::returnArrSu('', array('codUrl' => $url, 'price' => $par['total_fee']));
}

/**
* Function Description:统一下单API
* Function Name: unifiedOrder
* @param $params array
* attach 附加数据,在查询API和支付知中原样返回,该字段主要用于商户携带订单的自定义数
* line_name 线路名称
* order_id 订单ID
* total_fee 总金
* notify_url 回调地址
*
* @return array
*
* @author 倪宗�?
*/
public function unifiedOrderForSao($params)
{
$data = array(
'appid' => Config::getByName('app_id')['value'],//微信�?放平台审核�?�过的应用APPID
'mch_id' => Config::getByName('mch_id')['value'],//商户�? 微信支付分配的商户号
'nonce_str' => $this->getNonceStr(),//随机字符�?
'body' => $params['name'],//线路名称 �? 上订单ID
'out_trade_no' => $params['order_id'],//商户订单ID加上当前时间
'total_fee' => $params['total_fee'],//订单总金额,单位为分
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],//用户端实际ip
'notify_url' => $params['notify_url'],//通知地址
'trade_type' => 'NATIVE',//交易类型
);
$data['sign'] = $this->getSign($data);//交易签名
$curl = new CurlInterface($data, 2);//函数�?
$curl->setBaseUrl($this->unifiedOrderUrl);
$result = $curl->execute('', 'POST');
if (empty($result['prepay_id'])) {
return Util::returnArrEr('预支付交易会话异常!');
}
return Util::returnArrSu('', array('prepay_id' => $result['prepay_id'], 'code_url' => $result['code_url']));
}

/***************************************退款****************************************/

/**
* Des:微信退款接口
* Name: cancelOrder
* @param $params
* @return array
* @author 倪宗锋
*/
public static function cancelOrder($params)
{
$arr = array(
'appid' => Config::getByName('app_id')['value'],
'mch_id' => Config::getByName('mch_id')['value'],
'nonce_str' => static::getNonceStr(),
'out_trade_no' => (string)$params['order_id'],//订单ID
'out_refund_no' => (string)date('YmdHis') . rand(100, 999),//退款ID
'total_fee' => (string)$params['total_fee'] * 100,//订单总金额 元
'refund_fee' => (string)$params['refund_fee'] * 100,//退款金额 元
'op_user_id' => Config::getByName('mch_id')['value']
);
$arr['sign'] = static::getSign($arr);
$curl = new CurlInterface($arr, 2);//函数类
$certArr = [
"SSLCERT_PATH"=>ROOT_PATH.Config::getByName('cert_path')['value'],
"SSLKEY_PATH"=>ROOT_PATH.Config::getByName('key_path')['value']
];
$curl->setCert($certArr);
$curl->setBaseUrl('https://api.mch.weixin.qq.com/secapi/pay/refund');
$result = $curl->execute('', 'POST');
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
return Util::returnArrSu();
}
$msg = $result['return_msg'];
if ($msg == 'OK') {
$msg = $result['err_code_des'];
}
return Util::returnArrEr('退款失败!' . $msg);

}

/*************************************通用方法**************************************/
/**
* Des:检测是否已经支付
* Name: checkIsPay
* @param $orderId
* @return array
* @author 倪宗锋
*/
public static function checkIsPay($orderId)
{
$arr = array(
'appid' => Config::getByName('app_id')['value'],
'mch_id' => Config::getByName('mch_id')['value'],
'out_trade_no' => (string)$orderId,//订单ID
'nonce_str' => static::getNonceStr(),
);
$arr['sign'] = static::getSign($arr);
$curl = new CurlInterface($arr, 2);//函数类
$certArr = [
"SSLCERT_PATH"=>ROOT_PATH.Config::getByName('cert_path')['value'],
"SSLKEY_PATH"=>ROOT_PATH.Config::getByName('key_path')['value']
];
$curl->setCert($certArr);
$curl->setBaseUrl('https://api.mch.weixin.qq.com/pay/orderquery');
$result = $curl->execute('', 'POST');
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
return Util::returnArrSu('', $result);
}
$msg = $result['return_msg'];
if ($msg == 'OK') {
$msg = $result['err_code_des'];
}
return Util::returnArrEr('退款失败!' . $msg);
}

/**
* Function Description:获取签名
* Function Name: getSign
* @param $params
* @return string
*
* @author nzf
*/
public static function getSign($params)
{
if (isset($params['sign'])) {
unset($params['sign']);
}
//签名步骤按字典序排序参
ksort($params);
$string = self::ToUrlParams($params);
//签名步骤二:在string后加入KEY
$string = $string . "&key=" . Config::getByName('key')['value'];
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:有字符转为大
$result = strtoupper($string);
return $result;

}

/**
* Function Description:格式化参�? 格式化成url参数
* Function Name: ToUrlParams
* @param $params
*
* @return string
*
* @author 倪宗�?
*/
public static function ToUrlParams($params)
{
$buff = "";
foreach ($params as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}

/**
* Function Description:产生的随机字符串 不长
* Function Name: getNonceStr
* @param int $length
*
* @return string
*
* @author 倪宗�?
*/
public static function getNonceStr($length = 32)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
}

+ 92
- 0
addons/unishop/application/admin/controller/unishop/Order.php View File

@@ -506,4 +506,96 @@ class Order extends Backend
}
return $this->view->fetch();
}

public function export(){
$order_model=New \app\admin\model\unishop\Order();
$list = $order_model
->alias('o')
->join('user', 'user.id = o.user_id')
->join('unishop_order_product', 'unishop_order_product.order_id = o.id')
->where(['o.have_received'=>[">",0]])
->field('
user.username,
user.nickname,
user.floor,
user.email,
GROUP_CONCAT(unishop_order_product.title) as title,
o.total_price,
o.refund_fee,
SUM(unishop_order_product.number) as number,
o.remark')
->group("o.id")
->select();
$list = collection($list)->toArray();
$title = ['工号','姓名','楼层','邮箱','商品','支付金额','退款金额','购买数量','备注'];
// Create new Spreadsheet object
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle("订单信息");
// 方法一,使用 setCellValueByColumnAndRow
//表头
//设置单元格内容
foreach ($title as $key => $value) {
// 单元格内容写入
$sheet->setCellValueByColumnAndRow($key + 1, 1, $value);
}
$row = 2; // 从第二行开始
foreach ($list as $item) {
$column = 1;
foreach ($item as $value) {
// 单元格内容写入
$sheet->setCellValueByColumnAndRow($column, $row, $value);
$column++;
}
$row++;
}
$sheet_two = $spreadsheet->createSheet(2)->setTitle('商品信息');
$title1=["商品名称","件数","单价","总价"];
$product=new \app\admin\model\unishop\OrderProduct();
$product_list = $product->alias("p")
->join("unishop_order","p.order_id = unishop_order.id")
->where(['unishop_order.have_received'=>[">",0]])
->field('
p.title,
SUM(p.number) num,
p.price,
SUM(p.number)*p.price')
->group("p.id")
->select();
$product_list = collection($product_list)->toArray();

foreach ($title1 as $key => $value) {
// 单元格内容写入
$sheet_two->setCellValueByColumnAndRow($key + 1, 1, $value);
}
$row=2;
foreach ($product_list as $item) {
$column = 1;
foreach ($item as $value) {
// 单元格内容写入
$sheet_two->setCellValueByColumnAndRow($column, $row, $value);
$column++;
}
$row++;
}

$file_name="导出订单.xlsx";
// Redirect output to a client’s web browser (Xlsx)
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename='.$file_name);
header('Cache-Control: max-age=0');
// If you're serving to IE 9, then the following may be needed
header('Cache-Control: max-age=1');

// If you're serving to IE over SSL, then the following may be needed
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
header('Pragma: public'); // HTTP/1.0

$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('php://output');
exit;
}

}

+ 1
- 1
addons/unishop/application/admin/controller/unishop/Product.php View File

@@ -20,7 +20,7 @@ class Product extends Backend
* 快速搜索时执行查找的字段
*/
protected $searchFields = 'title';
protected $noNeedLogin = ["select"];
/**
* Multi方法可批量修改的字段
*/


+ 3
- 1
addons/unishop/application/admin/view/unishop/order/index.html View File

@@ -30,7 +30,9 @@
</ul>
</div>

<a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('unishop/order/recyclebin')?'':'hide'}" href="unishop/order/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
<!-- <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('unishop/order/recyclebin')?'':'hide'}" href="unishop/order/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>-->
<!-- <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('unishop/order/recyclebin')?'':'hide'}" href="unishop/order/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>-->
<!-- <a class="btn btn-success btn-recyclebin btn-dialog {:$auth->check('unishop/order/recyclebin')?'':'hide'}" href="unishop/order/export" title="{:__('导出')}"><i class="fa fa-recycle"></i> {:__('导出')}</a>-->
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('unishop/order/edit')}"


+ 39
- 14
addons/unishop/behavior/Order.php View File

@@ -2,6 +2,7 @@

namespace addons\unishop\behavior;

use addons\epay\library\Service;
use addons\unishop\extend\Ali;
use addons\unishop\extend\Hashids;
use addons\unishop\extend\Wechat;
@@ -172,20 +173,21 @@ class Order
$orderPrice = bcadd($orderPrice, bcmul($productInfo['sales_price'], $numbers[$key], 2), 2);
$baseProductInfo[] = $productInfo;
}
$delivery=0;
// 条件三
$delivery = (new DeliveryRuleModel())->cityInScopeOfDelivery($extra['city_id'], $extra['delivery_id']);
if (!$delivery) {
throw new Exception(__('Your receiving address is not within the scope of delivery'));
} else {
if ($delivery['min'] > array_sum($numbers)) {
throw new Exception(__('You must purchase at least %s item to use this shipping method', $delivery['min']));
}
}
$address = (new Address)->where(['id' => $extra['address_id'], 'user_id' => $extra['userId']])->find();
if (!$address) {
throw new Exception(__('Address not exist'));
}
// $delivery = (new DeliveryRuleModel())->cityInScopeOfDelivery($extra['city_id'], $extra['delivery_id']);
// if (!$delivery) {
// throw new Exception(__('Your receiving address is not within the scope of delivery'));
// } else {
// if ($delivery['min'] > array_sum($numbers)) {
// throw new Exception(__('You must purchase at least %s item to use this shipping method', $delivery['min']));
// }
// }
$address=[];
// $address = (new Address)->where(['id' => $extra['address_id'], 'user_id' => $extra['userId']])->find();
// if (!$address) {
// throw new Exception(__('Address not exist'));
// }

// 条件四
if ($extra['coupon_id']) {
@@ -218,6 +220,8 @@ class Order
{
$order = &$params;
$order->have_paid = time();// 更新支付时间为当前时间
$order->have_received = time();// 更新发货时间为当前时间
$order->have_delivered = time();// 更新收货时间为当前时间
$order->pay_type = $extra['pay_type'];
$order->save();

@@ -255,7 +259,7 @@ class Order
* 行为一:退款
* @param array $params 订单数据
*/
public function orderRefund(&$params)
public function orderRefundOld(&$params)
{
$order = &$params;

@@ -280,4 +284,25 @@ class Order

// More ...
}

/**
* 订单退款
* 行为一:退款
* @param array $params 订单数据
*/
public function orderRefund(&$params)
{
$order = &$params;
// 行为一
switch ($order['pay_type']) {
case \addons\unishop\model\Order::PAY_WXPAY:
Service::refund($params["out_trade_no"],"wechat",$params["total_price"]);
break;
case \addons\unishop\model\Order::PAY_ALIPAY:
Service::refund($params['out_trade_no'],"alipay",$params['total_price']);
break;
}

// More ...
}
}

+ 13
- 13
addons/unishop/behavior/OrderFlash.php View File

@@ -78,18 +78,18 @@ class OrderFlash


// 条件三
$delivery = (new DeliveryRuleModel())->cityInScopeOfDelivery($extra['city_id'], $extra['delivery_id']);
if (!$delivery) {
throw new Exception(__('Your receiving address is not within the scope of delivery'));
} else {
if ($delivery['min'] > array_sum($numbers)) {
throw new Exception(__('You must purchase at least %s item to use this shipping method', $delivery['min']));
}
}
$address = (new Address)->where(['id' => $extra['address_id'], 'user_id' => $extra['userId']])->find();
if (!$address) {
throw new Exception(__('Address not exist'));
}
// $delivery = (new DeliveryRuleModel())->cityInScopeOfDelivery($extra['city_id'], $extra['delivery_id']);
// if (!$delivery) {
// throw new Exception(__('Your receiving address is not within the scope of delivery'));
// } else {
// if ($delivery['min'] > array_sum($numbers)) {
// throw new Exception(__('You must purchase at least %s item to use this shipping method', $delivery['min']));
// }
// }
// $address = (new Address)->where(['id' => $extra['address_id'], 'user_id' => $extra['userId']])->find();
// if (!$address) {
// throw new Exception(__('Address not exist'));
// }

// 条件四
$orderPrice = 0;
@@ -108,7 +108,7 @@ class OrderFlash
// 没有优惠券
$coupon = [];

$params = [$products, $delivery, $coupon, $baseProductInfo, $address, $orderPrice, $specs, $numbers];
$params = [$products, [], $coupon, $baseProductInfo, [], $orderPrice, $specs, $numbers];
}

/**


+ 1
- 1
addons/unishop/controller/Address.php View File

@@ -27,7 +27,7 @@ class Address extends Base
* 允许频繁访问的接口
* @var array
*/
protected $frequently = ['area'];
protected $frequently = [];

/**
* 全部收货地址


+ 2
- 2
addons/unishop/controller/Ads.php View File

@@ -12,7 +12,7 @@ use app\common\controller\Api;
class Ads extends Api
{

protected $noNeedLogin = ['index'];
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];

public function _initialize()
@@ -47,7 +47,7 @@ class Ads extends Api
public function index()
{
$ads = \addons\unishop\model\Ads::where('status', 1)->cache('ads-index', 20)->select();
$this->success('广告列表', $ads);
$this->success('', $ads);
}

}

+ 13
- 13
addons/unishop/controller/Base.php View File

@@ -41,19 +41,19 @@ class Base extends Api
* @param int $millisecond
*/
public function limitVisit($millisecond = 200) {
$millisecond = $this->request->request('millisecond', $millisecond);
// 限制200毫秒 防止1秒两刀 (双击甚至三击,同一时间导致接口请求两次以上)
$action = $this->request->action();
if (!in_array($action, $this->frequently) && $this->auth && $this->auth->isLogin() && $millisecond > 0) {
$controller = $this->request->controller();
if (Cache::has($controller.'_'.$action.'_'.$this->auth->id)) {
if (Cache::get($controller.'_'.$action.'_'.$this->auth->id) + $millisecond > \addons\unishop\model\Config::getMillisecond()) {
$this->error(__('Frequent interface requests'));
}
}
Cache::set($controller.'_'.$action.'_'.$this->auth->id, \addons\unishop\model\Config::getMillisecond(), 1);
}
// $millisecond = $this->request->request('millisecond', $millisecond);
//
// // 限制200毫秒 防止1秒两刀 (双击甚至三击,同一时间导致接口请求两次以上)
// $action = $this->request->action();
// if (!in_array($action, $this->frequently) && $this->auth && $this->auth->isLogin() && $millisecond > 0) {
// $controller = $this->request->controller();
// if (Cache::has($controller.'_'.$action.'_'.$this->auth->id)) {
// if (Cache::get($controller.'_'.$action.'_'.$this->auth->id) + $millisecond > \addons\unishop\model\Config::getMillisecond()) {
// $this->error(__('Frequent interface requests'));
// }
// }
// Cache::set($controller.'_'.$action.'_'.$this->auth->id, \addons\unishop\model\Config::getMillisecond(), 1);
// }
}

/**


+ 6
- 1
addons/unishop/controller/Category.php View File

@@ -2,12 +2,13 @@

namespace addons\unishop\controller;

use addons\unishop\model\Config;
use app\common\controller\Api;

class Category extends Api
{

protected $noNeedLogin = ['all','menu','inlist'];
protected $noNeedLogin = [];
protected $noNeedRight = ['*'];

public function _initialize()
@@ -21,6 +22,10 @@ class Category extends Api
* 全部分类数据
*/
public function all(){
$activityTime=Config::getByName('activity_time')['value'];
if (strtotime($activityTime)<time()){
$this->error(__('Activity is end'));
}
$all = $this->model
->where('type','product')
->where('status','normal')


+ 141
- 21
addons/unishop/controller/Order.php View File

@@ -9,7 +9,10 @@

namespace addons\unishop\controller;

use addons\nzf\AliPay;
use addons\nzf\PayService;
use addons\unishop\extend\Hashids;
use addons\unishop\extend\Redis;
use addons\unishop\model\Area;
use addons\unishop\model\Config;
use addons\unishop\model\Evaluate;
@@ -17,6 +20,7 @@ use addons\unishop\model\Product;
use app\admin\model\unishop\Coupon as CouponModel;
use addons\unishop\model\DeliveryRule as DeliveryRuleModel;
use addons\unishop\model\OrderRefund;
use app\admin\model\unishop\OrderProduct;
use app\admin\model\unishop\OrderRefundProduct;
use think\Db;
use think\Exception;
@@ -38,13 +42,17 @@ class Order extends Base
*/
protected $frequently = ['getorders'];

protected $noNeedLogin = ['count'];
protected $noNeedLogin = ["addQRCode"];

/**
* 创建订单
*/
public function create()
{
$activityTime=Config::getByName('activity_time')['value'];
if (strtotime($activityTime)<time()){
$this->error(__('Activity is end'));
}
$productId = $this->request->post('id', 0);

try {
@@ -77,14 +85,14 @@ class Order extends Base
}

/** 默认地址 **/
$address = (new AddressModel)->where(['user_id' => $user_id, 'is_default' => AddressModel::IS_DEFAULT_YES])->find();
if ($address) {
$area = (new Area)->whereIn('id', [$address->province_id, $address->city_id, $address->area_id])->column('name', 'id');
$address = $address->toArray();
$address['province']['name'] = $area[$address['province_id']];
$address['city']['name'] = $area[$address['city_id']];
$address['area']['name'] = $area[$address['area_id']];
}
// $address = (new AddressModel)->where(['user_id' => $user_id, 'is_default' => AddressModel::IS_DEFAULT_YES])->find();
// if ($address) {
// $area = (new Area)->whereIn('id', [$address->province_id, $address->city_id, $address->area_id])->column('name', 'id');
// $address = $address->toArray();
// $address['province']['name'] = $area[$address['province_id']];
// $address['city']['name'] = $area[$address['city_id']];
// $address['area']['name'] = $area[$address['area_id']];
// }


/** 可用优惠券 **/
@@ -101,8 +109,8 @@ class Order extends Base


/** 运费数据 **/
$cityId = $address['city_id'] ? $address['city_id'] : 0;
$delivery = (new DeliveryRuleModel())->getDelivetyByArea($cityId);
// $cityId = $address['city_id'] ? $address['city_id'] : 0;
// $delivery = (new DeliveryRuleModel())->getDelivetyByArea($cityId);

foreach ($productData as &$product) {
$product['image'] = Config::getImagesFullUrl($product['image']);
@@ -112,9 +120,9 @@ class Order extends Base

$this->success('', [
'product' => $productData,
'address' => $address,
// 'address' => $address,
'coupon' => $coupon,
'delivery' => $delivery['list']
// 'delivery' => $delivery['list']
]);

} catch (Exception $e) {
@@ -219,6 +227,29 @@ class Order extends Base
if ($order['have_paid'] != \addons\unishop\model\Order::PAID_NO) {
$this->error('此订单已支付,无法取消');
}
// $redis = new Redis();
// $flash = (new \addons\unishop\model\Order)->alias("o")->
// join("unishop_order_product","unishop_order_product.order_id =o.id")
// ->where(["o.id"=>(int)$order_id])
// ->field("flash_id,product_id")->find();
// if ($flash){
// $redis->handler->hIncrBy('flash_sale_' . $flash->flash_id. '_' . $flash->product_id, 'sold', -1);
// }
$orderProduct = new OrderProduct();

$list =$orderProduct->where([
'order_id' => $order_id
])->select();
$list = collection($list)->toArray();
$product = new \app\admin\model\unishop\Product();
foreach ($list as $val){
try {
$product->where(["id"=>$val['product_id']])->setInc("stock", $val["number"]);
$product->where(["id"=>$val['product_id']])->setInc("real_sales",-$val["number"]);
}catch (Exception $e){
print_r($e);die;
}
}

if ($order['status'] == \addons\unishop\model\Order::STATUS_NORMAL && $order['have_paid'] == \addons\unishop\model\Order::PAID_NO) {
$order->status = \addons\unishop\model\Order::STATUS_CANCEL;
@@ -426,14 +457,14 @@ class Order extends Base
$order['express_number'] = $order['extend']['express_number'];

// 送货地址
$address = json_decode($order['extend']['address_json'], true);
$area = (new \addons\unishop\model\Area())
->whereIn('id', [$address['province_id'], $address['city_id'], $address['area_id']])
->column('name', 'id');
$delivery['username'] = $address['name'];
$delivery['mobile'] = $address['mobile'];
$delivery['address'] = $area[$address['province_id']] . ' ' . $area[$address['city_id']] . ' ' . $area[$address['area_id']] . ' ' . $address['address'];
$order['delivery'] = $delivery;
// $address = json_decode($order['extend']['address_json'], true);
// $area = (new \addons\unishop\model\Area())
// ->whereIn('id', [$address['province_id'], $address['city_id'], $address['area_id']])
// ->column('name', 'id');
// $delivery['username'] = $address['name'];
// $delivery['mobile'] = $address['mobile'];
// $delivery['address'] = $area[$address['province_id']] . ' ' . $area[$address['city_id']] . ' ' . $area[$address['area_id']] . ' ' . $address['address'];
// $order['delivery'] = $delivery;

// 是否已评论
$evaluate = array_column($order['evaluate'], 'product_id');
@@ -582,6 +613,52 @@ class Order extends Base
}
}

public function doRefund(){
$this->error("暂不支持");

$order_id = $this->request->post('order_id');
$order_id = Hashids::decodeHex($order_id);
$orderModel = new \addons\unishop\model\Order();
$order = $orderModel->where([
'id' => $order_id,
'user_id' => $this->auth->id,
'status'=>1,//订单状态正常
'have_paid'=>[">",0],//已支付
'have_received'=>0,//订单完成前
'had_refund'=>0
])->find();
if (!$order){
$this->error("订单信息错误");
}
// $redis = new Redis();
// $flash = $orderModel->alias("o")->
// join("unishop_order_product","unishop_order_product.order_id =o.id")
// ->join("unishop_flash_sale","unishop_order_product.flash_id=unishop_flash_sale.id")
// ->where(["o.id"=>(int)$order_id,"unishop_flash_sale.status"=>0,"unishop_flash_sale.switch"=>1,"unishop_flash_sale.deletetime"=>0])
// ->field("flash_id,product_id,endtime")->find();
// if (!$flash || $flash->endtime < time()){
// $this->error("活动已结束,不支持退款");
// }
// $sold = $redis->handler->hIncrBy('flash_sale_' . $flash->flash_id. '_' . $flash->product_id, 'sold', -1);
$order->status = \addons\unishop\model\Order::STATUS_REFUND;
$order->refund_status = \addons\unishop\model\Order::REFUND_STATUS_AGREE;
$result = $order->save();
if ($result !== false){
//order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额
$param = [
"order_id"=>$order['out_trade_no'],
"total_fee"=>$order['total_price'],
"refund_fee"=>$order['total_price'],
"memo"=>'订单退款',
];
PayService::cancel($param,$order["pay_type"]);
$this->success("success",[]);
}


$this->error("订单信息错误");
}

/**
* 售后发货
*/
@@ -625,4 +702,47 @@ class Order extends Base

}

/**
* Des: 生成二维码
* Name: addQRCode
* @param $qCode string 生成的内容
* @param $QRFile string 二维码图片路径
* @param int $reType 1:返回成功或失败 2 返回图片数据流
* @param bool|false $isCreate 生成的图片是否保留 当$reType=2才会有效
* @param bool $logo 是否添加logo图
* @param string $logoUrl logo图地址
* @return array
* @author 倪宗锋
*/
public function addQRCode()
{
include ROOT_PATH . '/addons/unishop/library/phpqrcode/phpqrcode.php';
$value = $this->request->request('url');//二维码内容
$value = str_replace("&amp;","&",$value);
$errorCorrectionLevel = 'H';//容错级别
$matrixPointSize = 6;//生成图片大小

$QRFile = ROOT_PATH . '/addons/unishop/library/phpqrcode/' . time().rand(1000,9999) . '.png';
//生成二维码图片
\QRcode::png($value, $QRFile, $errorCorrectionLevel, $matrixPointSize, 2);
$QR = imagecreatefromstring(file_get_contents($QRFile));
//二维码
$logoUrl = imagecreatefromstring(file_get_contents(ROOT_PATH . '/addons/unishop/library/phpqrcode/logo.png'));
$QR_width = imagesx($QR);//二维码图片宽度
$logo_width = imagesx($logoUrl);//logo图片宽度
$logo_height = imagesy($logoUrl);//logo图片高度
$logo_qr_width = $QR_width / 5;
$scale = $logo_width / $logo_qr_width;
$logo_qr_height = $logo_height / $scale;
$from_width = ($QR_width - $logo_qr_width) / 2;
//重新组合图片并调整大小
imagecopyresampled($QR, $logoUrl, $from_width, $from_width, 0, 0, $logo_qr_width,
$logo_qr_height, $logo_width, $logo_height);
//输出图片
Header("Content-type: image/png");
ImagePng($QR);
@unlink($QRFile);
die;
}

}

+ 93
- 160
addons/unishop/controller/Pay.php View File

@@ -9,6 +9,9 @@

namespace addons\unishop\controller;

use addons\config\AliPayConfig;
use addons\epay\library\Service;
use addons\nzf\AliPay;
use addons\unishop\extend\Ali;
use addons\unishop\extend\Hashids;
use addons\unishop\extend\Wechat;
@@ -20,7 +23,7 @@ use think\Log;

class Pay extends Base
{
protected $noNeedLogin = ['getPayType', 'notify', 'authRedirect', 'alipay', 'alinotify'];
protected $noNeedLogin = ['getPayType', 'notify','unify', 'authRedirect', 'alipay', 'alinotify'];

/**
* 获取支付类型
@@ -74,6 +77,12 @@ class Pay extends Base
$this->error(__('Order does not exist'));
}

$products = $order->products()->select();

$body = Config::getByName('name')['value'];
foreach ($products as $product) {
$body .= '_' . $product['title'];
}
//MWEB
$platfrom = $this->request->header('platform', 'MP-WEIXIN');

@@ -86,62 +95,28 @@ class Pay extends Base
$trade_type = 'MWEB';
break;
}

// 如果是微信内访问 公众号等
if (Wechat::h5InWechat()) {
$trade_type = 'JSAPI';
}

$products = $order->products()->select();

$body = Config::getByName('name')['value'];
foreach ($products as $product) {
$body .= '_' . $product['title'];
}

$app = Wechat::initEasyWechat('payment');
$result = $app->order->unify([
'body' => $body,
'out_trade_no' => $order['out_trade_no'],
'total_fee' => bcmul($order['total_price'],100),
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
'trade_type' => $trade_type, // 请对应换成你的支付方式对应的值类型
'openid' => Wechat::getOpenidByUserId($this->auth->id)
]);

if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {

if ($trade_type == 'JSAPI') {
// 二次签名
$result['timeStamp'] = (string)time();
$result['paySign'] = Wechat::paySign([
'appId' => Config::getByName('app_id')['value'],
'nonceStr' => $result['nonce_str'],
'package' => 'prepay_id='.$result['prepay_id'],
'timeStamp' => $result['timeStamp'],
'signType' => 'MD5'
], Config::getByName('key')['value']);
} elseif ($trade_type == 'MWEB') {
$page = '/pages/order/order?state=0';
if ($platfrom == 'APP-PLUS') {
$page = '/pages/index/index';
}
$result['mweb_url'] .= '&redirect_url='. urlencode('https://'.$_SERVER['HTTP_HOST'].'/h5/#'.$page);
$result['referer'] = 'https://'.$_SERVER['HTTP_HOST'];
}

$this->success('', $result);
} else {
$this->error($result['return_msg']);
$trade_type = 'wap';
}
$params = [
'amount' => $order['total_price'],
'orderid' => $order->out_trade_no,
'type' => "wechat",
'title' => $body,
'notifyurl' => AliPayConfig::getByName('notify_url'),
'returnurl' => AliPayConfig::getByName('ali_return_url'),
'trade_type' => $trade_type,

];
$this->success("", Service::submitOrder($params));
} catch (Exception $e) {
$this->error($e->getMessage());
}
}

/**
* 微信订单支付通知回调
* 支付通知回调
*/
public function notify()
{
@@ -149,48 +124,60 @@ class Pay extends Base
Hook::add('paid_success', 'addons\\unishop\\behavior\\Order');
Hook::add('paid_fail', 'addons\\unishop\\behavior\\Order');

$app = Wechat::initEasyWechat('payment');
$response = $app->handlePaidNotify(function($message, $fail) use ($app){
try {
// 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
$orderModel = new \addons\unishop\model\Order(); //($message['out_trade_no']);
$order = $orderModel->where(['out_trade_no' => $message['out_trade_no']])->find();

if (!$order || $order->have_paid != \addons\unishop\model\Order::PAID_NO) {
return true; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
}

// 这里调用微信的【订单查询】接口查一下该笔订单的情况,确认是已经支付
$result = $app->order->queryByOutTradeNumber($message['out_trade_no']);
if ($result['return_code'] == 'FAIL' || empty($result['result_code']) || $result['result_code'] == 'FAIL') {
return $fail('订单未支付');
}

// 检查是否成功
if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
// 用户是否支付成功
if ($message['result_code'] === 'SUCCESS') {

Hook::listen('paid_success', $order, ['pay_type' => \addons\unishop\model\Order::PAY_WXPAY]);

} elseif ($message['result_code'] === 'FAIL') {
// 用户支付失败
Hook::listen('paid_fail', $order);
}
} else {
return $fail('通信失败,请稍后再通知我');
}

return true;
} catch (\Exception $e) {
// 记录日志
Log::record('支付回调错误:'. $e->getMessage());
$paytype = $this->request->param('type');
$string = date('Y-m-d H:i:s', time()) . PHP_EOL;
$body = request()->post('', null, 'trim');
if (empty($body) == false) {
$string .= 'body : ' . json_encode($body) . PHP_EOL;
}
$pay = Service::checkNotify($paytype);
if (!$pay) {
$string.="签名错误" . PHP_EOL;
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/pay_".date("d"). '.log',$string , FILE_APPEND);
echo '签名错误';
return;
}
$data = $pay->verify();
try {
$payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
$out_trade_no = $data['out_trade_no'];

// $paytype="alipay";
// $payamount =11;
// $out_trade_no = "202009205f6707697421b23";

//你可以在此编写订单逻辑
//Log::record('Alipay notify ,支付成功');

// 条件一
$orderModel = new \addons\unishop\model\Order(); //($message['out_trade_no']);
$order = $orderModel->where(['out_trade_no' => $out_trade_no])->find();
if (!$order || $order->have_paid != \addons\unishop\model\Order::PAID_NO) {
$string.="订单不存在或已完成" . PHP_EOL;
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/pay_".date("d"). '.log',$string , FILE_APPEND);
throw new Exception('订单不存在或已完成');
}

return $fail('通信失败,请稍后再通知我');
// 条件二
if ($order->total_price > $payamount || $order->total_price < $payamount) {
$string.="金额不一" . PHP_EOL;
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/pay_".date("d"). '.log',$string , FILE_APPEND);
throw new Exception('金额不一');
}
});

$response->send();
// 添加行为
Hook::add('paid_success', 'addons\\unishop\\behavior\\Order');
$payTypeString = $paytype == 'alipay' ? \addons\unishop\model\Order::PAY_ALIPAY : \addons\unishop\model\Order::PAY_WXPAY;
Hook::listen('paid_success', $order, ['pay_type' => $payTypeString]);
//日志
$string.="成功".PHP_EOL;
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/pay_".date("d"). '.log',$string , FILE_APPEND);
} catch (Exception $e) {
$string.=$e->getMessage() . PHP_EOL;
file_put_contents(ROOT_PATH . '/runtime/log/' . date('Ym') ."/pay_".date("d"). '.log',$string , FILE_APPEND);
}
$pay = new \Yansongda\Pay\Pay();
echo $pay->success();
}

/**
@@ -253,87 +240,33 @@ class Pay extends Base
foreach ($products as $product) {
$body .= '_' . $product['title'];
}
$platfrom = $this->request->header('platform', 'H5');
$alipay = Ali::initAliPay();
$order = [
'out_trade_no' => $order->out_trade_no,
'total_amount' => $order->total_price,
'subject' => $body,
'http_method' => 'GET' // 如果想在 wap 支付时使用 GET 方式提交,请加上此参数。默认使用 POST 方式提交
$params = [
'amount' => $order->total_price,
'orderid' => $order->out_trade_no,
'type' => "alipay",
'title' => $body,
'notify_url' => AliPayConfig::getByName('ali_notify_url'),
'return_url' => AliPayConfig::getByName('ali_return_url'),
'method' => "wap",
];

switch ($platfrom) {
case 'H5':
// 直接返回
$alipay->wap($order)->send();
break;
case 'APP-PLUS':
//$pay->app($order)->send();
$this->success('', $alipay->app($order)->getContent());
break;
case 'MP-ALIPAY':

break;
default:
$this->error('此平台不支持支付宝支付');
}

return Service::submitOrder($params);
} catch (Exception $e) {
$this->error($e->getMessage());
}

}

/**
* 支付宝回调地址
*/
public function alinotify()
{
$alipay = Ali::initAliPay();

try{
$data = $alipay->verify(); // 是的,验签就这么简单!

// 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
// 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
// 4、验证app_id是否为该商户本身。
// 5、其它业务逻辑情况
if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
// 支付成功
//Log::record('Alipay notify ,支付成功');

// 条件一
$orderModel = new \addons\unishop\model\Order(); //($message['out_trade_no']);
$order = $orderModel->where(['out_trade_no' => $data['out_trade_no']])->find();
if (!$order || $order->have_paid != \addons\unishop\model\Order::PAID_NO) {
throw new Exception('订单不存在或已完成');
}

// 条件二
if ($order->total_price > $data['total_amount'] || $order->total_price < $data['total_amount']) {
throw new Exception('金额不一');
}

// 条件三
if ($data['app_id'] != Config::getByName('ali_app_id')['value']) {
throw new Exception('app_id不一');
}

// 添加行为
Hook::add('paid_success', 'addons\\unishop\\behavior\\Order');
Hook::listen('paid_success', $order, ['pay_type' => \addons\unishop\model\Order::PAY_ALIPAY]);

}

} catch (\Exception $e) {
Log::record('Alipay notify ,支付失败: '. $e->getMessage());
return $alipay->success()->send();
}

return $alipay->success()->send();// laravel 框架中请直接 `return $alipay->success()`
}

// public function notify(){
// $order = [
// "order_id"=>"202009275f7076e5c6f2f23",
// "total_fee"=>11,
// "memo"=>'取消订单',
// "refund_fee"=>11,
//
// ];//order_id:订单ID name:订单名称 total_fee:总金额-元 refund_fee退款金额
// AliPay::cancelOrder($order);
//
// }
}

+ 2
- 2
addons/unishop/controller/Product.php View File

@@ -12,7 +12,7 @@ use think\Exception;

class Product extends Base
{
protected $noNeedLogin = ['detail', 'lists'];
protected $noNeedLogin = [];

/**
* 获取产品数据
@@ -113,7 +113,7 @@ class Product extends Base
}

$result = $productModel
->where(['switch' => productModel::SWITCH_ON])
->where(['switch' => productModel::SWITCH_ON,'stock'=>[">",0]])
->page($page, $pagesize)
->order($by, $desc)
->field('id,title,image,sales_price,sales,real_sales')


+ 46
- 10
addons/unishop/controller/User.php View File

@@ -9,7 +9,9 @@

namespace addons\unishop\controller;

use addons\unishop\extend\Redis;
use addons\unishop\extend\Wechat;
use addons\unishop\model\Config;
use addons\unishop\model\UserExtend;
use app\common\library\Sms;
use think\Cache;
@@ -18,7 +20,7 @@ use think\Validate;

class User extends Base
{
protected $noNeedLogin = ['login', 'status', 'authSession', 'decryptData', 'register', 'resetpwd', 'loginForWechatMini'];
protected $noNeedLogin = ['login', 'status', 'authSession', 'decryptData', 'register', 'resetpwd', 'loginForWechatMini','checkRedis'];

/**
* 会员登录
@@ -36,8 +38,34 @@ class User extends Base
$ret = $this->auth->login($mobile, $password);
if ($ret) {
$data = $this->auth->getUserinfo();
$privilege_user_list=Config::getByName('privilege_user_list')['value'];
$privilege_user_list=explode(",",$privilege_user_list);
if (!in_array($data['id'],$privilege_user_list)){
//普通用户
//普通用户受限制时间
$ordinary_user_start=Config::getByName('ordinary_user_start')['value'];
$ordinary_user_end=Config::getByName('ordinary_user_end')['value'];
$ordinary_user_start=strtotime($ordinary_user_start);
$ordinary_user_end=strtotime($ordinary_user_end);
if (time()>$ordinary_user_end || time()<$ordinary_user_start){
$this->auth->logout();
$this->error('It\'s not time to open');
}
}else{
//特权用户
$privilege_user_start=Config::getByName('privilege_user_start')['value'];
$privilege_user_end=Config::getByName('privilege_user_end')['value'];
$privilege_user_start=strtotime($privilege_user_start);
$privilege_user_end=strtotime($privilege_user_end);
if (time()>$privilege_user_end || time()<$privilege_user_start){
$this->auth->logout();
$this->error('It\'s not time to open ');
}
}


$data['avatar'] = \addons\unishop\model\Config::getImagesFullUrl($data['avatar']);
$this->success(__('Logged in successful'), $data);
$this->success('Logged in successful', $data);
} else {
$this->error($this->auth->getError());
}
@@ -127,15 +155,16 @@ class User extends Base
*/
public function edit()
{
$userInfo = $this->auth->getUserinfo();
$username = $this->request->post('username', $userInfo['username']);
$mobile = $this->request->post('mobile', $userInfo['mobile']);
$avatar = $this->request->post('avatar', $userInfo['avatar']);

// $userInfo = $this->auth->getUserinfo();
// $username = $this->request->post('username', $userInfo['username']);
$password = $this->request->post('password', "");
// $avatar = $this->request->post('avatar', $userInfo['avatar']);
if (!$password){
$this->error(__('请填写密码'), 0);
}
$user = \app\common\model\User::get($this->auth->id);
$user->username = $username;
$user->mobile = $mobile;
$user->avatar = $avatar;
$pwd= \app\common\library\Auth::instance()->getEncryptPassword($password, $user->salt);
$user->password = $pwd;
if ($user->save()) {
$this->success(__('Modified'), 1);
} else {
@@ -273,5 +302,12 @@ class User extends Base

}

public function checkRedis(){
$redis = new Redis();
$a=$redis->handler->set("test_redis",1,86400);
$b=$redis->handler->get("test_redis");
$this->success('', $b);
}


}

+ 7
- 7
addons/unishop/extend/Ali.php View File

@@ -10,7 +10,7 @@
namespace addons\unishop\extend;


use addons\unishop\model\Config;
use addons\config\AliPayConfig;
use Yansongda\Pay\Pay;

class Ali
@@ -18,12 +18,12 @@ class Ali
public static function initAliPay()
{
$config = [
'app_id' => Config::getByName('ali_app_id')['value'],
'notify_url' => Config::getByName('ali_notify_url')['value'],
'return_url' => Config::getByName('ali_return_url')['value'],
'ali_public_key' => Config::getByName('ali_public_key')['value'],
'app_id' => AliPayConfig::getByName('ali_app_id'),
'notify_url' => AliPayConfig::getByName('ali_notify_url'),
'return_url' => AliPayConfig::getByName('ali_return_url'),
'ali_public_key' => AliPayConfig::getByName('ali_public_key'),
// 加密方式: **RSA2**
'private_key' => Config::getByName('ali_private_key')['value'],
'private_key' => AliPayConfig::getByName('ali_private_key'),
// 'log' => [ // optional
// 'file' => './logs/alipay.log',
// 'level' => 'info', // 建议生产环境等级调整为 info,开发环境为 debug
@@ -38,7 +38,7 @@ class Ali
//'mode' => 'dev', // optional,设置此参数,将进入沙箱模式
];

if (Config::getByName('ali_sandbox')['value'] == 1) {
if (AliPayConfig::getByName('ali_sandbox') == 1) {
$config['mode'] = 'dev';
}



+ 38
- 0
addons/unishop/library/phpqrcode/CHANGELOG View File

@@ -0,0 +1,38 @@
* 1.0.0 build 2010031920

- first public release
- help in readme, install
- cleanup ans separation of QRtools and QRspec
- now TCPDF binding requires minimal changes in TCPDF, having most of job
done in QRtools tcpdfBarcodeArray
- nicer QRtools::timeBenchmark output
- license and copyright notices in files
- indent cleanup - from tab to 4spc, keep it that way please :)
- sf project, repository, wiki
- simple code generator in index.php
* 1.1.0 build 2010032113

- added merge tool wich generate merged version of code
located in phpqrcode.php
- splited qrconst.php from qrlib.php
* 1.1.1 build 2010032405

- patch by Rick Seymour allowing saving PNG and displaying it at the same time
- added version info in VERSION file
- modified merge tool to include version info into generated file
- fixed e-mail in almost all head comments
* 1.1.2 build 2010032722

- full integration with TCPDF thanks to Nicola Asuni, it's author
- fixed bug with alphanumeric encoding detection
* 1.1.3 build 2010081807

- short opening tags replaced with standard ones
* 1.1.4 build 2010100721

- added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC)

+ 67
- 0
addons/unishop/library/phpqrcode/INSTALL View File

@@ -0,0 +1,67 @@
== REQUIREMENTS ==

* PHP5
* PHP GD2 extension with JPEG and PNG support
== INSTALLATION ==

If you want to recreate cache by yourself make sure cache directory is
writable and you have permisions to write into it. Also make sure you are
able to read files in it if you have cache option enabled
== CONFIGURATION ==

Feel free to modify config constants in qrconfig.php file. Read about it in
provided comments and project wiki page (links in README file)

== QUICK START ==

Notice: probably you should'nt use all of this in same script :)

<?phpb

//include only that one, rest required files will be included from it
include "qrlib.php"

//write code into file, Error corection lecer is lowest, L (one form: L,M,Q,H)
//each code square will be 4x4 pixels (4x zoom)
//code will have 2 code squares white boundary around

QRcode::png('PHP QR Code :)', 'test.png', 'L', 4, 2);

//same as above but outputs file directly into browser (with appr. header etc.)
//all other settings are default
//WARNING! it should be FIRST and ONLY output generated by script, otherwise
//rest of output will land inside PNG binary, breaking it for sure
QRcode::png('PHP QR Code :)');

//show benchmark
QRtools::timeBenchmark();

//rebuild cache
QRtools::buildCache();

//code generated in text mode - as a binary table
//then displayed out as HTML using Unicode block building chars :)
$tab = $qr->encode('PHP QR Code :)');
QRspec::debug($tab, true);

== TCPDF INTEGRATION ==

Inside bindings/tcpdf you will find slightly modified 2dbarcodes.php.
Instal phpqrcode liblaty inside tcpdf folder, then overwrite (or merge)
2dbarcodes.php

Then use similar as example #50 from TCPDF examples:

<?php

$style = array(
'border' => true,
'padding' => 4,
'fgcolor' => array(0,0,0),
'bgcolor' => false, //array(255,255,255)
);

//code name: QR, specify error correction level after semicolon (L,M,Q,H)
$pdf->write2DBarcode('PHP QR Code :)', 'QR,L', '', '', 30, 30, $style, 'N');

+ 165
- 0
addons/unishop/library/phpqrcode/LICENSE View File

@@ -0,0 +1,165 @@
GNU LESSER 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.


This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

0. Additional Definitions.

As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".

The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.

The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.

1. Exception to Section 3 of the GNU GPL.

You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.

2. Conveying Modified Versions.

If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:

a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or

b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.

3. Object Code Incorporating Material from Library Header Files.

The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:

a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.

b) Accompany the object code with a copy of the GNU GPL and this license
document.

4. Combined Works.

You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:

a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.

b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.

c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.

d) Do one of the following:

0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.

1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.

e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)

5. Combined Libraries.

You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:

a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.

b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.

6. Revised Versions of the GNU Lesser General Public License.

The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser 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
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.

If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

+ 15
- 0
addons/unishop/library/phpqrcode/QrCode.php View File

@@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2016/11/18
* Time: 11:25
*/

namespace Base\Lib\phpqrcode;
include 'phpqrcode.php';

class QrCode extends \QRcode
{

}

+ 45
- 0
addons/unishop/library/phpqrcode/README View File

@@ -0,0 +1,45 @@
This is PHP implementation of QR Code 2-D barcode generator. It is pure-php
LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi.

== LICENSING ==

Copyright (C) 2010 by Dominik Dzienia

This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or any later version.

This library 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 Lesser General Public License (LICENSE file)
for more details.

You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

== INSTALATION AND USAGE ==

* INSTALL file
* http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page

== CONTACT ==

Fell free to contact me via e-mail (deltalab at poczta dot fm) or using
folowing project pages:

* http://sourceforge.net/projects/phpqrcode/
* http://phpqrcode.sourceforge.net/
== ACKNOWLEDGMENTS ==

Based on C libqrencode library (ver. 3.1.1)
Copyright (C) 2006-2010 by Kentaro Fukuchi
http://megaui.net/fukuchi/works/qrencode/index.en.html

QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
countries.

Reed-Solomon code encoder is written by Phil Karn, KA9Q.
Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q

+ 2
- 0
addons/unishop/library/phpqrcode/VERSION View File

@@ -0,0 +1,2 @@
1.1.4
2010100721

+ 2875
- 0
addons/unishop/library/phpqrcode/bindings/tcpdf/qrcode.php
File diff suppressed because it is too large
View File


+ 2
- 0
addons/unishop/library/phpqrcode/cache/frame_1.dat View File

@@ -0,0 +1,2 @@
xÚ��Á À E9³u��`³"PÅ„CÛ牗T!0$
E•É²Q™�Ém½úhÛ¾9{kI"› 9Ln)Ap¤åÖ¾Ë>ß^‡Õz³mënÅ–;ü´mßn†ú¦Ë

BIN
addons/unishop/library/phpqrcode/cache/frame_1.png View File

Before After
Width: 21  |  Height: 21  |  Size: 126 B

BIN
addons/unishop/library/phpqrcode/cache/frame_10.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_10.png View File

Before After
Width: 57  |  Height: 57  |  Size: 202 B

BIN
addons/unishop/library/phpqrcode/cache/frame_11.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_11.png View File

Before After
Width: 61  |  Height: 61  |  Size: 205 B

BIN
addons/unishop/library/phpqrcode/cache/frame_12.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_12.png View File

Before After
Width: 65  |  Height: 65  |  Size: 216 B

BIN
addons/unishop/library/phpqrcode/cache/frame_13.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_13.png View File

Before After
Width: 69  |  Height: 69  |  Size: 210 B

BIN
addons/unishop/library/phpqrcode/cache/frame_14.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_14.png View File

Before After
Width: 73  |  Height: 73  |  Size: 213 B

BIN
addons/unishop/library/phpqrcode/cache/frame_15.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_15.png View File

Before After
Width: 77  |  Height: 77  |  Size: 219 B

+ 1
- 0
addons/unishop/library/phpqrcode/cache/frame_16.dat View File

@@ -0,0 +1 @@
xÚí™A„ E]sëIX´;¸Ün6€È`‚q”êêW6ñ奚`Œ%A/3!¢°‚¢Š!g–ÈÌ¡’1N) éE¢Ï|;®—>6â¸�Þ97$ëÄôëc]kkö�wé1Öü[·m­CÍœcÊRºÄê¹>¦èµ¾šE,•hʼnp„#áxF�yWÏÇVWGçòÕ3¼Õ+шþàË“úSŽâ}Äž�#áG8b^c^cÏÀŽp„c&3YQ"ñŽ÷çÌvµù›…ñàÎþþ¼–¹kÞ9ŠÜ‡÷}”¹³ï×ú ¢Ä¿�QäÿL—/ÝÔÀÏ

BIN
addons/unishop/library/phpqrcode/cache/frame_16.png View File

Before After
Width: 81  |  Height: 81  |  Size: 211 B

BIN
addons/unishop/library/phpqrcode/cache/frame_17.dat View File


BIN
addons/unishop/library/phpqrcode/cache/frame_17.png View File

Before After
Width: 85  |  Height: 85  |  Size: 211 B

+ 2
- 0
addons/unishop/library/phpqrcode/cache/frame_18.dat View File

@@ -0,0 +1,2 @@
xÚí™A
ƒ0E]çÖ…,2;sƒä&ÉÍšh¥ÛêO¡ôÝÈàã1&09OIv@DDÒ Ì&§Ù‰K�XÈÕFv•<Ádqò9Ö<%h•¹ Yïs !(d¥²ës;~||b(ÏøYůg#µ`œK ±S¼Åô¹Ä¶˜ùsàidß�Lg:Ó™Îtþ/gmª�™ƒkÅMâ3³{­4rTÈQýÿe¥·s·>ó<Ó™Ît¦3�éÌ;ïH¼#Ñ™Ît¦3�ÍYœ+og©hù¶óµÙ½¬lnðûF>Øi^»#awm;gè~pÛgìNs{6z’‘»ãºïÞäp¾Ê'

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save