PayHandler.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. /**
  3. * 杉德支付
  4. * User: Ocean
  5. * Date: 2018/4/23
  6. * Time: 10:30
  7. */
  8. namespace common\pay\sand;
  9. use backend\models\Config;
  10. use backend\models\Deposit;
  11. use backend\models\SyncDesposit;
  12. use common\helpers\Utils;
  13. use common\pay\BasePayHandler;
  14. use Yii;
  15. use yii\helpers\VarDumper;
  16. class PayHandler extends BasePayHandler
  17. {
  18. public $payUrl;
  19. public $mid;
  20. public $certPwd;
  21. public $pubCert;
  22. public $priCert;
  23. /**
  24. * @inheritdoc
  25. */
  26. public function init()
  27. {
  28. parent::init();
  29. if ($this->payUrl == null) {
  30. $this->payUrl = Yii::$app->params['sand.payUrl'];
  31. }
  32. if ($this->mid == null) {
  33. $this->mid = Yii::$app->params['sand.mid'];
  34. }
  35. if ($this->certPwd == null) {
  36. $this->certPwd = Yii::$app->params['sand.certPwd'];
  37. }
  38. if ($this->pubCert == null) {
  39. $this->pubCert = __DIR__ . '/cert/sand.cer';
  40. }
  41. if ($this->priCert == null) {
  42. $this->priCert = __DIR__ . '/cert/private.pfx';
  43. }
  44. }
  45. /**
  46. * 去支付
  47. * @param array $params
  48. * @return array
  49. */
  50. public function outPay($deposit, $params)
  51. {
  52. $data['head'] = [
  53. 'version' => '1.0',
  54. 'method' => 'sandpay.trade.pay',
  55. 'accessType' => '1',
  56. 'productId' => '00000007',
  57. 'mid' => $this->mid,
  58. 'channelType' => '07',
  59. 'reqTime' => date('YmdHis', time())
  60. ];
  61. $data['body'] = [
  62. 'orderCode' => $deposit['order_sn'],
  63. 'totalAmount' => sprintf('%012s', $deposit['rmb'] * 100),
  64. 'subject' => 'RJ' . $deposit['order_sn'],
  65. 'body' => 'RJ' . $deposit['order_sn'],
  66. 'txnTimeOut' => date('YmdHis', time()+3600*10),
  67. 'payMode' => 'bank_pc',
  68. 'payExtra' => json_encode(['payType'=> 1,'bankCode' => $params['bankCode']]),
  69. 'clientIp' => isset($params['ip']) ? $params['ip'] : Utils::getClientIp(),
  70. //'notifyUrl' => $this->notifyUrl,
  71. //'frontUrl' => $this->returnUrl,
  72. 'notifyUrl' => 'http://crm.aremeok.com/pay/notify/3',
  73. 'frontUrl' => 'http://crm.aremeok.com/pay/return/3',
  74. 'extend' => ''
  75. ];
  76. $prikey = PayUtils::loadPk12Cert($this->priCert,$this->certPwd);
  77. $sign = PayUtils::sign($data, $prikey);
  78. $postData = [
  79. 'charset' => 'utf-8',
  80. 'signType' => '01',
  81. 'data' => json_encode($data),
  82. 'sign' => $sign
  83. ];
  84. Yii::warning('支付请求参数,' . VarDumper::dumpAsString($data), __METHOD__);
  85. $result = PayUtils::http_post_json( $this->payUrl,$postData);
  86. parse_str(urldecode($result), $arr);
  87. $arr['data'] = str_replace(array(" ","\t","\n","\r"),array('','','',''),$arr['data']);
  88. $data = json_decode($arr['data'],true);
  89. $credential = json_decode($data['body']['credential'],true);
  90. if(isset($credential['params']['orig']) && isset($credential['params']['sign']) ){
  91. $arr['data']= PayUtils::mb_array_chunk($data);
  92. $arr['data'] = str_replace(array("\\\/","\\/","\/"),array("/","/","/"), $arr['data']);
  93. }else {
  94. $data['body']['credential'] = PayUtils::json_encodes($credential);
  95. $arr['data'] = str_replace(array("\\\/","\\/","\/"," "),array("/","/","/","+"),PayUtils::json_encodes($data));
  96. }
  97. $arr['sign'] = preg_replace('/\s/', '+', $arr['sign']);
  98. try{
  99. PayUtils::verify($arr['data'], $arr['sign'], $this->pubCert);
  100. }catch (\Exception $e){
  101. Yii::warning('签名失败,' . VarDumper::dumpAsString($e->getMessage()), __METHOD__);
  102. }
  103. $data = json_decode($arr['data'],320);
  104. // return $data;
  105. if ($data['head']['respCode'] == "000000" ) {
  106. $credential = str_replace(array('"{','}"'),array('{','}'),stripslashes($data['body']['credential']));
  107. }
  108. Yii::warning('支付请求结果,' . VarDumper::dumpAsString($credential), __METHOD__);
  109. return $credential;
  110. return $this->payJump($credential);
  111. }
  112. /**
  113. * 支付跳转HTML拼接
  114. * @param $credential
  115. * @return string
  116. */
  117. public function payJump($credential)
  118. {
  119. $html = <<<eot
  120. <script>
  121. function wap_pay() {
  122. var responseText = $("#credential").text();
  123. //console.log(responseText);
  124. paymentjs.createPayment(responseText, function(result, err) {
  125. //console.log(result);
  126. //console.log(err.msg);
  127. //console.log(err.extra);
  128. });
  129. }
  130. </script>
  131. <div style="display: none" >
  132. <p id="credential">$credential</p>
  133. </div>
  134. eot;
  135. return $html;
  136. }
  137. /**
  138. * 处理异步回调
  139. * @param array $params
  140. * @return array
  141. */
  142. public function handleNotify($params)
  143. {
  144. Yii::warning('支付异步通知参数,' . VarDumper::dumpAsString($params), __METHOD__);
  145. $sign = $params['sign']; //签名
  146. $signType = $params['signType']; //签名方式
  147. $data = stripslashes($params['data']); //支付数据
  148. $charset = $params['charset']; //支付编码
  149. $result = json_decode($data,true); //data数据
  150. Yii::warning('支付异步通知参数sand,' . VarDumper::dumpAsString($result), __METHOD__);
  151. $merOrderId = $result['body']['orderCode'];
  152. if (PayUtils::verify($data, $sign, $this->pubCert)) {
  153. Yii::warning('支付异步通知认证签名成功,' . VarDumper::dumpAsString($data), __METHOD__);
  154. $reuslt = Deposit::find()->where(['order_sn' => $merOrderId])->asArray()->limit(1)->one();
  155. if ($reuslt['type'] != 1) {
  156. $res = Deposit::updateAll(['type' => 1], "order_sn = $merOrderId");
  157. $configData = Config::find()->asArray()->one();
  158. if ($configData['auto_deposit'] == 1 && $res) {
  159. $syncDespositModel = new SyncDesposit();
  160. $syncDespositModel->login = $reuslt['login'];
  161. $syncDespositModel->amount = $reuslt['amount'];
  162. $syncDespositModel->comment = 'Deposit';
  163. $syncDespositModel->memo = $merOrderId;
  164. $syncDespositModel->type = 2;
  165. $syncDespositModel->in_time = time();
  166. $syncDespositModel->save();
  167. }
  168. return true;
  169. }
  170. } else {
  171. Yii::warning('支付异步通知认证签名失败,' . VarDumper::dumpAsString($data), __METHOD__);
  172. return false;
  173. }
  174. return false;
  175. }
  176. /**
  177. * @param bool $success
  178. * @return string
  179. */
  180. public function outNotify($success)
  181. {
  182. if ($success == true) {
  183. return 'respCode=000000';
  184. } else {
  185. return 'fail';
  186. }
  187. }
  188. /**
  189. * 处理同步回调
  190. * @param array $params
  191. * @return array
  192. */
  193. public function handleReturn($params)
  194. {
  195. Yii::warning('支付同步通知参数,' . VarDumper::dumpAsString($params), __METHOD__);
  196. $sign = $params['sign']; //签名
  197. $signType = $params['signType']; //签名方式
  198. $data = stripslashes($params['data']); //支付数据
  199. $charset = $params['charset']; //支付编码
  200. $result = json_decode($data,true); //data数据
  201. $merOrderId = $result['body']['orderCode'];
  202. if (PayUtils::verify($data, $sign, $this->pubCert)) {
  203. $reuslt = Deposit::find()->where(['order_sn' => $merOrderId])->asArray()->limit(1)->one();
  204. if ($reuslt['type'] != 1) {
  205. Deposit::updateAll(['type' => 1], "order_sn = $merOrderId");
  206. $configData = Config::find()->asArray()->one();
  207. if ($configData['auto_deposit'] == 1) {
  208. $syncDespositModel = new SyncDesposit();
  209. $syncDespositModel->login = $reuslt['login'];
  210. $syncDespositModel->amount = $reuslt['amount'];
  211. $syncDespositModel->comment = 'Deposit';
  212. $syncDespositModel->memo = $merOrderId;
  213. $syncDespositModel->type = 2;
  214. $syncDespositModel->in_time = time();
  215. $syncDespositModel->save();
  216. }
  217. return true;
  218. }
  219. } else {
  220. Yii::warning('支付同步通知认证签名失败,' . VarDumper::dumpAsString($params), __METHOD__);
  221. return false;
  222. }
  223. return false;
  224. }
  225. /**
  226. * @param bool $success
  227. */
  228. public function outReturn($success)
  229. {
  230. }
  231. /**
  232. * 退款接口
  233. * @return mixed
  234. */
  235. public function outRefund()
  236. {
  237. $data = array(
  238. 'head' => array(
  239. 'version' => '1.0',
  240. 'method' => 'sandpay.trade.refund',
  241. 'productId' => '00000007',
  242. 'accessType' => '1',
  243. 'mid' => $this->mid,
  244. 'channelType' => '07',
  245. 'reqTime' => date('YmdHis', time())
  246. ),
  247. 'body' => array(
  248. 'orderCode' => 'r'.date('YmdHis').rand(100,999),
  249. 'oriOrderCode' => '201808311527289902',
  250. 'refundAmount' => sprintf('%012s', 3420 * 100),
  251. 'notifyUrl' => 'http://crm.handz-fx.com/test/notify',
  252. 'refundReason' => 'test',
  253. 'extend' => ''
  254. )
  255. );
  256. $prikey = PayUtils::loadPk12Cert($this->priCert,$this->certPwd);
  257. $sign = PayUtils::sign($data, $prikey);
  258. $post = array(
  259. 'charset' => 'utf-8',
  260. 'signType' => '01',
  261. 'data' => json_encode($data),
  262. 'sign' => $sign
  263. );
  264. $result = PayUtils::http_post_json('https://cashier.sandpay.com.cn/gateway/api/order/refund',$post);
  265. parse_str(urldecode($result),$arr);
  266. return $arr['data'];
  267. }
  268. }