lokielse / omnipay-alipay-example

A simple example
28 stars 11 forks source link

调试错误,请回到请求来源地,重新发起请求。 错误代码 ILLEGAL_SIGN #4

Closed FlowerWrong closed 9 years ago

FlowerWrong commented 9 years ago

问题描述

调试错误,请回到请求来源地,重新发起请求。 错误代码 ILLEGAL_SIGN

网上答案

网上说编码问题 我设置 $gateway->setInputCharset('utf-8');

结果

跳转后页面是这样的gb2312

<title>支付宝 - 网上支付 安全快速!</title>
<meta content="text/html; charset=gb2312" http-equiv="Content-Type">
<meta content="ie=7" http-equiv="x-ua-compatible">
<meta content="中国最大的第三方电子支付服务提供商" name="description">
<meta content="网上购物/网上支付/安全支付/安全购物/购物,安全/支付/支付宝,在线/付款,收款/网上,贸易/网上贸易" name="keywords">
lokielse commented 9 years ago

请把必要的代码贴上来看看(账号和密钥可以不贴)

FlowerWrong commented 9 years ago

基本配置都有,按照demo做的,账户那些都配置并且核对了几次,cacert.pem也有。

路由

/*------------------------<支付路由>------------------------------*/
/*-参考https://github.com/lokielse/omnipay-alipay-example-*/
Route::get('/alipay/cart', 'AlipayController@getCart');
Route::post('/alipay/pay', 'AlipayController@postPay');
/**
 * pay success client return.
 */
Route::get('/alipay/return', 'AlipayController@getPayReturn');
/**
 * pay success server notify.(!!!not support local-test server)
 */
Route::post('/alipay/notify', 'AlipayController@postPayNotify');
/*------------------------</支付路由>------------------------------*/

控制器

<?php
use Omnipay\Omnipay;
class AlipayController extends \BaseController {
  public function getCart() {
    return Response::view('pay.cart', array());
  }
  public function postPay()
  {
    $return_url = Input::getUriForPath('/alipay/return');
    $notify_url = Input::getUriForPath('/alipay/notify');
    $gateway = Omnipay::create('Alipay_Express');
    $gateway->setPartner(Config::get('pay.alipay.id'));
    $gateway->setKey(Config::get('pay.alipay.key'));
    $gateway->setSellerEmail(Config::get('pay.alipay.email'));
    $gateway->setNotifyUrl($notify_url);
    $gateway->setReturnUrl($return_url);
    $gateway->setInputCharset('utf-8');
    # new order
    # db
    $order = array(
      'out_trade_no' => sprintf('%d%d', time(), mt_rand(1000, 9999)),
      'subject'      => 'test888', //order title
      'total_fee'    => Input::get('total_fee'), //order total fee
    );
    $response = $gateway->purchase($order)->send();
    # return a payto_url, and client redirect to alipay.
    return Response::json(['payto_url' => $response->getRedirectUrl()]);
  }
  public function getPayReturn() {
    //dd(Input:all());
    $gateway = Omnipay::create('Alipay_Express');
    $gateway->setPartner(Config::get('pay.alipay.id'));
    $gateway->setKey(Config::get('pay.alipay.key'));
    $gateway->setSellerEmail(Config::get('pay.alipay.email'));
    $gateway->setInputCharset('utf-8');
    $options['request_params'] = Input::all();
    $options['ca_cert_path']   = storage_path() . '/cert/cacert.pem';
    $options['sign_type']      = 'MD5';
    $request                   = $gateway->completePurchase($options)->send();
    $debug_data                = $request->getData();
    if ($request->isSuccessful()) { //
        $out_trade_no = Input::get('out_trade_no');
        #####
        # eg: $order = Order::find($out_trade_no);
        # !!!!you should check your order status here for duplicate request.
        #####
        # Event::fire('alipay.pay_success', ['out_trade_no' => $out_trade_no, 'meta' => Input::all()]);
        header("Content-type:text/html;charset=utf-8");
        echo 'hey! pay verify success! make a redirect with client or server here';
    } else {
        echo 'hey! pay verify fail! make a redirect with client or server here';
    }
  }
  public function postPayNotify() {
    $gateway = Omnipay::create('Alipay_Express');
    $gateway->setPartner(Config::get('pay.alipay.id'));
    $gateway->setKey(Config::get('pay.alipay.key'));
    $gateway->setSellerEmail(Config::get('pay.alipay.email'));
    $options['request_params'] = Input::all();
    $options['ca_cert_path']   = storage_path() . '/cert/cacert.pem';
    $options['sign_type']      = 'MD5';
    $request                   = $gateway->completePurchase($options)->send();
    $debug_data                = $request->getData();
    if ($request->isSuccessful()) {
        $out_trade_no = Input::get('out_trade_no');
        #####
        # eg: $order = Order::find($out_trade_no);
        # !!!!you should check your order status here for duplicate request.
        #####
        Event::fire('alipay.pay_success', ['out_trade_no' => $out_trade_no, 'meta' => Input::all()]);
        die('success'); //it should be string 'success'
    } else {
        die('fail'); //it should be string 'fail'
    }
  }
}
lokielse commented 9 years ago

刚我用该omnipay-alipay-example工程的源码测试了一下,是能成功跳转到支付页面的哦!

请你检查一下postPay方法里面的代码,特别的是Config::get取得的各项参数和Input::get取得的参数, 是否有误或为空。

另外你可以将$response->getRedirectUrl()的结果打印出来看看哦, 正常情况下应如下格式:

https://mapi.alipay.com/gateway.do?service=create_direct_pay_by_user&partner=20880XXXX480381&payment_type=1&notify_url=http%3A%2F%2Fomnipay-alipay-example.dev%2Fpay%2Falipay%2Fnotify.do&return_url=http%3A%2F%2Fomnipay-alipay-example.dev%2Fpay%2Falipay%2Freturn.do&seller_email=example%40163.com&out_trade_no=14332230893351&subject=test&total_fee=0.01&_input_charset=utf-8&sign=0ada7afdc59ccc480fdd0ed62d2c3090&sign_type=MD5
lokielse commented 9 years ago

另外$gateway = Omnipay::create('Alipay_Express'); 中的支付服务Alipay_Express为PC端的及时到账服务,请确认你签约的是这个产品哦!

FlowerWrong commented 9 years ago

Thx very much! 我的key错了一个字符。

lokielse commented 9 years ago

[抠鼻]

mingyun commented 9 years ago

请问是否支持APP端的服务端异步通知,看example里没有?

lokielse commented 9 years ago

@mingyun

ExampleReadme中的示例类似,如下:

/**
 * pay success server notify.(!!!not support local-test server)
 */
Route::post(
    '/pay/alipay/notify.do',
    function () {
        //网关需设置为Alipay_MobileExpress
        $gateway = Omnipay::create('Alipay_MobileExpress');
        $gateway->setPartner(Config::get('pay.alipay.id'));
        $gateway->setKey(Config::get('pay.alipay.key'));
        $gateway->setSellerEmail(Config::get('pay.alipay.email'));
        $options['request_params'] = Input::all();
        //在此设置支付宝公钥
        $options['ali_public_key']   = storage_path('cert/ali_public_key.pem');
        //签名方式RSA
        $options['sign_type']      = 'RSA';
        $request                   = $gateway->completePurchase($options)->send();
        $debug_data                = $request->getData();
        if ($request->isSuccessful()) {
            $out_trade_no = Input::get('out_trade_no');
            #####
            # eg: $order = Order::find($out_trade_no);
            # !!!!you should check your order status here for duplicate request.
            #####
            Event::fire('alipay.pay_success', ['out_trade_no' => $out_trade_no, 'meta' => Input::all()]);
            die('success'); //it should be string 'success'
        } else {
            die('fail'); //it should be string 'fail'
        }
    }
);
mingyun commented 9 years ago

@lokielse 谢谢回复,但是提示The ca_cert_path parameter is required,The request_params.trade_status parameter is required,所以我改成


        $gateway = Omnipay::create('Alipay_MobileExpress');
        $gateway->setPartner(Config::get('pay.alipay.id'));
        $gateway->setKey(Config::get('pay.alipay.key'));
        $gateway->setSellerEmail(Config::get('pay.alipay.email'));

        //在此设置支付宝公钥
        $options['ali_public_key']   = storage_path('cert/ali_public_key.pem');
        //签名方式RSA
        $options['sign_type']      = 'RSA';
        $options['ca_cert_path']   = storage_path() . '/key/cacert.pem';
        $options['request_params'] = ['trade_status'=>'in','out_trade_no'=>65,'trade_no'=>'df'];
        $request                   = $gateway->completePurchase($options)->send();
        $debug_data                = $request->getData();
        if ($request->isSuccessful()) {
            $out_trade_no = Input::get('out_trade_no');
            #####
            # eg: $order = Order::find($out_trade_no);
            # !!!!you should check your order status here for duplicate request.
            #####
            \Event::fire('alipay.pay_success', ['out_trade_no' => $out_trade_no, 'meta' => Input::all()]);
            die('success'); //it should be string 'success'
        } else {
            die('fail'); //it should be string 'fail'
        }

里面公钥路径和cacert.pem都错的,request_params也随意设置的,但是$request->isSuccessful()直接通过了!

// $request                   = $gateway->completePurchase($options)->send();
//这里不该是purchase吗?因为createRequest请求的不是MobileExpressPurchaseRequest
public function completePurchase(array $parameters = array())
    {
        return $this->createRequest('\Omnipay\Alipay\Message\ExpressCompletePurchaseRequest', $parameters);
    }
public function purchase(array $parameters = array())
    {
        return $this->createRequest('\Omnipay\Alipay\Message\MobileExpressPurchaseRequest', $parameters);
    }

而只有Omnipay\Alipay\Message\ExpressCompletePurchaseRequest.php这个文件rsaVerify函数验证了公钥,请指正,谢谢

lokielse commented 9 years ago

@mingyun 刚对你指出的问题提交了一个更新,请更新代码后测试。

mingyun commented 9 years ago

@lokielse 我更新代码后rsaVerify方法里$ali_public_key_path取不到为空,发现$sign = $this->rsaVerify($query_string, trim($this->getAliPubicKey()), $this->getRequestParam('sign'));这里少了个字母,应该为getAliPublicKey,麻烦修改下,然后$options['ca_cert_path'] = storage_path() . '/key/cacert.pem';这个不用设置吗?

lokielse commented 9 years ago

@mingyun 更正了,ca_cert_path在此不用设置

lokielse commented 9 years ago

@mingyun 那还是加上吧,应该是没有安装支付宝钱包的适合会使用notify_id去验证,这个适合会使用ca_cert, 你可以自己核实一下。