Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信支付沙箱地址混乱 #665

Closed
skyred opened this issue Apr 26, 2017 · 12 comments
Closed

微信支付沙箱地址混乱 #665

skyred opened this issue Apr 26, 2017 · 12 comments

Comments

@skyred
Copy link
Contributor

skyred commented Apr 26, 2017

我用的环境

PHP 版本:7.0.1
overtrue/wechat 版本:a3fcf13

问题及现象

在微信沙箱文档上,https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=21_2

  1. 图片上说,沙箱环境是 /sandboxnew
  2. 文字上说,沙箱环境是 /sandbox

我两个都测试了,当使用 /sandbox,错误是:

商户号mch_id或sub_mch_id不存在

当使用 /sandboxnew 时候,错误是:

验证签名失败, 请调用getsignkey生成沙箱密钥

同样的参数不边,我直接接正式环境,既取出 /sandbox 或者 /sandboxnew 路径,可以正常生成二维码。

光从错误信息的文字上来看,似乎 /sandboxnew 是正确的地址。但是,getsignkey 是要做什么呢? 目前没有在微信文档上看见。

@skyred
Copy link
Contributor Author

skyred commented Apr 26, 2017

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=21_2 文档地址是从 #507 获取,但是我通过文档导航,找到了 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_1 ,里面包括了 getsignkey 的描述,似乎更全

@mingyoung
Copy link
Collaborator

/sandboxnew 为准,我问过客服了;
沙箱模式的签名是要从微信服务器获取的,之前也提醒过你了。。。

@skyred
Copy link
Contributor Author

skyred commented Apr 26, 2017

根据文档:

为保证商户接入质量,提升交易安全及用户体验,微信支付的合作服务商在正式上线交易前,必须先根据本文指引完成验收。验收完成后,服务商在验收公众平台(微信号:WXPayAssist)提交验收通过申请,审核通过后,才能开通相应的支付权限(如:刷卡支付)。否则,请根据审核驳回提示,重新完成验收。

新的微信支付接通必须通过沙盒验收过程。现在需要做的开发有:

  1. /Payment/API.php里添加一个 getSandboxSignKey()
  2. 添加 protected $sandboxSignKey;
  3. 在每次对微信endpoint发出请求的时候,如果是$sandboxEnabled == true, 并且$sandboxSignKey为空,那么就先申请这个key
  4. 目前没有对这个key有persistent caching解决方法。但也许在未来的版本里,可以提供一个方法,使用这个SDK的应用来cache这个key.

如果有其他建议,请提供。

@skyred
Copy link
Contributor Author

skyred commented Apr 26, 2017

第二种解决方案是:

  1. /Payment/API.php里添加一个 getSandboxSignKey()
  2. 让应用根据自己的需要叫 getSandboxSignKey(),并且把结果缓存
  3. 然后重新创建一个新的 $app = new Application($options);,这里的$options包含了第二步结果里的sandbox_signkey

我个人更喜欢第二种方案,其他人有没有建议?

@mingyoung
Copy link
Collaborator

能不能做到只修改 $payment->sandboxMode(true | false) 即可切换 Sandbox 环境和生产环境?不需要增改其他代码?

@skyred
Copy link
Contributor Author

skyred commented Apr 26, 2017

能不能做到只修改 $payment->sandboxMode(true | false) 即可切换 Sandbox 环境和生产环境?不需要增改其他代码?

你的这个建议是方案一可以提供的:#665 (comment), 但是方案一的缺点是:

  1. 每次给微信做任何请求的时候,都需要请求一次sandbox_signkey. (因为,我们无法在SDK里做到缓存sandbox_signkey)。
  2. 对SDK的修改要比方案二多。

@mingyoung
Copy link
Collaborator

但是在使用上的话方案二会略麻烦?😄

@skyred
Copy link
Contributor Author

skyred commented Apr 26, 2017

但是在使用上的话方案二会略麻烦?

和方案一比,麻烦一点,以下是我使用方案二的代码:

    $options = [
      // 前面的appid什么的也得保留哦
      'app_id' => $appid,
      // ...
      // payment
      'payment' => [
        'merchant_id'        => $mch_id,
        'key' => '4eb1a5b6d9e5533657e94bd089255d99',
        'cert_path'          => 'path/to/your/cert.pem', // XXX: 绝对路径!!!!
        'key_path'           => 'path/to/your/key',      // XXX: 绝对路径!!!!
        'notify_url'         => $payment_gateway_plugin->getNotifyUrl()->toString(),
        // 'device_info'     => '013467007045764',
        // ...
      ],
    ];
    $app = new Application($options);
    $wechat_pay = $app->payment;

    if ($mode) {
      // 从Drupal缓存里读取sanbox_signkey
     $cid = 'mymodule_example:' . \Drupal::languageManager()->getCurrentLanguage()->getId();

     $sanbox_signkey = NULL;
     if ($cache = \Drupal::cache()->get($cid)) {
       $sanbox_signkey = $cache->data;
     } else {
       $result = $wechat_pay->getSandboxSignKey();
       if ($result->return_code == 'SUCCESS') {
          $options['key'] = $result->sandbox_signkey; 
          $app = new Application($options);
          $wechat_pay = $app->payment;*/
          $wechat_pay->sandboxMode(true);
           \Drupal::cache()->set($cid, $result->sandbox_signkey); // 把新取得的sanbox_signkey放到缓存里
       }
      }
    }

@mingyoung
Copy link
Collaborator

所以……第一种方案会好点?

@overtrue
Copy link
Collaborator

SDK 里为啥不能缓存 sandbox_signkey ?

@skyred
Copy link
Contributor Author

skyred commented Apr 27, 2017

SDK 里为啥不能缓存 sandbox_signkey ?

我说的是 persistent caching. 当有多个HTTP请求到服务器,仅仅在SDK里,没办法共享sandbox_signkey。我上面的例子是把缓存放在MySQL/Memcache/Redis里。

@overtrue
Copy link
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants