PaysController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. namespace App\Http\Controllers\Wechat\Pay;
  3. use EasyWeChat\Payment\Order;
  4. use App\Http\Requests;
  5. use App\Http\Controllers\WechatController;
  6. use App\Http\Controllers\Controller;
  7. use Illuminate\Http\Request;
  8. use EasyWeChat\Foundation\Application;
  9. use EasyWeChat\Message\Text;
  10. /**
  11. * 微信支付
  12. */
  13. class PaysController extends WechatController
  14. {
  15. public $payment;
  16. public $options;
  17. public function __construct()
  18. {
  19. $this->options = array();
  20. parent::__construct();
  21. }
  22. function set_options($appid){
  23. $this->options = [];
  24. return $this->options;
  25. }
  26. /**
  27. * 接收微信回调
  28. * @return Response
  29. */
  30. public function index(Request $request)
  31. {
  32. // if($request->has('echostr')) exit($request->input('echostr'));echostr
  33. v('start_check_sign');
  34. v($request->all());
  35. $echostr = $request->get('echostr');
  36. if(!empty($echostr)){
  37. echo $echostr;exit();
  38. }
  39. if(!$this->checkSignature($request)){
  40. v('return_fail:');
  41. // exit;
  42. }else{
  43. v('return_success:');
  44. }
  45. v('start_setmessagehander:'.$this->local_test);
  46. if(env('DEVELOP_MODE') == 'local'){
  47. $notify = $this->get_fake_data();
  48. $res = $this->deal_callback($notify,true);
  49. }else{
  50. v('start-payment');
  51. $response = $this->payment->handleNotify(function($notify, $successful){
  52. return $this->deal_callback($notify,$successful);
  53. });
  54. return $response;
  55. }
  56. v('last_echo');
  57. }
  58. function deal_callback($notify,$successful){
  59. v('wxpay_deal_callback_in');
  60. v('notify:');v($notify);v('successful:'.$successful);
  61. return true; // 返回处理完成
  62. }
  63. function notify(Request $request){
  64. v('wxpay_notify');v($request->all());
  65. echo 'success';
  66. }
  67. /**
  68. * @api {get} /create_wxpay_order?body=:body&detail=:detail&total_fee=:total_fee&open_id=:open_id 创建交易订单
  69. * @apiName create_wxpay_order
  70. * @apiGroup Bag
  71. * @apiDescription
  72. * 创建订单,返回的是支付的config数组
  73. * @apiParam {String} body 支付简要描述.
  74. * @apiParam {String} detail 支付详细描述.
  75. * @apiParam {String} total_fee 支付金额(单位分).
  76. * @apiParam {String} open_id 用户open_id.
  77. * @apiSuccess {String} appId .
  78. * @apiSuccess {String} nonceStr .
  79. * @apiSuccess {String} package .
  80. * @apiSuccess {String} signType .
  81. * @apiSuccess {String} paySign .
  82. * @apiSuccess {String} timestamp .
  83. */
  84. /**
  85. http://auth.aizhuishu.com/pay/create_wxpay_order?out_trade_no=2017120917571001&body=%E6%B5%8B%E8%AF%95%E4%B8%8B%E8%80%8C%E5%B7%B2&detail=%E6%B5%8B%E8%AF%95%E4%B8%8B%E7%88%B1%E8%BF%BD%E4%B9%A6%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98&total_fee=1&appid=wx2538d0bc2ea3089e&open_id=oc5mg0xkIlKEMDkQL39RSLXhfatM&notify_url=http%3A%2F%2Fpay.aizhuishu.com%2Fpay%2Fnotify&timestamp=1512788565&sign=c2da337c73393dbd51ef2d58559daa15
  86. http://zydy/pay/create_wxpay_order?out_trade_no=2017120917571001&body=%E6%B5%8B%E8%AF%95%E4%B8%8B%E8%80%8C%E5%B7%B2&detail=%E6%B5%8B%E8%AF%95%E4%B8%8B%E7%88%B1%E8%BF%BD%E4%B9%A6%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98&total_fee=1&appid=wx2538d0bc2ea3089e&open_id=oc5mg0xkIlKEMDkQL39RSLXhfatM&notify_url=http%3A%2F%2Fpay.aizhuishu.com%2Fpay%2Fnotify&timestamp=1512788565&sign=c2da337c73393dbd51ef2d58559daa15
  87. http://zydy/pay/create_wxpay_order?out_trade_no=2017120917571002&body=%E6%B5%8B%E8%AF%95%E4%B8%8B%E8%80%8C%E5%B7%B2&detail=%E6%B5%8B%E8%AF%95%E4%B8%8B%E7%88%B1%E8%BF%BD%E4%B9%A6%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98&total_fee=1&appid=wx2538d0bc2ea3089e&open_id=oc5mg0xkIlKEMDkQL39RSLXhfatM&notify_url=http%3A%2F%2Fauth.aizhuishu.com%2Fpay%2Fnotify&timestamp=1512788565&sign=c2da337c73393dbd51ef2d58559daa15
  88. */
  89. function create_wxpay_order(Request $request){
  90. $result = array('code'=>1,'msg'=>'','data'=>'');
  91. $body = $request->get('body');
  92. $detail = $request->get('detail');
  93. $total_fee = $request->get('total_fee');
  94. $open_id = $request->get('open_id');
  95. $appid = $request->get('appid');
  96. $out_trade_no = $request->get('out_trade_no');
  97. $attach = $request->get('attach');
  98. $is_call_pay = $request->get('is_call_pay');//是否直接唤起
  99. $notify_url = $request->get('notify_url');
  100. $redirect_url = $request->get('redirect_url');
  101. if(empty($open_id) || empty($notify_url) || empty($redirect_url) || empty($appid) || empty($out_trade_no)){
  102. $result['code'] = 0;
  103. $result['msg'] = 'invalid param';
  104. v('invalid_param_open_id:'.$open_id);
  105. json_echo($result);
  106. }
  107. $this->set_options($appid);
  108. if(empty($this->options)){
  109. $result['code'] = 0;
  110. $result['msg'] = 'invalid appid';
  111. v('invalid_param_open_id:'.$open_id.' appid:'.$appid);
  112. json_echo($result);
  113. }
  114. $check_result = $this->check_sign_params($request);
  115. if($check_result['code'] == 0){
  116. $result['code'] = 0;
  117. $result['msg'] = $check_result['msg'];
  118. json_echo($result);
  119. }
  120. $attributes = [
  121. 'trade_type' => 'JSAPI', // JSAPI,NATIVE,APP...
  122. 'body' => $body,
  123. 'detail' => $detail,
  124. 'out_trade_no' => $out_trade_no,
  125. 'total_fee' => $total_fee, // 单位:分
  126. 'attach' => $attach , // 附加参数,127字符
  127. 'openid' => $open_id, // trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识,
  128. // ...
  129. ];
  130. v('attributes:');v($attributes);
  131. $order = new Order($attributes);
  132. $this->options['payment']['notify_url'] = urldecode($notify_url);
  133. $app = new Application($this->options);
  134. $this->payment = $app->payment;
  135. // 创建订单
  136. $prepare_result = $this->payment->prepare($order);
  137. v('$prepare_result:');v($prepare_result);
  138. $prepayId = '';
  139. if ($prepare_result->return_code == 'SUCCESS' && $prepare_result->result_code == 'SUCCESS'){
  140. $prepayId = $prepare_result->prepay_id;
  141. }else{
  142. $result['code'] = 0;
  143. $result['msg'] = 'prepare order fail';
  144. v('prepare_order_fail:'.$attributes['out_trade_no']);
  145. json_echo($result);
  146. }
  147. v('prepayId:'.$prepayId);
  148. $config = $this->payment->configForJSSDKPayment($prepayId); // 返回数组
  149. v('config:');v($config);
  150. // 状态没问题则创建订单
  151. if(!empty($config)){
  152. }else{
  153. $result['code'] = 0;
  154. $result['msg'] = 'configForJSSDKPayment fail';
  155. v('configForJSSDKPayment_fail:'.$attributes['out_trade_no']);
  156. json_echo($result);
  157. }
  158. $result['data'] = $config;
  159. v('create_result:');v($result);
  160. if(!$is_call_pay){
  161. json_echo($result);
  162. }else{
  163. $pay_info = array();
  164. $pay_info['appId'] = $config['appId'];
  165. $pay_info['timeStamp'] = $config['timestamp'];
  166. $pay_info['nonceStr'] = $config['nonceStr'];
  167. $pay_info['package'] = $config['package'];
  168. $pay_info['paySign'] = $config['paySign'];
  169. $pay_info['pay_redirect_url'] = $redirect_url;
  170. return view('pay.order.index',compact('pay_info'));
  171. }
  172. }
  173. /**
  174. * @api {get} /bag/create_wxpay_order_refund?out_trade_no=:out_trade_no&timestamp=:timestamp&sign=:sign 交易退款
  175. * @apiName create_wxpay_order_refund
  176. * @apiGroup Bag
  177. * @apiDescription
  178. * 创建微信退款订单(暂时不需要)
  179. * @apiParam {String} out_trade_no 支付订单号.
  180. * @apiParam {String} timestamp 时间戳.
  181. * @apiParam {String} sign 签名.
  182. */
  183. // 暂时不管:可能会遇到这个问题,交易未结算资金不足,请使用可用余额退款
  184. function create_wxpay_order_refund(Request $request){
  185. $result = array('code'=>1,'msg'=>'','data'=>'');
  186. $out_trade_no = $request->get('out_trade_no');
  187. $timestamp = $request->get('timestamp');
  188. $sign = $request->get('sign');
  189. if(empty($out_trade_no) || empty($timestamp) || empty($sign)){
  190. $result['code'] = 0;
  191. $result['msg'] = 'invalid param';
  192. v('invalid_param_out_trade_no:'.$out_trade_no);
  193. json_echo($result);
  194. }
  195. $param = array();
  196. $param['out_trade_no'] = $out_trade_no;
  197. $param['timestamp'] = $timestamp;
  198. $my_sign = $this->WxSign->get_sign($param);
  199. if($sign != $my_sign){
  200. $result['code'] = 0;
  201. $result['msg'] = 'invalid sign';
  202. v('create_wxpay_order_refund_sign_error:'.$out_trade_no.' $sign:'.$sign.' $my_sign:'.$my_sign);
  203. json_echo($result);
  204. }
  205. $refund_no = get_orderno_by_time();
  206. $total_fee = $wx_pay_record->total_fee;
  207. $refund_fee = $total_fee;
  208. $open_id = $wx_pay_record->open_id;
  209. v('refund:out_trade_no:'.$out_trade_no.' refund_no:'.$refund_no.' total_fee:'.$total_fee.' refund_fee:'.$refund_fee.' open_id:'.$open_id);
  210. $refund_result = $this->payment->refund($out_trade_no, $refund_no, $total_fee, $total_fee);
  211. // $refund_result = $this->get_fake_refund_data();
  212. v('$refund_result');v($refund_result);
  213. if ($refund_result->return_code == 'SUCCESS' && $refund_result->result_code == 'SUCCESS'){
  214. $refund_result->open_id = $open_id;
  215. // WxRefundRecord::save_wx_refund_record($refund_result);
  216. }else{
  217. $result['code'] = 0;
  218. $result['msg'] = 'refund fail';
  219. v('refund_fail:'.$out_trade_no);
  220. json_echo($result);
  221. }
  222. $result['data'] = 'refund success';
  223. json_echo($result);
  224. }
  225. /**
  226. * 查询退款结果
  227. */
  228. //http://wread/pay/query_refund?out_trade_no=201705171025468688026&timestamp=12&sign=2cb2d01ae367265a1dbdd663e1d32415
  229. function query_refund(Request $request){
  230. $out_trade_no = $request->get('out_trade_no');
  231. $timestamp = $request->get('timestamp');
  232. $sign = $request->get('sign');
  233. if(empty($out_trade_no) || empty($timestamp) || empty($sign)){
  234. $result['code'] = 0;
  235. $result['msg'] = 'invalid param';
  236. v('invalid_param_out_trade_no:'.$out_trade_no);
  237. json_echo($result);
  238. }
  239. $param = array();
  240. $param['out_trade_no'] = $out_trade_no;
  241. $param['timestamp'] = $timestamp;
  242. $my_sign = $this->WxSign->get_sign($param);
  243. if($sign != $my_sign){
  244. $result['code'] = 0;
  245. $result['msg'] = 'invalid sign';
  246. v('query_refund_sign_error:'.$out_trade_no.' $sign:'.$sign.' $my_sign:'.$my_sign);
  247. json_echo($result);
  248. }
  249. $query_refund_result = $this->payment->queryRefund($out_trade_no);
  250. v('query_refund_result:');v($query_refund_result);
  251. }
  252. private function checkSignature($request)
  253. {
  254. $signature = $request->get('signature');
  255. $timestamp = $request->get('timestamp');
  256. $nonce = $request->get('nonce');
  257. $echostr = $request->get('echostr');
  258. // $token = 'd4352c0225d5da500b176cf3464e9822';
  259. $tmpArr = array($this->token, $timestamp, $nonce);
  260. sort($tmpArr, SORT_STRING);
  261. $tmpStr = implode( $tmpArr );
  262. $tmpStr = sha1( $tmpStr );
  263. v('$tmpStr:'.$tmpStr);
  264. if( $tmpStr == $signature ){
  265. return true;
  266. }else{
  267. return false;
  268. }
  269. }
  270. function get_fake_data(){
  271. $message = new \stdClass();
  272. $message->out_trade_no = '201705261556493599255';
  273. return $message;
  274. }
  275. //"return_code":"SUCCESS","return_msg":"OK","appid":"wx27c650c50a36cc46","mch_id":"1468320702","nonce_str":"DNMs2GFrmZilOy8w","sign":"B1F25F070184B94202D67D3722057850","result_code":"SUCCESS","transaction_id":"4005562001201705171197097763","out_trade_no":"201705171025468688026","out_refund_no":"201705181118027912184","refund_id":"50000302912017051801101133889","refund_channel":null,"refund_fee":"500","coupon_refund_fee":"0","total_fee":"500","cash_fee":"500","coupon_refund_count":"0","cash_refund_fee":"500"}
  276. function get_fake_refund_data(){
  277. $refund_result = new \stdClass();
  278. $refund_result->return_code = 'SUCCESS';
  279. $refund_result->result_code = 'SUCCESS';
  280. $refund_result->transaction_id = '4005562001201705171197097763';
  281. $refund_result->out_trade_no = '201705171025468688026';
  282. $refund_result->out_refund_no = '201705181118027912184';
  283. $refund_result->refund_id = '50000302912017051801101133889';
  284. $refund_result->refund_channel = '';
  285. $refund_result->refund_fee = '500';
  286. $refund_result->coupon_refund_fee = '0';
  287. $refund_result->total_fee = '500';
  288. $refund_result->cash_fee = '500';
  289. $refund_result->coupon_refund_count = '0';
  290. $refund_result->cash_refund_fee = '500';
  291. $refund_result->return_msg = 'OK';
  292. $refund_result->appid = 'wx27c650c50a36cc46';
  293. $refund_result->mch_id = '1468320702';
  294. $refund_result->nonce_str = 'DNMs2GFrmZilOy8w';
  295. $refund_result->sign = 'B1F25F070184B94202D67D3722057850';
  296. return $refund_result;
  297. }
  298. }