作者 魏强

授权及支付

@@ -13,6 +13,12 @@ if (file_exists(CMF_ROOT . "data/conf/config.php")) { @@ -13,6 +13,12 @@ if (file_exists(CMF_ROOT . "data/conf/config.php")) {
13 } else { 13 } else {
14 $runtimeConfig = []; 14 $runtimeConfig = [];
15 } 15 }
  16 +if (file_exists(CMF_ROOT . "app/extra/wechat.php")) {
  17 + $wechatConfig['wechat_config'] = include CMF_ROOT . "app/extra/wechat.php";
  18 +} else {
  19 + $wechatConfig['wechat_config'] = [];
  20 +}
  21 +
16 $configs = [ 22 $configs = [
17 // +---------------------------------------------------------------------- 23 // +----------------------------------------------------------------------
18 // | 应用设置 24 // | 应用设置
@@ -227,4 +233,4 @@ $configs = [ @@ -227,4 +233,4 @@ $configs = [
227 'cmf_admin_theme_path' => 'themes/', 233 'cmf_admin_theme_path' => 'themes/',
228 'cmf_admin_default_theme' => 'admin_simpleboot3', 234 'cmf_admin_default_theme' => 'admin_simpleboot3',
229 ]; 235 ];
230 -return array_merge($configs, $runtimeConfig);  
  236 +return array_merge($configs, $runtimeConfig,$wechatConfig);
@@ -12,6 +12,7 @@ use cmf\controller\HomeBaseController; @@ -12,6 +12,7 @@ use cmf\controller\HomeBaseController;
12 12
13 class IndexController extends HomeBaseController 13 class IndexController extends HomeBaseController
14 { 14 {
  15 + protected $abc;
15 public function index() 16 public function index()
16 { 17 {
17 return $this->fetch(':index'); 18 return $this->fetch(':index');
@@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
3 namespace app\portal\controller; 3 namespace app\portal\controller;
4 4
5 use cmf\controller\HomeBaseController; 5 use cmf\controller\HomeBaseController;
  6 +use EasyWeChat\Foundation\Application;
  7 +use EasyWeChat\Payment\Order;
6 use think\Db; 8 use think\Db;
7 -use think\Log;  
8 -use think\Validate;  
9 9
10 /** 10 /**
11 * 微信支付,退款,提现DEMO 11 * 微信支付,退款,提现DEMO
@@ -14,67 +14,142 @@ use think\Validate; @@ -14,67 +14,142 @@ use think\Validate;
14 */ 14 */
15 class PayController extends HomeBaseController 15 class PayController extends HomeBaseController
16 { 16 {
  17 + protected $options;
  18 + function _initialize()
  19 + {
  20 + parent::_initialize();
  21 + $this->options = [
  22 + 'app_id' => config('wechat_config.app_id'), // AppID
  23 + 'secret' => config('wechat_config.secret'), // AppSecret
  24 + // payment
  25 + 'payment' => config('wechat_config.payment'),
  26 + ];
  27 + }
17 28
18 /** 29 /**
19 * 微信支付 30 * 微信支付
20 */ 31 */
21 public function index(){ 32 public function index(){
  33 + $attributes = [
  34 + 'trade_type' => 'JSAPI',
  35 + 'body' => '百荣科技',
  36 + 'detail' => '以客户为中心 以奋斗者文本',
  37 + 'out_trade_no' => cmf_get_order_sn(),
  38 + 'total_fee' => 1, // 单位:分
  39 + 'notify_url' => url('portal/pay/notify','','',true), // 支付结果通知网址,如果不设置则会使用配置里的默认地址
  40 + 'openid' => cmf_get_current_user_openid(), // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识,
  41 + ];
  42 + $order = new Order($attributes);
  43 +
  44 + $app = new Application($this->options);
  45 + $payment = $app->payment;
  46 + $result = $payment->prepare($order);
  47 +
  48 + if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
  49 + $prepayId = $result->prepay_id;
  50 + $jsApiParameters=$payment->configForJSSDKPayment($prepayId);
  51 + $this->assign('jsApiParameters',json_encode($jsApiParameters));
  52 + return $this->fetch();
  53 + }else{
  54 + $this->error('支付参数错误','',$result);
  55 + }
22 56
23 } 57 }
24 58
25 /** 59 /**
26 * 支付回调 60 * 支付回调
  61 + * @throws \EasyWeChat\Core\Exceptions\FaultException
27 */ 62 */
28 public function notify(){ 63 public function notify(){
  64 + cache('nnn',111);
  65 + $app = new Application($this->options);
  66 + $response = $app->payment->handleNotify(function($notify, $successful){
  67 + cache('notify',$notify);
  68 + cache('successful',$successful);
  69 + /*这里是支付回调逻辑处理,一下是DEMO*/
  70 +
  71 +// // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
  72 +// $out_trade_no=$notify->out_trade_no;
  73 +// $order = Db::name('order')->where('order_sn',$out_trade_no)->find();
  74 +// if (!$order) { // 如果订单不存在
  75 +// return 'Order not exist.'; // 告诉微信,我已经处理完了,订单没找到,别再通知我了
  76 +// }
  77 +// // 如果订单存在
  78 +// // 检查订单是否已经更新过支付状态
  79 +// if ($order['pay_time']>0) { // 假设订单字段“支付时间”不为空代表已经支付
  80 +// return true; // 已经支付成功了就不再更新了
  81 +// }
  82 +//
  83 +// // 用户是否支付成功
  84 +// if ($successful) {
  85 +// // 回填微信的订单号
  86 +// $update['transaction_id']=$notify->transaction_id;
  87 +// $update['pay_time']=time();
  88 +// // 不是已经支付状态则修改为已经支付状态
  89 +// $update['status'] = 2;
  90 +// } else { // 用户支付失败
  91 +// $update['status']=9;
  92 +// }
  93 +// Db::name('order')->where('order_sn',$out_trade_no)->update($update);
  94 +
  95 + return true; // 返回处理完成
  96 + });
  97 +
  98 + $response->send();
  99 + }
  100 +
29 101
  102 + /**
  103 + * 查询订单
  104 + */
  105 + public function checkOrder(){
  106 + $app = new Application($this->options);
  107 + $payment = $app->payment;
  108 + $orderNo = "2018080210097519";//商户系统内部的订单号(out_trade_no)
  109 + $result=$payment->query($orderNo);
  110 + var_dump($result);
30 } 111 }
31 112
32 /** 113 /**
33 * 退款 114 * 退款
34 - * @throws \WxPayException  
35 */ 115 */
36 public function refund(){ 116 public function refund(){
37 - $param = $this->request->param(); 117 + //todo 退款逻辑应该加入百荣签名验证规则,避免出现被盗用
  118 + /*$param=$this->request->param();
38 $signature = $param['s']; 119 $signature = $param['s'];
39 $arithmetic['timeStamp']= $param['t']; 120 $arithmetic['timeStamp']= $param['t'];
40 $arithmetic['randomStr']= $param['r']; 121 $arithmetic['randomStr']= $param['r'];
41 $arithmetic['orderSn']= $param['o']; 122 $arithmetic['orderSn']= $param['o'];
42 $str = arithmetic($arithmetic); 123 $str = arithmetic($arithmetic);
43 if($str != $signature){ 124 if($str != $signature){
44 - $this->error('签名验证失败');  
45 - }  
46 -  
47 - /*微信退款*/  
48 - require_once EXTEND_PATH."WxpayAPI/lib/WxPay.Api.php";  
49 - require_once EXTEND_PATH."WxpayAPI/example/log.php";  
50 - if(isset($info["transaction_id"]) && empty($info["transaction_id"])){  
51 - $transaction_id = $info["transaction_id"];  
52 - $total_fee = $info["real_price"]*100;  
53 - $refund_fee = $info["real_price"]*100;  
54 - $input = new \WxPayRefund();  
55 - $input->SetTransaction_id($transaction_id);  
56 - $input->SetTotal_fee($total_fee);  
57 - $input->SetRefund_fee($refund_fee);  
58 - $input->SetOut_refund_no(\WxPayConfig::MCHID.date("YmdHis"));  
59 - $input->SetOp_user_id(\WxPayConfig::MCHID);  
60 - $ret=\WxPayApi::refund($input);  
61 - if($ret['result_code']=='SUCCESS'){  
62 - //todo 退款成功处理  
63 - $this->success('退款成功');  
64 - }else{  
65 - $this->error("退款失败:".$ret['err_code_des']);  
66 - }  
67 - }else{  
68 - $this->error('缺少退款标识');  
69 - } 125 + $this->error('签名验证失败');
  126 + }*/
  127 + $app = new Application($this->options);
  128 + $payment = $app->payment;
  129 + //使用商户订单号退款 PS.其他形式参考文档
  130 + $orderNo = "2018080210097519";//商户系统内部的订单号(out_trade_no)
  131 + $refundNo = cmf_get_order_sn();//退款单号
  132 + $result = $payment->refund($orderNo, $refundNo, 100, 80); // 总金额 100, 退款 80,refundFee可选(为空时全额退款)
  133 + var_dump($result);
  134 + }
70 135
  136 + /**
  137 + * 查询退款
  138 + */
  139 + public function checkRefund(){
  140 + $app = new Application($this->options);
  141 + $payment = $app->payment;
  142 + $outTradeNo="2018080210097519";//商户系统内部的订单号(out_trade_no)
  143 + $result = $payment->queryRefund($outTradeNo);
  144 + var_dump($result);
71 } 145 }
72 146
73 /** 147 /**
74 - * 提现 148 + * 红包
75 */ 149 */
76 - public function withdraw_cash(){  
77 - $param = $this->request->param(); 150 + public function luckyMoney(){
  151 + //todo 退款逻辑应该加入百荣签名验证规则,避免出现被盗用
  152 + /*$param=$this->request->param();
78 $signature = $param['s']; 153 $signature = $param['s'];
79 $arithmetic['timeStamp']= $param['t']; 154 $arithmetic['timeStamp']= $param['t'];
80 $arithmetic['randomStr']= $param['r']; 155 $arithmetic['randomStr']= $param['r'];
@@ -82,19 +157,51 @@ class PayController extends HomeBaseController @@ -82,19 +157,51 @@ class PayController extends HomeBaseController
82 $str = arithmetic($arithmetic); 157 $str = arithmetic($arithmetic);
83 if($str != $signature){ 158 if($str != $signature){
84 $this->error('签名验证失败'); 159 $this->error('签名验证失败');
85 - }  
86 - $price=1;  
87 - $openid='';  
88 -  
89 - $merch=new \MerchPay();  
90 - $trade_no = cmf_get_order_sn();  
91 - $res=$merch->pay($openid,$trade_no,$price,'提现');  
92 - if($res['result_code']=='SUCCESS'){  
93 - //todo 提现成功处理  
94 - }else{  
95 - $this->error('操作失败:'.$res['return_msg']);  
96 - } 160 + }*/
  161 +
  162 + $app = new Application($this->options);
  163 + $luckyMoney = $app->lucky_money;
  164 + $luckyMoneyData = [
  165 + 'mch_billno' => 'xy123456',
  166 + 'send_name' => '测试红包',
  167 + 're_openid' => 'oxTWIuGaIt6gTKsQRLau2M0yL16E',
  168 + 'total_num' => 1, //普通红包固定为1,裂变红包不小于3
  169 + 'total_amount' => 100, //单位为分,普通红包不小于100,裂变红包不小于300
  170 + 'wishing' => '祝福语',
  171 + 'client_ip' => '192.168.0.1', //可不传,不传则由 SDK 取当前客户端 IP
  172 + 'act_name' => '测试活动',
  173 + 'remark' => '测试备注',
  174 + // ...
  175 + ];
  176 + //普通红包
  177 + $result = $luckyMoney->send($luckyMoneyData, \EasyWeChat\Payment\LuckyMoney\API::TYPE_NORMAL);
  178 + var_dump($result);
  179 + }
  180 +
  181 + /**
  182 + * 查询红包
  183 + */
  184 + public function checkLuckyMoney(){
  185 + $mchBillNo = "商户系统内部的订单号(mch_billno)";
  186 + $app = new Application($this->options);
  187 + $luckyMoney = $app->lucky_money;
  188 + $luckyMoney->query($mchBillNo);
  189 + }
97 190
  191 + /**
  192 + * 生成签名DEMO
  193 + * @return string
  194 + */
  195 + public function getSignatureDemo(){
  196 + $timeStamp = time();
  197 + $randomStr = cmf_random_string(8);
  198 + $arithmetic['timeStamp']= $timeStamp;
  199 + $arithmetic['randomStr']= $randomStr;
  200 + $signature = arithmetic($arithmetic);
  201 + $notifyParam=array('t'=>$timeStamp,'r'=>$randomStr,'s'=>$signature);
  202 + $url=url('your url 表达式',$notifyParam,true,true);
  203 + return $url;
98 } 204 }
99 205
  206 +
100 } 207 }
@@ -10,24 +10,108 @@ @@ -10,24 +10,108 @@
10 // +---------------------------------------------------------------------- 10 // +----------------------------------------------------------------------
11 namespace app\user\controller; 11 namespace app\user\controller;
12 12
  13 +use app\user\model\UserModel;
13 use cmf\controller\HomeBaseController; 14 use cmf\controller\HomeBaseController;
14 use think\Db; 15 use think\Db;
15 use EasyWeChat\Foundation\Application; 16 use EasyWeChat\Foundation\Application;
  17 +use think\Log;
16 18
17 class IndexController extends HomeBaseController 19 class IndexController extends HomeBaseController
18 { 20 {
19 public function callback(){ 21 public function callback(){
20 - $config = []; 22 + $appId=config('wechat_config.app_id');
  23 + $secret=config('wechat_config.secret');
  24 + $config = [
  25 + 'app_id' => $appId,
  26 + 'secret' => $secret,
  27 + ];
21 28
22 $app = new Application($config); 29 $app = new Application($config);
23 $oauth = $app->oauth; 30 $oauth = $app->oauth;
24 $user = $oauth->user(); 31 $user = $oauth->user();
25 $wechat_user = $user->toArray(); 32 $wechat_user = $user->toArray();
26 //todo $wechat_user与数据库对比 33 //todo $wechat_user与数据库对比
27 - session('wechat_user',$wechat_user);  
28 - $target_url=session('target_url');  
29 - $targetUrl = empty($target_url) ? '/' : $target_url;  
30 - header('location:'. $targetUrl); 34 + if(isset($wechat_user['id'])){
  35 + $openid=$wechat_user['id'];
  36 + $findThirdPartyUser = Db::name("third_party_user")
  37 + ->where('openid', $openid)
  38 + ->where('app_id', $appId)
  39 + ->find();
  40 + $currentTime = time();
  41 + $ip = $this->request->ip(0, true);
  42 + if ($findThirdPartyUser) {
  43 + $token = cmf_generate_user_token($findThirdPartyUser['user_id'], 'public');
  44 + $userData = [
  45 + 'last_login_ip' => $ip,
  46 + 'last_login_time' => $currentTime,
  47 + 'login_times' => ['exp', 'login_times+1']
  48 + ];
  49 + $row1=Db::name("third_party_user")
  50 + ->where('openid', $openid)
  51 + ->where('app_id', $appId)
  52 + ->update($userData);
  53 + $userInfo=Db::name("third_party_user")
  54 + ->where('openid', $openid)
  55 + ->where('app_id', $appId)->find();
  56 + unset($userData['login_times']);
  57 + $row2=Db::name("user")
  58 + ->where('id', $userInfo['user_id'])
  59 + ->update($userData);
  60 + if($row1!==false&&$row2!==false){
  61 + $userModel=new UserModel();
  62 + $user=$userModel->getUserInfo(['user_id'=>$userInfo['user_id'],'app_id'=>$appId]);
  63 + cmf_update_current_user($user);
  64 + session('token',$token);
  65 + Db::commit();
  66 + }else{
  67 + Db::rollback();
  68 + }
  69 + }else{
  70 + Db::startTrans();
  71 + $userId = Db::name("user")->insertGetId([
  72 + 'create_time' => $currentTime,
  73 + 'user_status' => 1,
  74 + 'user_type' => 2,
  75 + 'sex' => $wechat_user['original']['sex'],
  76 + 'user_nickname' => $wechat_user['nickname'],
  77 + 'avatar' => $wechat_user['avatar'],
  78 + 'last_login_ip' => $ip,
  79 + 'last_login_time' => $currentTime,
  80 + ]);
  81 +
  82 + $row=Db::name("third_party_user")->insert([
  83 + 'openid' => $openid,
  84 + 'user_id' => $userId,
  85 + 'third_party' => 'public',
  86 + 'nickname' => $wechat_user['nickname'],
  87 + 'app_id' => $appId,
  88 + 'last_login_ip' => $ip,
  89 + 'union_id' => '',
  90 + 'last_login_time' => $currentTime,
  91 + 'create_time' => $currentTime,
  92 + 'login_times' => 1,
  93 + 'status' => 1,
  94 + 'more' => json_encode($wechat_user)
  95 + ]);
  96 + if($userId && $row){
  97 + $token = cmf_generate_user_token($userId, 'public');
  98 + $userModel=new UserModel();
  99 + $user=$userModel->getUserInfo(['user_id'=>$userId,'app_id'=>$appId]);
  100 + cmf_update_current_user($user);
  101 + session('token',$token);
  102 + Db::commit();
  103 + }else{
  104 + Db::rollback();
  105 + }
  106 + }
  107 + $target_url=session('target_url');
  108 + $targetUrl = empty($target_url) ? '/' : $target_url;
  109 + header('location:'. $targetUrl);
  110 + }else{
  111 + Log::write('获取微信用户数据失败');
  112 + $this->error('获取微信用户数据失败');
  113 + }
  114 +
31 } 115 }
32 116
33 /** 117 /**
@@ -22,6 +22,9 @@ class TestController extends WeChatBaseController @@ -22,6 +22,9 @@ class TestController extends WeChatBaseController
22 $this->checkWeChatUserLogin(); 22 $this->checkWeChatUserLogin();
23 } 23 }
24 24
  25 + public function index(){
  26 +
  27 + }
25 28
26 29
27 } 30 }
@@ -30,8 +30,8 @@ class UserModel extends Model @@ -30,8 +30,8 @@ class UserModel extends Model
30 if(empty($where)){ 30 if(empty($where)){
31 redirect('/'); 31 redirect('/');
32 } 32 }
33 - $user= Db::name("user_third")->alias('a')  
34 - ->join('__USER__ b','a.user_id=b.id','LEFT') 33 + $user= Db::name("third_party_user")->alias('b')
  34 + ->join('__USER__ a','a.id=b.user_id','LEFT')
35 ->field('a.*,b.openid,b.union_id') 35 ->field('a.*,b.openid,b.union_id')
36 ->where($where) 36 ->where($where)
37 ->find(); 37 ->find();
@@ -80,6 +80,20 @@ function cmf_get_current_user_id() @@ -80,6 +80,20 @@ function cmf_get_current_user_id()
80 } 80 }
81 81
82 /** 82 /**
  83 + * 获取当前登录前台用户openid
  84 + * @return int
  85 + */
  86 +function cmf_get_current_user_openid()
  87 +{
  88 + $sessionOpenId = session('user.openid');
  89 + if (empty($sessionOpenId)) {
  90 + return 0;
  91 + }
  92 +
  93 + return $sessionOpenId;
  94 +}
  95 +
  96 +/**
83 * 返回带协议的域名 97 * 返回带协议的域名
84 */ 98 */
85 function cmf_get_domain() 99 function cmf_get_domain()
@@ -206,17 +206,17 @@ class WeChatBaseController extends BaseController @@ -206,17 +206,17 @@ class WeChatBaseController extends BaseController
206 $userId = cmf_get_current_user_id(); 206 $userId = cmf_get_current_user_id();
207 if (empty($userId)) { 207 if (empty($userId)) {
208 $config = [ 208 $config = [
  209 + 'app_id' => config('wechat_config.app_id'),
  210 + 'secret' => config('wechat_config.secret'),
209 'oauth' => [ 211 'oauth' => [
210 'scopes' => ['snsapi_userinfo'], 212 'scopes' => ['snsapi_userinfo'],
211 - 'callback' => '/oauth_callback', 213 + 'callback' => url('user/index/callback'),
212 ], 214 ],
213 ]; 215 ];
214 -  
215 $app = new Application($config); 216 $app = new Application($config);
216 - $oauth = $app->oauth;  
217 $target_url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; 217 $target_url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
218 session('target_url',$target_url); 218 session('target_url',$target_url);
219 - return $oauth->redirect(); 219 + $app->oauth->redirect()->send();
220 } 220 }
221 } 221 }
222 222
@@ -244,8 +244,8 @@ class Payment @@ -244,8 +244,8 @@ class Payment
244 { 244 {
245 $config = $this->configForPayment($prepayId, false); 245 $config = $this->configForPayment($prepayId, false);
246 246
247 - $config['timestamp'] = $config['timeStamp'];  
248 - unset($config['timeStamp']); 247 +// $config['timestamp'] = $config['timeStamp'];
  248 +// unset($config['timeStamp']);
249 249
250 return $config; 250 return $config;
251 } 251 }