Shengpay.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /**
  3. * Shengpay.php UTF-8
  4. * 盛付通微信支付函数
  5. *
  6. * @date : 2017年05月03日上午12:40:40
  7. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  8. * @author : ou <ozf@huosdk.com>
  9. * @version : HUOSDK 7.0
  10. */
  11. namespace huolib\pay\driver;
  12. use huolib\constant\PaywayConst;
  13. use huolib\pay\Driver;
  14. use think\Exception;
  15. use think\Log;
  16. class Shengpay extends Driver {
  17. private $config;
  18. /**
  19. * 构造函数
  20. */
  21. public function __construct() {
  22. // 包含配置文件
  23. if (file_exists(GLOBAL_CONF_PATH."extra/pay/shengpay/config.php")) {
  24. $_config = include GLOBAL_CONF_PATH."extra/pay/shengpay/config.php";
  25. } else {
  26. $_config = array();
  27. }
  28. $this->config = array(
  29. 'url' => "https://api.shengpay.com/html5-gateway/express.htm?page=mobile",
  30. 'senderId' => $_config['senderId'],
  31. 'key' => $_config['key'],
  32. 'rsa_public_key' => $_config['rsa_public_key'],
  33. 'default_mem_real_name' => $_config['default_mem_real_name'],
  34. 'default_mem_mobile' => $_config['default_mem_mobile'],
  35. );
  36. $this->notify_url = $_config['notify_url'];
  37. }
  38. /**
  39. * 移动APP支付函数
  40. *
  41. * @access public
  42. *
  43. */
  44. public function clientPay() {
  45. // TODO: Implement clientPay() method.
  46. }
  47. /**
  48. * 移动端支付函数
  49. *
  50. * @return bool
  51. */
  52. public function mobilePay() {
  53. $_ext['product_id'] = $this->product_id;
  54. $_data = array(
  55. "merchantNo" => $this->config['senderId'],
  56. "charset" => 'UTF-8',
  57. "requestTime" => date("YmdHis", time()),
  58. "outMemberId" => $this->mem_id,
  59. "outMemberRegistTime" => date("YmdHis", $this->mem_reg_time),
  60. "outMemberRegistIP" => $this->getIp(),
  61. "outMemberVerifyStatus" => empty($this->mem_real_name) ? '0' : '1',
  62. "outMemberName" => empty($this->mem_real_name) ? $this->config['default_mem_real_name']
  63. : $this->mem_real_name,
  64. "outMemberMobile" => empty($this->mem_mobile) ? $this->config['default_mem_mobile']
  65. : $this->mem_mobile,
  66. "merchantOrderNo" => $this->order_id,
  67. "productName" => $this->product_name,
  68. "productDesc" => $this->product_desc,
  69. "currency" => 'CNY',
  70. "amount" => $this->real_amount,
  71. "pageUrl" => $this->return_url,
  72. "notifyUrl" => $this->notify_url,
  73. "userIP" => $this->getIp(),
  74. "exts" => json_encode($_ext),
  75. "signType" => "MD5"
  76. );
  77. $_sign = '';
  78. foreach ($_data as $val) {
  79. if ($val !== '') {
  80. $_sign = $_sign.$val.'|';
  81. }
  82. }
  83. $_sign = $_sign.$this->config['key'];
  84. $_data['signMsg'] = strtoupper(md5($_sign));
  85. $html_text = $this->buildRequestForm($_data, "post", $this->config['url']);
  86. header("Content-type:text/html;charset=utf-8");
  87. return $this->clientAjax(PaywayConst::PAYWAY_SHENGPAY, $html_text, 1, 1, 1);
  88. }
  89. /**
  90. * @param $param
  91. * @param $method
  92. * @param $action
  93. *
  94. * @return string
  95. */
  96. function buildRequestForm($param, $method, $action) {
  97. $_sHtml = "<form id='shengpaysubmit' name='shengpaysubmit' action='".$action."' method='".$method."'>";
  98. foreach ($param as $key => $val) {
  99. $_sHtml .= "<input type='hidden' name='".$key."' value='".$val."'/>";
  100. }
  101. $_sHtml = $_sHtml.'</form>';
  102. return $_sHtml;
  103. }
  104. /**
  105. * PC端支付函数
  106. *
  107. * @access public
  108. *
  109. *
  110. */
  111. public function pcPay() {
  112. return $this->mobilePay();
  113. }
  114. /**
  115. * 异步回调函数
  116. *
  117. * @access public
  118. */
  119. public function notifyUrl() {
  120. $_verify_result = $this->verifyNotify();
  121. if ($_verify_result === true) {
  122. /* 平台订单号 */
  123. $_out_trade_no = $_REQUEST["OrderNo"];;
  124. /* 支付宝交易号 */
  125. $_trade_no = $_REQUEST['TransNo'];
  126. /* 交易金额 */
  127. $_amount = $_REQUEST['TransAmount'];
  128. /* 该笔订单的备注、描述、明细等。对应请求时的body参数,原样通知回来。 */
  129. $_ext1 = htmlspecialchars_decode($_REQUEST['Ext1']);
  130. $_ext = json_decode($_ext1, true);
  131. $_product_id = $_ext['product_id'];
  132. // 交易状态
  133. $trade_status = $_REQUEST['TransStatus'];
  134. if ($trade_status === '01') {
  135. $_class = $this->order_class;
  136. $_func = $this->func;
  137. try {
  138. if (class_exists($_class)) {
  139. $_order = new $_class();
  140. $_order->$_func($_product_id, $_out_trade_no, $_trade_no, $_amount, 'shengpay');
  141. } else {
  142. Log::write(
  143. "func=".__FUNCTION__."&class=".__CLASS__."&order_class=".$_class
  144. ."&func=".$_func, LOG::ERROR
  145. );
  146. }
  147. } catch (Exception $_e) {
  148. Log::write(
  149. "func=".__FUNCTION__."&class=".__CLASS__."&order_class=".$_class
  150. ."&func=".$_func."&err=".$_e->getMessage()."&errCode=".$_e->getCode(), LOG::ERROR
  151. );
  152. }
  153. }
  154. echo "OK";
  155. // 下面写验证通过的逻辑 比如说更改订单状态等等 $_POST['out_trade_no'] 为订单号;
  156. } else {
  157. echo "fail";
  158. }
  159. }
  160. /**
  161. * 验证盛付通发来的请求是否合法
  162. *
  163. * @return bool|int 合法:true ,其它false
  164. */
  165. function verifyNotify() {
  166. try {
  167. $Name = $_REQUEST["Name"];
  168. $Version = $_REQUEST["Version"];
  169. $Charset = $_REQUEST["Charset"];
  170. $TraceNo = $_REQUEST["TraceNo"];
  171. $MsgSender = $_REQUEST["MsgSender"];
  172. $SendTime = $_REQUEST["SendTime"];
  173. $InstCode = $_REQUEST["InstCode"];
  174. $OrderNo = $_REQUEST["OrderNo"];
  175. $OrderAmount = $_REQUEST["OrderAmount"];
  176. $TransNo = $_REQUEST["TransNo"];
  177. $TransAmount = $_REQUEST["TransAmount"];
  178. $TransStatus = $_REQUEST["TransStatus"];
  179. $TransType = $_REQUEST["TransType"];
  180. $TransTime = $_REQUEST["TransTime"];
  181. $MerchantNo = $_REQUEST["MerchantNo"];
  182. $ErrorCode = $_REQUEST["ErrorCode"];
  183. $ErrorMsg = $_REQUEST["ErrorMsg"];
  184. $Ext1 = htmlspecialchars_decode($_REQUEST["Ext1"]);
  185. $SignType = $_REQUEST["SignType"];
  186. $SignMsg = $_REQUEST["SignMsg"];
  187. //第一步进行相关的验签操作
  188. $encryptCode = '';
  189. $encryptCode .= $this->isEmpty($Name) ? "" : $Name."|";
  190. $encryptCode .= $this->isEmpty($Version) ? "" : $Version."|";
  191. $encryptCode .= $this->isEmpty($Charset) ? "" : $Charset."|";
  192. $encryptCode .= $this->isEmpty($TraceNo) ? "" : $TraceNo."|";
  193. $encryptCode .= $this->isEmpty($MsgSender) ? "" : $MsgSender."|";
  194. $encryptCode .= $this->isEmpty($SendTime) ? "" : $SendTime."|";
  195. $encryptCode .= $this->isEmpty($InstCode) ? "" : $InstCode."|";
  196. $encryptCode .= $this->isEmpty($OrderNo) ? "" : $OrderNo."|";
  197. $encryptCode .= $this->isEmpty($OrderAmount) ? "" : $OrderAmount."|";
  198. $encryptCode .= $this->isEmpty($TransNo) ? "" : $TransNo."|";
  199. $encryptCode .= $this->isEmpty($TransAmount) ? "" : $TransAmount."|";
  200. $encryptCode .= $this->isEmpty($TransStatus) ? "" : $TransStatus."|";
  201. $encryptCode .= $this->isEmpty($TransType) ? "" : $TransType."|";
  202. $encryptCode .= $this->isEmpty($TransTime) ? "" : $TransTime."|";
  203. $encryptCode .= $this->isEmpty($MerchantNo) ? "" : $MerchantNo."|";
  204. $encryptCode .= $this->isEmpty($ErrorCode) ? "" : $ErrorCode."|";
  205. $encryptCode .= $this->isEmpty($ErrorMsg) ? "" : $ErrorMsg."|";
  206. $encryptCode .= $this->isEmpty($Ext1) ? "" : $Ext1."|";
  207. $encryptCode .= $this->isEmpty($SignType) ? "" : $SignType."|";
  208. if (isset($SignMsg) && isset($SignType) && strcasecmp("RSA", $SignType) == 0) {//RSA验签
  209. $publicKey
  210. = <<<EOT
  211. -----BEGIN PUBLIC KEY-----
  212. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC69veKW1X9GETEFr49gu9PN8w7
  213. H6alWec8wmF8SoP3tqQLAflZp8g83UZPX2UWhClnm53P5ZwesaeSTHkXkSI0iSjw
  214. d27N07bc8puNgB5BAGhJ80KYqTv3Zovl04C8AepVmxy9iFniJutJSYYtsRcnHYyU
  215. NoJai4VXhJsp5ZRMqwIDAQAB
  216. -----END PUBLIC KEY-----
  217. EOT;
  218. //线上的盛付通公钥
  219. $signResult = openssl_verify(
  220. $encryptCode, base64_decode($SignMsg), $publicKey, OPENSSL_ALGO_MD5
  221. ); // 响应的验签
  222. if ($signResult) {
  223. return true;
  224. } else {
  225. return false;
  226. }
  227. } else {
  228. return false;
  229. }
  230. } catch (Exception $e) {
  231. Log::write(
  232. "shengpay sign verify err=".$e->getMessage()."&errCode=".$e->getCode(), LOG::ERROR
  233. );
  234. }
  235. return false;
  236. }
  237. private function isEmpty($var) {
  238. if (isset($var) && $var != "") {
  239. return false;
  240. } else {
  241. return true;
  242. }
  243. }
  244. /**
  245. * 接收支付成功回调
  246. *
  247. * @access public
  248. *
  249. *
  250. */
  251. public function returnUrl() {
  252. $_status = 2;
  253. return $this->clientAjax(PaywayConst::PAYWAY_SHENGPAY, '22', $_status, 1, 1);
  254. }
  255. /**
  256. * 查询订单
  257. *
  258. * @access public
  259. *
  260. * @param string $order_id 商户系统内部订单号
  261. * @param string $transaction_id 第三方支付的订单号
  262. * @param null $ext 扩展信息
  263. *
  264. */
  265. public function orderQuery($order_id, $transaction_id, $ext = null) {
  266. // TODO: Implement orderQuery() method.
  267. }
  268. }