APP支付(支付宝和微信生成客户端签名及回调验签)

 

<?php
namespace Pn\Controller;
use Think\Controller\RestController;
class PayController extends RestController{
    public function __construct(){
        import('Vendor.WePay.WeEncryption');
        import('Vendor.WePay.Curl');
    }
    public function Payment(){
        $arr['appid'] = $_POST['appid'];//应用id
        $arr['userdid'] = $_POST['userdid'];//登录用户id
        $arr['paytype'] = $_POST['paytype'];//支付方式
        $arr['productid'] = $_POST['productid'];//商品id
        $arr['time'] = $_POST['time'];
        $sign = $_POST['sign'];//安全验证sign
        $vsign = strrank($arr);//签名加密
        
        if($vsign!=$sign){
            $return['respCode'] = 1001;
            $return['msg'] = "签名错误";
            $this -> response($return,'json');//返回数据
            exit();
        }else{
            switch ($_POST["paytype"]){
                case 1://支付宝
                    $data["signdata"] = $this->alipay();
                    echo json_encode($data);
                break;
                case 2://微信支付
                    $data = $this->wechatpay($_POST['appid'],$_POST['userdid'],$_POST['productid']);
                    echo $data;
                break;
                default:
                $return["respCode"] = "error"; 
                $return['msg'] = "支付方式错误";
                $this -> response($return,'json');//返回数据
                exit();
            }
        }
    }
    /**
     * 微信APP客户端支付
     */
    public function wechatpay($appid,$userdid,$productid){
       $WeEncryption = new \WeEncryption();	//实例化传输类;
       switch ($productid){
           case 1://季付商品(¥100)
               $body = "陪你季付VIP";//商品描述
               $total_fee = "100.00";//总金额
           break;
           case 2://月付商品(¥50)
               $body = "陪你月付VIP";//商品描述
               $total_fee = "50.00";//总金额
           break;
       }
       $out_trade_no = date("YmdHis").rand(10,100);//商户订单号
       $spbill_create_ip = getclientip();//终端IP

       $data = array(
           'body'				=>	$body,
           'out_trade_no'		=>	$out_trade_no,
           'total_fee'			=>	$total_fee,
           'spbill_create_ip'	=>	$spbill_create_ip,
       );
       
       $encpt = $WeEncryption::getInstance();	//实例化签名类
       $url = "http://xxxx.com/Pay/wx_notify_verify";
       $encpt->setNotifyUrl($url);			//设置异步通知地址
       
       $curl = new \Curl();				//实例化传输类;
       $xml_data = $encpt->sendRequest($curl, $data);		//发送请求

       $postObj = $encpt->xmlToObject($xml_data);			//解析返回数据
       if ($postObj === false) {
           echo 'FAIL';
           exit;
       }
       if ($postObj->return_code == 'FAIL') {
           echo $postObj->return_msg;
       } else {
           $resignData = array(
               'appid'			=>	$postObj->appid,
               'partnerid'		=>	$postObj->mch_id,
               'prepayid'		=>	$postObj->prepay_id,
               'noncestr'		=>	$postObj->nonce_str,
               'timestamp'		=>	time(),
               'package'	=>	'Sign=WXPay'
           );
           $sign = $encpt->getClientPay($resignData);
           $resignData['sign'] = $sign;
           return  json_encode($resignData);
       }
    }
    /**
     * 微信App支付回调
     */
    public function wx_notify_verify(){
        $WeEncryption = new \WeEncryption();	//实例化传输类;
        $encpt = $WeEncryption::getInstance();
        $obj = $encpt->getNotifyData();
        if ($obj === false) {
            exit;
        }
        if ($obj) {
            $data = array(
                'appid'				=>	$obj->appid,
                'mch_id'			=>	$obj->mch_id,
                'nonce_str'			=>	$obj->nonce_str,
                'result_code'		=>	$obj->result_code,
                'openid'			=>	$obj->openid,
                'trade_type'		=>	$obj->trade_type,
                'bank_type'			=>	$obj->bank_type,
                'total_fee'			=>	$obj->total_fee,
                'cash_fee'			=>	$obj->cash_fee,
                'transaction_id'	=>	$obj->transaction_id,
                'out_trade_no'		=>	$obj->out_trade_no,
                'time_end'			=>	$obj->time_end
            );
            $sign = $encpt->getSign($data);
            if ($sign == $obj->sign) {//验签通过
                $reply = "<xml>
					<return_code><![CDATA[SUCCESS]]></return_code>
					<return_msg><![CDATA[OK]]></return_msg>
				</xml>";
                echo $reply;
                exit;
            }else{
                $reply = "<xml>
					<return_code><![CDATA[FAIL]]></return_code>
					<return_msg><![CDATA[NO]]></return_msg>
				</xml>";
                echo $reply;
                exit;
            }
        }
    }
    
    /**
     * https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.NgdeQA&treeId=59&articleId=103663&docType=1
     * 服务端生成app支付使用的参数以及签名
     * @param $params <Array>
     * @return <Array>
    */
    public function alipay(){ 

        $ali = array(
          'service' => 'mobile.securitypay.pay',
          'partner' => 'xxxx',
          '_input_charset' => 'utf-8',
          'sign_type' => 'RSA',
          'sign' => '',
          'notify_url' => 'http://xxxxxxxx.com/Pay/alipay_notify_url',//回调地址
          'out_trade_no' => date("YmdHis").rand(10,100),//商户网站唯一订单号
          'subject' => '测试',//商品名称
          'payment_type' => 1,//支付类型
          'seller_id' => 'lql@jieku.com',//支付宝账号
          'total_fee' => '0.01',//总金额
          'body' => 'Iphone6 16G',//商品详情
        );
        
        $ali = self::argSort($ali);
        $str = '';
        
        foreach($ali as $key=>$val){
            if($key == 'sign_type' || $key == 'sign'){
                continue;
            }else{
                if($str == ''){
                    $str = $key.'='.'"'.$val.'"';
                }else{
                    $str = $str.'&'.$key.'='.'"'.$val.'"';
                }
            }
        }        
                               
        $sign = urlencode(self::sign($str));
        $str = $str.'&sign='.'"'.$sign.'"'.'&sign_type='.'"'.$ali['sign_type'].'"';//传给支付宝接口的数据
        return $str;
    }
    
    /**
     * 准备签名参数
     */
    public function argSort($para) {
        ksort($para);
        reset($para);
        return $para;
    }
    
   /**
     * 生成请求参数的签名
     * @param $params <Array>
     * @return <String>
     *
   */
   public function sign($data) {
        //读取私钥文件
        $priKey = file_get_contents('./Public/key/rsa_private_key.pem');//私钥文件路径
        //转换为openssl密钥,必须是没有经过pkcs8转换的私钥
        $res = openssl_get_privatekey($priKey);
        //调用openssl内置签名方法,生成签名$sign
        openssl_sign($data, $sign, $res);
        //释放资源
        openssl_free_key($res);
        //base64编码
        $sign = base64_encode($sign);
        return $sign;
    }
    
   /**
     * 支付宝回调地址
    */
    public function alipay_notify_url(){

        $orderpay = M("orderpay");
        $async = empty($_GET);
        $data = $async ? $_POST : $_GET;
  
        if (empty($data)) {
            return FALSE;
        }

        $signValid = $this->verifyParameters($data, $data["sign"]);//验签
        $notify_id = isset($data['notify_id']) ? $data['notify_id'] : NULL;
        
        //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)
        $responseTxt = 'true';
        if (!empty($notify_id)) {
            $responseTxt = $this->verifyFromServer($notify_id);
        }

        if($signValid && preg_match("/true$/i", $responseTxt)){//验证成功
            if($_POST['trade_status'] == 'TRADE_FINISHED'){
                
               $_POST["createdatetime"] = time();
               
               if($orderpay->create()){
                    $orderpay->add();
                    echo "success";
               }else{
                   echo "fail";//验证失败
               }
            }
            else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                $_POST["createdatetime"] = time();
                if($orderpay->create()){
                    $orderpay->add();
                    echo "success";
                }else{
                    echo "fail";//验证失败
                }
            }
        }else{
            echo "fail";//验证失败
        }
    }
    /**
     * 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串
     * @param unknown $params
     * @param unknown $sign
     * @return boolean
     */
    function verifyParameters($params, $sign) {
        
        $public_key_path = './Public/key/alipay_public_key.pem';//公钥(合作伙伴)

        $params = $this->filterSignParameter($params);
        ksort($params);
        reset($params);
    
        $content = urldecode(http_build_query($params));
       
        return $this->rsaVerify($content, $public_key_path, $sign);

    }
    /**
     * 过滤参数,去除sign/sign_type参数
     * @param $params
     * @return <Array>
     */
    function filterSignParameter($params) {
        $result = array();
        foreach ($params as $key => $value) {
            if ($key != 'sign' && $key != 'sign_type' && $value) {
                $result[$key] = $value;
            }
        }
        return $result;
    }
    /**
     * RSA验签,注意验签的公钥是支付宝的公钥,不是自己生成的rsa公钥,可以在淘宝的demo中获得
     * @param $data string 待签名数据
     * @param $ali_public_key_path string 支付宝的公钥文件路径
     * @param $sign string 要校对的的签名结果
     * @return <Boolean> 验证结果
     * @throws Exception
     */
    function rsaVerify($data, $ali_public_key_path, $sign) {
        $pubKey = file_get_contents($ali_public_key_path);
        $res = openssl_get_publickey($pubKey);
        if(!$res){
            throw new \Exception('公钥格式错误');
        }
        $result = (bool)openssl_verify($data, base64_decode($sign), $res);
        openssl_free_key($res);
        return $result;
    }
    function verifyFromServer($notify_id) {
        $transport = "http";
        $partner = "xxxxxxxxxxx";
        $cacert = "./Public/key/cacert.pem";
        $transport = strtolower(trim($transport));
        $partner = trim($partner);
        $veryfy_url = "http://notify.alipay.com/trade/notify_query.do?partner=$partner¬ify_id=$notify_id";
        $curl = curl_init($veryfy_url);
        curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
        curl_setopt($curl, CURLOPT_CAINFO, $cacert);//证书地址
        $responseText = curl_exec($curl);
        // var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容
        curl_close($curl);
        return $responseText;
    }
      /**格式化公钥
    * $pubKey PKCS#1格式的公钥串
    * return pem格式公钥, 可以保存为.pem文件
    */
   function formatPubKey($pubKey) {
       $fKey = "-----BEGIN PUBLIC KEY-----\n";
       $len = strlen($pubKey);
       for($i = 0; $i < $len; ) {
           $fKey = $fKey . substr($pubKey, $i, 64) . "\n";
           $i += 64;
       }
       $fKey .= "-----END PUBLIC KEY-----";
       return $fKey;
   }
}
问题咨询QQ1370373713http://blog.csdn.net/apensu/article/details/46945193

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Java 语言中,你可以使用支付宝提供的 SDK 来实现支付宝支付回调验签。以下是一个简单的示例代码: 1. 首先,确保你已经引入了支付宝的 SDK,例如 alipay-sdk-java。 2. 在你的回调接口中,获取支付宝返回的参数。 3. 使用支付宝提供的 DefaultAlipayClient 类创建一个 AlipayClient 对象,传入相应的配置参数。 4. 创建一个 AlipaySignature 类的实例,使用该实例的 verify 方法进行签名验证。 5. 根据签名验证的结果进行相应的处理。 示例代码: ```java import com.alipay.api.AlipayApiException; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.internal.util.AlipaySignature; import javax.servlet.http.HttpServletRequest; import java.util.Map; public class AlipayCallbackHandler { public void handleCallback(HttpServletRequest request) { // 获取支付宝返回的参数 Map<String, String[]> parameterMap = request.getParameterMap(); Map<String, String> params = new HashMap<>(); for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) { String key = entry.getKey(); String[] values = entry.getValue(); if (values.length > 0) { params.put(key, values[0]); } } // 配置参数 String gatewayUrl = "https://openapi.alipay.com/gateway.do"; String appId = "your app id"; String privateKey = "your private key"; String charset = "UTF-8"; String alipayPublicKey = "alipay public key"; String signType = "RSA2"; // 创建 AlipayClient 对象 DefaultAlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", charset, alipayPublicKey, signType); // 验证签名 try { boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayPublicKey, charset, signType); if (verifyResult) { // 签名验证成功,根据支付结果进行处理 String tradeStatus = params.get("trade_status"); if ("TRADE_SUCCESS".equals(tradeStatus)) { // 修改订单状态、发送邮件等 } } else { // 签名验证失败,处理异常情况 } } catch (AlipayApiException e) { // 验证过程中发生异常,处理异常情况 } } } ``` 在上述示例代码中,需要将 "your app id"、"your private key"、"alipay public key" 替换为你自己的配置参数。另外,根据你的具体业务需求,可以在签名验证成功后进行相应的处理,例如修改订单状态、发送邮件等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luke·Wong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值