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

bump to v1.2.2 #42

Merged
merged 5 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# 变更历史

## 1.2.2 - 2021-09-09

[变更细节](../../compare/v1.2.1...v1.2.2)

- 以`at sign`形式,温和提示`APIv2`的`DEP_XML_PROTOCOL_IS_REACHABLE_EOL`,相关[#38](https://github.com/wechatpay-apiv3/wechatpay-php/issues/38);
- 优化`Transformer::toArray`函数,对入参`xml`非法时,返回空`array`,并把最后一条错误信息温和地打入`E_USER_NOTICE`通道;
- 修正`Formatter::ksort`排列键值时兼容问题,使用`字典序(dictionary order)`排序,相关[#41](https://github.com/wechatpay-apiv3/wechatpay-php/issues/41), 感谢 @suiaiyun 报告此问题;

## 1.2.1 - 2021-09-06

[变更细节](../../compare/v1.2.0...v1.2.1)
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ APIv3已内置 `请求签名` 和 `应答验签` 两个middleware中间件,创

## 项目状态

当前版本为`1.2.1`测试版本。
当前版本为`1.2.2`测试版本。
请商户的专业技术人员在使用时注意系统和软件的正确性和兼容性,以及带来的风险。

**版本说明:** `开发版`指: `类库API`随时会变;`测试版`指: 少量`类库API`可能会变;`稳定版`指: `类库API`稳定持续;版本遵循[语义化版本号](https://semver.org/lang/zh-CN/)规则。
Expand Down Expand Up @@ -60,7 +60,7 @@ composer require wechatpay/wechatpay

```json
"require": {
"wechatpay/wechatpay": "^1.2.1"
"wechatpay/wechatpay": "^1.2.2"
}
```

Expand Down Expand Up @@ -402,6 +402,8 @@ try {

商户在平滑迁移时,务必调整`php.ini`的`display_errors=Off`或者`error_reporting`错误级别,来防止把这条**提醒**信息打送至前台业务系统。

**注:** `v1.2.2`版调整了上述提示,直至`APIv2`生命周期结束,不再强提示。

### 初始化

```php
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wechatpay/wechatpay",
"version": "1.2.1",
"version": "1.2.2",
"description": "[A]Sync Chainable WeChatPay v2&v3's OpenAPI SDK for PHP",
"type": "library",
"keywords": [
Expand Down
2 changes: 1 addition & 1 deletion src/ClientDecoratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface ClientDecoratorInterface
/**
* @var string - This library version
*/
public const VERSION = '1.2.1';
public const VERSION = '1.2.2';

/**
* @var string - The HTTP transfer `xml` based protocol
Expand Down
2 changes: 1 addition & 1 deletion src/ClientXmlTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ abstract protected static function withDefaults(array ...$config): array;
public static function transformRequest(?string $mchid = null, string $secret = '', ?array $merchant = null): callable
{
return static function (callable $handler) use ($mchid, $secret, $merchant): callable {
trigger_error(Exception\WeChatPayException::DEP_XML_PROTOCOL_IS_REACHABLE_EOL, E_USER_DEPRECATED);
@trigger_error(Exception\WeChatPayException::DEP_XML_PROTOCOL_IS_REACHABLE_EOL, E_USER_DEPRECATED);

return static function (RequestInterface $request, array $options = []) use ($handler, $mchid, $secret, $merchant): PromiseInterface {
$data = $options['xml'] ?? [];
Expand Down
4 changes: 2 additions & 2 deletions src/Formatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use function is_null;

use const SORT_FLAG_CASE;
use const SORT_NATURAL;
use const SORT_STRING;

use InvalidArgumentException;

Expand Down Expand Up @@ -121,7 +121,7 @@ public static function joinedByLineFeed(...$pieces): string
*/
public static function ksort(array $thing = []): array
{
ksort($thing, SORT_FLAG_CASE | SORT_NATURAL);
ksort($thing, SORT_FLAG_CASE | SORT_STRING);
TheNorthMemory marked this conversation as resolved.
Show resolved Hide resolved

return $thing;
}
Expand Down
21 changes: 21 additions & 0 deletions src/Transformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
use function array_walk;
use function is_array;
use function is_object;
use function is_string;
use function preg_replace;
use function strpos;
use function preg_match;
use function sprintf;
use function trigger_error;
use function libxml_clear_errors;
use function libxml_disable_entity_loader;
use function libxml_get_last_error;
use function libxml_use_internal_errors;
use function simplexml_load_string;

use SimpleXMLElement;
use Traversable;
Expand All @@ -40,10 +48,23 @@ public static function toArray(string $xml = '<xml/>'): array
{
LIBXML_VERSION < 20900 && $previous = libxml_disable_entity_loader(true);

libxml_use_internal_errors(true);
$el = simplexml_load_string(static::sanitize($xml), SimpleXMLElement::class, LIBXML_NONET | LIBXML_COMPACT | LIBXML_NOCDATA | LIBXML_NOBLANKS);

LIBXML_VERSION < 20900 && isset($previous) && libxml_disable_entity_loader($previous);

if (false === $el && false !== ($err = libxml_get_last_error())) {
// while parsing failed, let's clean the internal buffer and
// only leave the last error message which still can be fetched by the `error_get_last()` function.
libxml_clear_errors();
@trigger_error(sprintf(
'Parsing the $xml failed with the last error(level=%d,code=%d,message=%s).',
$err->level, $err->code, $err->message
));

return [];
}

return static::cast($el);
}

Expand Down
48 changes: 46 additions & 2 deletions tests/FormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

namespace WeChatPay\Tests;

use const SORT_FLAG_CASE;
use const SORT_STRING;
use const SORT_NATURAL;
use const SORT_REGULAR;

use function method_exists;
use function strlen;
use function strval;
Expand Down Expand Up @@ -236,7 +241,7 @@ public function testNoneArgumentPassedToJoinedByLineFeed(): void
/**
* @return array<string,array<array<string,string>>>
*/
public function ksortByFlagNaturePhrasesProvider(): array
public function ksortPhrasesProvider(): array
{
return [
'normal' => [
Expand All @@ -247,19 +252,58 @@ public function ksortByFlagNaturePhrasesProvider(): array
['rfc1' => '1', 'b' => '4', 'rfc822' => '2', 'rfc2086' => '3'],
['b' => '4', 'rfc1' => '1', 'rfc822' => '2', 'rfc2086' => '3'],
],
'issue #41 `re_openid` with `remark` keys' => [
[
'mch_billno' => 'etGkDmT3BJyuhnhU9d', 'mch_id' => 'xxxxx', 'wxappid' => 'wx01111111', 'send_name' => 'aaaaa', 're_openid' => 'o8xSOxxxxxxx',
'total_amount' => '100', 'total_num' => '1', 'wishing' => '红包祝福语', 'client_ip' => '192.168.0.1', 'act_name' => '活动名称', 'remark' => '备注',
],
[
'act_name' => '活动名称', 'client_ip' => '192.168.0.1', 'mch_billno' => 'etGkDmT3BJyuhnhU9d', 'mch_id' => 'xxxxx', 're_openid' => 'o8xSOxxxxxxx',
'remark' => '备注', 'send_name' => 'aaaaa', 'total_amount' => '100', 'total_num' => '1', 'wishing' => '红包祝福语', 'wxappid' => 'wx01111111',
],
],
'the key point of the issue #41 different' => [
[
're_openid' => 'o8xSOxxxxxxx', 'remark' => '备注',
],
[
're_openid' => 'o8xSOxxxxxxx', 'remark' => '备注',
],
],
];
}

/**
* @param array<string,string> $thing
* @param array<string,string> $excepted
* @dataProvider ksortByFlagNaturePhrasesProvider
* @dataProvider ksortPhrasesProvider
*/
public function testKsort(array $thing, array $excepted): void
{
self::assertEquals(Formatter::ksort($thing), $excepted);
}

public function testKsortWithDifferentFlags(): void
{
$excepted = ['re_openid' => 'o8xSOxxxxxxx', 'remark' => '备注'];
// `_` chrcode is 95, `m` is 109, the ordering should be the above

$sample1 = ['remark' => '备注', 're_openid' => 'o8xSOxxxxxxx'];
// `natural ordering`
self::assertTrue(ksort($sample1, SORT_FLAG_CASE | SORT_NATURAL));
self::assertNotEquals(array_keys($excepted), array_keys($sample1));

$sample2 = ['remark' => '备注', 're_openid' => 'o8xSOxxxxxxx'];
// `dictionary order`
self::assertTrue(ksort($sample2, SORT_FLAG_CASE | SORT_STRING));
self::assertEquals(array_keys($excepted), array_keys($sample2));

$sample3 = ['remark' => '备注', 're_openid' => 'o8xSOxxxxxxx'];
// `default SORT_REGULAR`
self::assertTrue(ksort($sample3, SORT_REGULAR));
self::assertEquals(array_keys($excepted), array_keys($sample3));
}

/**
* @return array<string,array<array<string,string>>>
*/
Expand Down
19 changes: 10 additions & 9 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,19 @@ Certificate:
vendor/bin/phpunit
PHPUnit 9.5.9 by Sebastian Bergmann and contributors.

............................................................... 63 / 500 ( 12%)
............................................................... 126 / 500 ( 25%)
............................................................... 189 / 500 ( 37%)
............................................................... 252 / 500 ( 50%)
............................................................... 315 / 500 ( 63%)
............................................................... 378 / 500 ( 75%)
............................................................... 441 / 500 ( 88%)
........................................................... 500 / 500 (100%)
............................................................... 63 / 504 ( 12%)
............................................................... 126 / 504 ( 25%)
............................................................... 189 / 504 ( 37%)
............................................................... 252 / 504 ( 50%)
............................................................... 315 / 504 ( 62%)
............................................................... 378 / 504 ( 75%)
............................................................... 441 / 504 ( 87%)
............................................................... 504 / 504 (100%)


Time: 00:00.641, Memory: 12.00 MB

OK (500 tests, 2258 assertions)
OK (504 tests, 2268 assertions)
rm -rf ./tests/fixtures/mock.*
```

Expand Down
43 changes: 43 additions & 0 deletions tests/TransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
use function array_map;
use function file_get_contents;
use function json_encode;
use function is_string;
use function error_clear_last;
use function error_get_last;
use function method_exists;

use WeChatPay\Transformer;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -82,6 +86,45 @@ public function testToArray(string $xmlString, array $keys): void
}, $keys);
}

/**
* @return array<string,array{string,?string}>
*/
public function xmlToArrayBadPhrasesDataProvider(): array
{
$baseDir = __DIR__ . DIRECTORY_SEPARATOR . 'fixtures' . DIRECTORY_SEPARATOR;

return [
$f = 'fragment_injection.sample.xml' => [(string)file_get_contents($baseDir . $f), null],
$f = 'invalid.xxe_injection.sample.xml' => [(string)file_get_contents($baseDir . $f), null],
$f = 'invalid.bad_entity.sample.xml' => [(string)file_get_contents($baseDir . $f), '#^Parsing the \$xml failed with the last error#'],
$f = 'invalid.normal_404.sample.html' => [(string)file_get_contents($baseDir . $f), '#^Parsing the \$xml failed with the last error#'],
];
}

/**
* @dataProvider xmlToArrayBadPhrasesDataProvider
* @param string $xmlString
* @param ?string $pattern
*/
public function testToArrayBadPhrases(string $xmlString, ?string $pattern): void
{
error_clear_last();
$array = Transformer::toArray($xmlString);
self::assertIsArray($array);
if (is_string($pattern)) {
self::assertEmpty($array);
/** @var array{'message':string,'type':int,'file':string,'line':int} $err */
$err = error_get_last();
if (method_exists($this, 'assertMatchesRegularExpression')) {
$this->assertMatchesRegularExpression($pattern, $err['message']);
} else {
self::assertRegExp($pattern, $err['message']);
}
} else {
self::assertNotEmpty($array);
}
}

/**
* @return array<string,array{array<mixed>,bool,bool,string,string}>
*/
Expand Down
14 changes: 14 additions & 0 deletions tests/fixtures/fragment_injection.sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<batchjob>
<payment>
<account>5678-attacker</account>
<rcpt>206-1234</rcpt>
<amount>100.00</amount>
<comment></comment>
</payment>
<payment>
<account>1234-victim</account>
<rcpt>206-1234</rcpt>
<amount>100.00</amount>
<comment>Hacked</comment>
</payment>
</batchjob>
6 changes: 6 additions & 0 deletions tests/fixtures/invalid.bad_entity.sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" standalone="yes"?>
<movies>
<movie>
<titles>PHP: Behind the Parser</title>
</movie>
</movies>
7 changes: 7 additions & 0 deletions tests/fixtures/invalid.normal_404.sample.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
3 changes: 3 additions & 0 deletions tests/fixtures/invalid.xxe_injection.sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://tst.qq.com/xxe_inject/463103c2ee4067e1c4f5318440dc245d">]>
<foo><value>&xxe;</value></foo>