├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── paylib
├── .gitignore
├── build.gradle
├── libs
│ └── alipaySingle-20170510.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zys
│ │ └── paylib
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── zys
│ │ │ └── paylib
│ │ │ ├── PayConfig.java
│ │ │ ├── alipay
│ │ │ ├── AlipayUtil.java
│ │ │ ├── AuthResult.java
│ │ │ ├── Base64.java
│ │ │ ├── OrderInfoUtil.java
│ │ │ ├── PayResult.java
│ │ │ └── SignUtils.java
│ │ │ ├── pay
│ │ │ ├── AliPay.java
│ │ │ ├── IPay.java
│ │ │ ├── PayTools.java
│ │ │ └── WxPay.java
│ │ │ └── wxpay
│ │ │ ├── ParameterConfig.java
│ │ │ ├── WXPayInfo.java
│ │ │ └── WXPayUtil.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── zys
│ └── paylib
│ └── ExampleUnitTest.java
├── sample
├── .gitignore
├── build.gradle
├── class_files.txt
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── zys
│ │ └── zyspay
│ │ └── demo
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── zys
│ │ │ └── zyspay
│ │ │ └── demo
│ │ │ ├── App.java
│ │ │ ├── MainActivity.java
│ │ │ └── wxapi
│ │ │ └── WXPayEntryActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── wx_pay_result.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── zys
│ └── zyspay
│ └── demo
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # IntelliJ
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/assetWizardSettings.xml
41 | .idea/dictionaries
42 | .idea/libraries
43 | .idea/caches
44 |
45 | # Keystore files
46 | # Uncomment the following line if you do not want to check your keystore files in.
47 | #*.jks
48 |
49 | # External native build folder generated in Android Studio 2.2 and later
50 | .externalNativeBuild
51 |
52 | # Google Services (e.g. APIs or Firebase)
53 | google-services.json
54 |
55 | # Freeline
56 | freeline.py
57 | freeline/
58 | freeline_project_description.json
59 |
60 | # fastlane
61 | fastlane/report.xml
62 | fastlane/Preview.html
63 | fastlane/screenshots
64 | fastlane/test_output
65 | fastlane/readme.md
66 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PayLib
2 | [](https://jitpack.io/#Equalzys/PayLib)
3 |
4 | 支付宝支付,微信支付封装,使用简单方便
5 | 只用自己服务器返回 支付宝或微信的预支付订单号 即可完成支付
6 |
7 | 第一步:在项目根目录的 build.gradle 里添加jitpack库
8 | ```java
9 | allprojects {
10 | repositories {
11 | ...
12 | maven { url 'https://jitpack.io' }
13 | }
14 | }
15 | ```
16 |
17 | 第二步:在app的 build.gradle 里添加依赖
18 | ```java
19 | dependencies {
20 | implementation 'com.github.Equalzys:PayLib:1.0.2'
21 | }
22 | ```
23 |
24 | 第三步:初始化库(建议在application里初始化)
25 | ```java
26 | String RSA_PRIVATE="6e**********eo5ff9==";
27 | //用到支付宝的时候配置
28 | PayConfig.alipay()
29 | .appId("2017******3659")
30 | .rsa(RSA_PRIVATE)
31 | .notifyUrl("http://www.xx**xx.com/api/trade/notify/alipay")
32 | .intro("支付宝订单-")
33 | .init();
34 |
35 | //用到微信的时候配置
36 | PayConfig.wxpay()
37 | .appId("wx62*******87")
38 | .mchId("15******1")
39 | .apiKey("Rd88G******I0ci406")
40 | .notifyUrl("http://www.xx**xx.com/api/trade/notify/wxpay")
41 | .intro("微信订单-")
42 | .init();
43 | ```
44 |
45 | 第四步:在支付的地方调用pay,ps:微信支付需要在包名下添加 wxapi.WXPayEntryActivity
46 | ```java
47 | //支付宝支付
48 | String tradenumber = "这里是实际交易订单号-服务器返回";
49 | double money=0.01;//需要支付的金额
50 | PayTools.aliPay(this)
51 | .tradeNumber(tradenumber)
52 | .money(money)
53 | .intro("订单-")//(非必填)
54 | .pay(new AlipayUtil.AlipayCallBack() {
55 | @Override
56 | public void success(String ordernumber, String resultInfo) {
57 |
58 | }
59 |
60 | @Override
61 | public void fail(String resultInfo) {
62 |
63 | }
64 |
65 | });
66 |
67 |
68 |
69 | //微信支付
70 | String tradenumber = "这里是实际交易订单号-服务器返回";
71 | double money=0.01;//需要支付的金额
72 | PayTools.wxPay(this)
73 | .tradeNumber(tradenumber)
74 | .intro("订单-")//(非必填)
75 | .money(money)
76 | .pay();//支付回调在WXPayEntryActivity
77 |
78 |
79 | ```
80 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | mavenCentral()
8 | maven {
9 | url "https://jitpack.io"
10 | }
11 | maven {
12 | url "https://maven.google.com"
13 | }
14 | }
15 | dependencies {
16 | classpath 'com.android.tools.build:gradle:3.3.0'
17 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
18 | // NOTE: Do not place your application dependencies here; they belong
19 | // in the individual module build.gradle files
20 | }
21 | }
22 |
23 | allprojects {
24 | repositories {
25 | google()
26 | jcenter()
27 | mavenCentral()
28 | maven {
29 | url "https://jitpack.io"
30 | }
31 | maven {
32 | url "https://maven.google.com"
33 | }
34 | }
35 | }
36 |
37 | task clean(type: Delete) {
38 | delete rootProject.buildDir
39 | }
40 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 |
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Feb 18 09:24:05 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/paylib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/paylib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | group='com.github.Equalzys'
4 |
5 | android {
6 | compileSdkVersion 28
7 |
8 | defaultConfig {
9 | minSdkVersion 16
10 | targetSdkVersion 28
11 | versionCode 100
12 | versionName "1.0.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 |
18 | useLibrary 'org.apache.http.legacy'
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | dexOptions {
27 | preDexLibraries = false
28 | }
29 | repositories {
30 | flatDir{ dirs 'libs' }
31 | }
32 |
33 | }
34 |
35 | dependencies {
36 | implementation fileTree(include: ['*.jar'], dir: 'libs')
37 | implementation 'com.android.support:appcompat-v7:28.0.0'
38 | testImplementation 'junit:junit:4.12'
39 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
40 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
41 | api files('libs/alipaySingle-20170510.jar')
42 | api 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:5.1.6'
43 | }
44 |
--------------------------------------------------------------------------------
/paylib/libs/alipaySingle-20170510.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/paylib/libs/alipaySingle-20170510.jar
--------------------------------------------------------------------------------
/paylib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/paylib/src/androidTest/java/com/zys/paylib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.zys.paylib.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/paylib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 |
10 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/PayConfig.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.text.TextUtils;
6 |
7 | import com.zys.paylib.alipay.AlipayUtil;
8 | import com.zys.paylib.wxpay.ParameterConfig;
9 |
10 | public class PayConfig {
11 |
12 | private static final String TAG = "PayConfig";
13 |
14 |
15 | public static AliConfig alipay() {
16 | return new AliConfig();
17 | }
18 |
19 | public static class AliConfig {
20 | /**
21 | * appid
22 | */
23 | public AliInfo appId(String appid) {
24 | return new AliInfo(appid);
25 | }
26 |
27 | public class AliInfo {
28 | private String app_id;
29 | private String rsa_private;
30 | private String notify_url;
31 | private String intro;
32 |
33 |
34 | public AliInfo(String appid) {
35 | this.app_id = appid;
36 | }
37 | /**
38 | * 商户私钥,pkcs8格式,rsa2
39 | */
40 | public AliInfo rsa(String rsa_private) {
41 | this.rsa_private = rsa_private;
42 | return this;
43 | }
44 |
45 | /**
46 | * 自己服务器支付回调地址
47 | */
48 | public AliInfo notifyUrl(String notify_url) {
49 | this.notify_url = notify_url;
50 | return this;
51 | }
52 |
53 | /**
54 | * 支付宝窗口显示的订单信息:默认为 "订单-实际订单号",'-实际订单号'为固定值
55 | * 这里可以修改 "订单"这两个字,修改为 "测试订单-实际订单号"
56 | */
57 | public AliInfo intro(String i) {
58 | this.intro = i;
59 | return this;
60 | }
61 |
62 | public void init() {
63 | AlipayUtil.setAPPID(app_id);
64 | AlipayUtil.setNotifyUrl(notify_url);
65 | AlipayUtil.setRsaPrivate(rsa_private);
66 | if (!TextUtils.isEmpty(intro)) {
67 | AlipayUtil.setIntro(intro);
68 | }
69 | }
70 | }
71 |
72 | }
73 |
74 | public static WXPConfig wxpay() {
75 | return new WXPConfig();
76 | }
77 |
78 | public static class WXPConfig {
79 | /**
80 | * appid
81 | */
82 | public WXInfo appId(String appid) {
83 | return new WXInfo(appid);
84 | }
85 |
86 | public class WXInfo {
87 | private String app_id;
88 |
89 | private String mch_id;
90 | private String api_key;
91 | private String notify_url;
92 | private String intro;
93 |
94 | public WXInfo(String appid) {
95 | this.app_id = appid;
96 | }
97 |
98 | /**
99 | * 商户号
100 | */
101 | public WXInfo mchId(String mch_id) {
102 | this.mch_id = mch_id;
103 | return this;
104 | }
105 |
106 | /**
107 | * API密钥,在商户平台设置
108 | */
109 | public WXInfo apiKey(String api_key) {
110 | this.api_key = api_key;
111 | return this;
112 | }
113 |
114 | /**
115 | * 自己服务器支付回调地址
116 | */
117 | public WXInfo notifyUrl(String notify_url) {
118 | this.notify_url = notify_url;
119 | return this;
120 | }
121 |
122 | /**
123 | * 支付宝窗口显示的订单信息:默认为 "订单-实际订单号",'-实际订单号'为固定值
124 | * 这里可以修改 "订单"这两个字,修改为 "测试订单-实际订单号"
125 | */
126 | public WXInfo intro(String i) {
127 | this.intro = i;
128 | return this;
129 | }
130 |
131 | public void init() {
132 | ParameterConfig.setWxAppId(app_id);
133 | ParameterConfig.setWxMchId(mch_id);
134 | ParameterConfig.setWX_notifyUrl(notify_url);
135 | ParameterConfig.setWxApiKey(api_key);
136 | if (!TextUtils.isEmpty(intro)) {
137 | ParameterConfig.setIntro(intro);
138 | }
139 |
140 | }
141 | }
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/AlipayUtil.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.content.DialogInterface;
6 | import android.os.Handler;
7 | import android.os.Message;
8 | import android.text.TextUtils;
9 | import android.util.Log;
10 |
11 | import com.alipay.sdk.app.PayTask;
12 | import com.zys.paylib.wxpay.ParameterConfig;
13 |
14 | import java.text.SimpleDateFormat;
15 | import java.util.Date;
16 | import java.util.Locale;
17 | import java.util.Map;
18 | import java.util.Random;
19 |
20 |
21 | public class AlipayUtil {
22 | String TAG = "AlipayUtil";
23 | private static AlipayUtil mUtil;
24 |
25 | private static String APPID = "";
26 | //商户私钥,pkcs8格式
27 | private static String RSA_PRIVATE = "";
28 | //测试回调地址
29 | private static String NOTIFY_URL = "";
30 | private static String intro = "订单-";
31 | boolean rsa2 = true;
32 | private static final int SDK_PAY_FLAG = 1;
33 | private String OutTradeNo; //商户唯一支付订单号
34 | private static final int SDK_AUTH_FLAG = 2;
35 |
36 |
37 | public static AlipayUtil getInstance() {
38 | if (mUtil == null) {
39 | mUtil = new AlipayUtil();
40 | }
41 | return mUtil;
42 | }
43 |
44 | private Handler mHandler = new Handler() {
45 | public void handleMessage(Message msg) {
46 | switch (msg.what) {
47 | case SDK_PAY_FLAG: {
48 | @SuppressWarnings("unchecked")
49 | PayResult payResult = new PayResult((Map) msg.obj);
50 | /**
51 | 对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。
52 | */
53 | // 同步返回需要验证的信息
54 | String resultInfo = payResult.getResult();
55 | String resultStatus = payResult.getResultStatus();
56 | Log.d(TAG, "resultInfo=" + resultInfo + "---resultStatus=" + resultStatus);
57 | // 判断resultStatus 为9000则代表支付成功
58 | if (TextUtils.equals(resultStatus, "9000")) {
59 | //支付成功
60 | if (callback != null) {
61 | callback.success(OutTradeNo, resultInfo);
62 | }
63 | } else {
64 | //支付失败
65 | if (callback != null) {
66 | callback.fail(resultInfo);
67 | }
68 | }
69 | break;
70 | }
71 | case SDK_AUTH_FLAG: {
72 | @SuppressWarnings("unchecked")
73 | AuthResult authResult = new AuthResult((Map) msg.obj, true);
74 | String resultStatus = authResult.getResultStatus();
75 |
76 | // 判断resultStatus 为“9000”且result_code
77 | // 为“200”则代表授权成功,具体状态码代表含义可参考授权接口文档
78 | if (TextUtils.equals(resultStatus, "9000") && TextUtils.equals(authResult.getResultCode(), "200")) {
79 | Log.d(TAG, "授权成功");
80 | } else {
81 | Log.d(TAG, "授权失败");
82 | if (callback != null) {
83 | callback.fail("9000-授权失败");
84 | }
85 | }
86 | break;
87 | }
88 | default:
89 | break;
90 | }
91 | }
92 |
93 | ;
94 | };
95 |
96 |
97 | public void pay(final Activity activity, String body, String price, AlipayCallBack callback) {
98 |
99 | pay(activity, "", body, price, callback);
100 | }
101 |
102 | public void pay(final Activity activity, String subject_start, String body, String price,
103 | AlipayCallBack callback) {
104 |
105 | if (TextUtils.isEmpty(APPID) || TextUtils.isEmpty(RSA_PRIVATE) || TextUtils.isEmpty(NOTIFY_URL)) {
106 | new AlertDialog.Builder(activity).setTitle("警告").setMessage("需要配置APPID | RSA_PRIVATE|" +
107 | " NOTIFY_URL\n请调用PayConfig进行初始化配置")
108 | .setPositiveButton("确定", new DialogInterface.OnClickListener() {
109 | @Override
110 | public void onClick(DialogInterface dialoginterface, int i) {
111 | }
112 | }).show();
113 | return;
114 | }
115 | this.OutTradeNo = body;
116 | this.callback = callback;
117 | if (TextUtils.isEmpty(subject_start)) {
118 | subject_start = intro;
119 | }
120 | Map params = OrderInfoUtil.buildOrderParamMap(APPID, body, price,
121 | subject_start + body, NOTIFY_URL, rsa2);
122 | String orderParam = OrderInfoUtil.buildOrderParam(params);
123 |
124 | String privateKey = RSA_PRIVATE;
125 | String sign = OrderInfoUtil.getSign(params, privateKey, rsa2);
126 | Log.d(TAG, "签名:" + sign);
127 | final String orderInfo = orderParam + "&" + sign;
128 |
129 | Runnable payRunnable = new Runnable() {
130 |
131 | @Override
132 | public void run() {
133 | PayTask alipay = new PayTask(activity);
134 | Map result = alipay.payV2(orderInfo, true);
135 | // Log.i("msp", result.toString());
136 |
137 | Message msg = new Message();
138 | msg.what = SDK_PAY_FLAG;
139 | msg.obj = result;
140 | mHandler.sendMessage(msg);
141 | }
142 | };
143 |
144 | Thread payThread = new Thread(payRunnable);
145 | payThread.start();
146 |
147 | }
148 |
149 |
150 | /**
151 | * get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
152 | */
153 | public String getOutTradeNo() {
154 | SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
155 | Date date = new Date();
156 | String key = format.format(date);
157 | Random r = new Random();
158 | key = key + r.nextInt();
159 | key = key.substring(0, 15);
160 | return key;
161 | }
162 |
163 | /**
164 | * sign the order info. 对订单信息进行签名
165 | *
166 | * @param content 待签名订单信息
167 | */
168 | public String sign(String content) {
169 | return SignUtils.sign(content, RSA_PRIVATE, false);
170 | }
171 |
172 | /**
173 | * get the sign type we use. 获取签名方式
174 | */
175 | public String getSignType() {
176 | return "sign_type=\"RSA\"";
177 | }
178 |
179 | private AlipayCallBack callback;
180 |
181 | public interface AlipayCallBack {
182 | /**
183 | * 支付成功
184 | */
185 | void success(String ordernumber, String resultInfo);
186 |
187 | /**
188 | * 支付失败
189 | */
190 | void fail(String resultInfo);
191 |
192 | }
193 |
194 | public static String getAPPID() {
195 | return APPID;
196 | }
197 |
198 | public static void setAPPID(String APPID) {
199 | AlipayUtil.APPID = APPID;
200 | }
201 |
202 | public static String getRsaPrivate() {
203 | return RSA_PRIVATE;
204 | }
205 |
206 | public static void setRsaPrivate(String rsaPrivate) {
207 | RSA_PRIVATE = rsaPrivate;
208 | }
209 |
210 | public static String getNotifyUrl() {
211 | return NOTIFY_URL;
212 | }
213 |
214 | public static void setNotifyUrl(String notifyUrl) {
215 | NOTIFY_URL = notifyUrl;
216 | }
217 |
218 | public static String getIntro() {
219 | return intro;
220 | }
221 |
222 | public static void setIntro(String i) {
223 | intro = i;
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/AuthResult.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
import android.text.TextUtils;
import java.util.Map;
public class AuthResult {
private String resultStatus;
private String result;
private String memo;
private String resultCode;
private String authCode;
private String alipayOpenId;
public AuthResult(Map rawResult, boolean removeBrackets) {
if (rawResult == null) {
return;
}
for (String key : rawResult.keySet()) {
if (TextUtils.equals(key, "resultStatus")) {
resultStatus = rawResult.get(key);
} else if (TextUtils.equals(key, "result")) {
result = rawResult.get(key);
} else if (TextUtils.equals(key, "memo")) {
memo = rawResult.get(key);
}
}
String[] resultValue = result.split("&");
for (String value : resultValue) {
if (value.startsWith("alipay_open_id")) {
alipayOpenId = removeBrackets(getValue("alipay_open_id=", value), removeBrackets);
continue;
}
if (value.startsWith("auth_code")) {
authCode = removeBrackets(getValue("auth_code=", value), removeBrackets);
continue;
}
if (value.startsWith("result_code")) {
resultCode = removeBrackets(getValue("result_code=", value), removeBrackets);
continue;
}
}
}
private String removeBrackets(String str, boolean remove) {
if (remove) {
if (!TextUtils.isEmpty(str)) {
if (str.startsWith("\"")) {
str = str.replaceFirst("\"", "");
}
if (str.endsWith("\"")) {
str = str.substring(0, str.length() - 1);
}
}
}
return str;
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo + "};result={" + result + "}";
}
private String getValue(String header, String data) {
return data.substring(header.length(), data.length());
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}
/**
* @return the resultCode
*/
public String getResultCode() {
return resultCode;
}
/**
* @return the authCode
*/
public String getAuthCode() {
return authCode;
}
/**
* @return the alipayOpenId
*/
public String getAlipayOpenId() {
return alipayOpenId;
}
}
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/Base64.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
2 |
3 | public final class Base64 {
4 |
5 | private static final int BASELENGTH = 128;
6 | private static final int LOOKUPLENGTH = 64;
7 | private static final int TWENTYFOURBITGROUP = 24;
8 | private static final int EIGHTBIT = 8;
9 | private static final int SIXTEENBIT = 16;
10 | private static final int FOURBYTE = 4;
11 | private static final int SIGN = -128;
12 | private static char PAD = '=';
13 | private static byte[] base64Alphabet = new byte[BASELENGTH];
14 | private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
15 |
16 | static {
17 | for (int i = 0; i < BASELENGTH; ++i) {
18 | base64Alphabet[i] = -1;
19 | }
20 | for (int i = 'Z'; i >= 'A'; i--) {
21 | base64Alphabet[i] = (byte) (i - 'A');
22 | }
23 | for (int i = 'z'; i >= 'a'; i--) {
24 | base64Alphabet[i] = (byte) (i - 'a' + 26);
25 | }
26 |
27 | for (int i = '9'; i >= '0'; i--) {
28 | base64Alphabet[i] = (byte) (i - '0' + 52);
29 | }
30 |
31 | base64Alphabet['+'] = 62;
32 | base64Alphabet['/'] = 63;
33 |
34 | for (int i = 0; i <= 25; i++) {
35 | lookUpBase64Alphabet[i] = (char) ('A' + i);
36 | }
37 |
38 | for (int i = 26, j = 0; i <= 51; i++, j++) {
39 | lookUpBase64Alphabet[i] = (char) ('a' + j);
40 | }
41 |
42 | for (int i = 52, j = 0; i <= 61; i++, j++) {
43 | lookUpBase64Alphabet[i] = (char) ('0' + j);
44 | }
45 | lookUpBase64Alphabet[62] = (char) '+';
46 | lookUpBase64Alphabet[63] = (char) '/';
47 |
48 | }
49 |
50 | private static boolean isWhiteSpace(char octect) {
51 | return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
52 | }
53 |
54 | private static boolean isPad(char octect) {
55 | return (octect == PAD);
56 | }
57 |
58 | private static boolean isData(char octect) {
59 | return (octect < BASELENGTH && base64Alphabet[octect] != -1);
60 | }
61 |
62 | /**
63 | * Encodes hex octects into Base64
64 | *
65 | * @param binaryData
66 | * Array containing binaryData
67 | * @return Encoded Base64 array
68 | */
69 | public static String encode(byte[] binaryData) {
70 |
71 | if (binaryData == null) {
72 | return null;
73 | }
74 |
75 | int lengthDataBits = binaryData.length * EIGHTBIT;
76 | if (lengthDataBits == 0) {
77 | return "";
78 | }
79 |
80 | int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
81 | int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
82 | int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
83 | : numberTriplets;
84 | char encodedData[] = null;
85 |
86 | encodedData = new char[numberQuartet * 4];
87 |
88 | byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
89 |
90 | int encodedIndex = 0;
91 | int dataIndex = 0;
92 |
93 | for (int i = 0; i < numberTriplets; i++) {
94 | b1 = binaryData[dataIndex++];
95 | b2 = binaryData[dataIndex++];
96 | b3 = binaryData[dataIndex++];
97 |
98 | l = (byte) (b2 & 0x0f);
99 | k = (byte) (b1 & 0x03);
100 |
101 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
102 | : (byte) ((b1) >> 2 ^ 0xc0);
103 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
104 | : (byte) ((b2) >> 4 ^ 0xf0);
105 | byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
106 | : (byte) ((b3) >> 6 ^ 0xfc);
107 |
108 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
109 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
110 | encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
111 | encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
112 | }
113 |
114 | // form integral number of 6-bit groups
115 | if (fewerThan24bits == EIGHTBIT) {
116 | b1 = binaryData[dataIndex];
117 | k = (byte) (b1 & 0x03);
118 |
119 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
120 | : (byte) ((b1) >> 2 ^ 0xc0);
121 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
122 | encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
123 | encodedData[encodedIndex++] = PAD;
124 | encodedData[encodedIndex++] = PAD;
125 | } else if (fewerThan24bits == SIXTEENBIT) {
126 | b1 = binaryData[dataIndex];
127 | b2 = binaryData[dataIndex + 1];
128 | l = (byte) (b2 & 0x0f);
129 | k = (byte) (b1 & 0x03);
130 |
131 | byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
132 | : (byte) ((b1) >> 2 ^ 0xc0);
133 | byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
134 | : (byte) ((b2) >> 4 ^ 0xf0);
135 |
136 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
137 | encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
138 | encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
139 | encodedData[encodedIndex++] = PAD;
140 | }
141 |
142 | return new String(encodedData);
143 | }
144 |
145 | /**
146 | * Decodes Base64 data into octects
147 | *
148 | * @param encoded
149 | * string containing Base64 data
150 | * @return Array containind decoded data.
151 | */
152 | public static byte[] decode(String encoded) {
153 |
154 | if (encoded == null) {
155 | return null;
156 | }
157 |
158 | char[] base64Data = encoded.toCharArray();
159 | // remove white spaces
160 | int len = removeWhiteSpace(base64Data);
161 |
162 | if (len % FOURBYTE != 0) {
163 | return null;// should be divisible by four
164 | }
165 |
166 | int numberQuadruple = (len / FOURBYTE);
167 |
168 | if (numberQuadruple == 0) {
169 | return new byte[0];
170 | }
171 |
172 | byte decodedData[] = null;
173 | byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
174 | char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
175 |
176 | int i = 0;
177 | int encodedIndex = 0;
178 | int dataIndex = 0;
179 | decodedData = new byte[(numberQuadruple) * 3];
180 |
181 | for (; i < numberQuadruple - 1; i++) {
182 |
183 | if (!isData((d1 = base64Data[dataIndex++]))
184 | || !isData((d2 = base64Data[dataIndex++]))
185 | || !isData((d3 = base64Data[dataIndex++]))
186 | || !isData((d4 = base64Data[dataIndex++]))) {
187 | return null;
188 | }// if found "no data" just return null
189 |
190 | b1 = base64Alphabet[d1];
191 | b2 = base64Alphabet[d2];
192 | b3 = base64Alphabet[d3];
193 | b4 = base64Alphabet[d4];
194 |
195 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
196 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
197 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
198 | }
199 |
200 | if (!isData((d1 = base64Data[dataIndex++]))
201 | || !isData((d2 = base64Data[dataIndex++]))) {
202 | return null;// if found "no data" just return null
203 | }
204 |
205 | b1 = base64Alphabet[d1];
206 | b2 = base64Alphabet[d2];
207 |
208 | d3 = base64Data[dataIndex++];
209 | d4 = base64Data[dataIndex++];
210 | if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
211 | if (isPad(d3) && isPad(d4)) {
212 | if ((b2 & 0xf) != 0)// last 4 bits should be zero
213 | {
214 | return null;
215 | }
216 | byte[] tmp = new byte[i * 3 + 1];
217 | System.arraycopy(decodedData, 0, tmp, 0, i * 3);
218 | tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
219 | return tmp;
220 | } else if (!isPad(d3) && isPad(d4)) {
221 | b3 = base64Alphabet[d3];
222 | if ((b3 & 0x3) != 0)// last 2 bits should be zero
223 | {
224 | return null;
225 | }
226 | byte[] tmp = new byte[i * 3 + 2];
227 | System.arraycopy(decodedData, 0, tmp, 0, i * 3);
228 | tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
229 | tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
230 | return tmp;
231 | } else {
232 | return null;
233 | }
234 | } else { // No PAD e.g 3cQl
235 | b3 = base64Alphabet[d3];
236 | b4 = base64Alphabet[d4];
237 | decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
238 | decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
239 | decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
240 |
241 | }
242 |
243 | return decodedData;
244 | }
245 |
246 | /**
247 | * remove WhiteSpace from MIME containing encoded Base64 data.
248 | *
249 | * @param data
250 | * the byte array of base64 data (with WS)
251 | * @return the new length
252 | */
253 | private static int removeWhiteSpace(char[] data) {
254 | if (data == null) {
255 | return 0;
256 | }
257 |
258 | // count characters that's not whitespace
259 | int newSize = 0;
260 | int len = data.length;
261 | for (int i = 0; i < len; i++) {
262 | if (!isWhiteSpace(data[i])) {
263 | data[newSize++] = data[i];
264 | }
265 | }
266 | return newSize;
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/OrderInfoUtil.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
2 |
3 |
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.net.URLEncoder;
7 | import java.text.SimpleDateFormat;
8 | import java.util.ArrayList;
9 | import java.util.Calendar;
10 | import java.util.Collections;
11 | import java.util.Date;
12 | import java.util.HashMap;
13 | import java.util.List;
14 | import java.util.Locale;
15 | import java.util.Map;
16 | import java.util.Random;
17 |
18 |
19 | public class OrderInfoUtil {
20 |
21 | /**
22 | * 构造授权参数列表
23 | *
24 | * @param pid
25 | * @param app_id
26 | * @param target_id
27 | * @return
28 | */
29 | public static Map buildAuthInfoMap(String pid, String app_id, String target_id, boolean rsa2) {
30 | Map keyValues = new HashMap();
31 |
32 | // 商户签约拿到的app_id,如:2013081700024223
33 | keyValues.put("app_id", app_id);
34 |
35 | // 商户签约拿到的pid,如:2088102123816631
36 | keyValues.put("pid", pid);
37 |
38 | // 服务接口名称, 固定值
39 | keyValues.put("apiname", "com.alipay.account.auth");
40 |
41 | // 商户类型标识, 固定值
42 | keyValues.put("app_name", "mc");
43 |
44 | // 业务类型, 固定值
45 | keyValues.put("biz_type", "openservice");
46 |
47 | // 产品码, 固定值
48 | keyValues.put("product_id", "APP_FAST_LOGIN");
49 |
50 | // 授权范围, 固定值
51 | keyValues.put("scope", "kuaijie");
52 |
53 | // 商户唯一标识,如:kkkkk091125
54 | keyValues.put("target_id", target_id);
55 |
56 | // 授权类型, 固定值
57 | keyValues.put("auth_type", "AUTHACCOUNT");
58 |
59 | // 签名类型
60 | keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");
61 |
62 | return keyValues;
63 | }
64 |
65 | /**
66 | * 构造支付订单参数列表
67 | * @param app_id
68 | * @return
69 | */
70 | public static Map buildOrderParamMap(String app_id,String ordernumber, String price,String subject,String notify_url,boolean rsa2) {
71 | Map keyValues = new HashMap();
72 |
73 | keyValues.put("app_id", app_id);
74 |
75 | keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"out_trade_no\":\"" + ordernumber + "\"}");
76 |
77 | keyValues.put("charset", "utf-8");
78 | keyValues.put("total_amount", price);
79 | keyValues.put("body", ordernumber);
80 | keyValues.put("subject", subject);
81 |
82 | keyValues.put("method", "alipay.trade.app.pay");
83 |
84 | keyValues.put("sign_type", rsa2 ? "RSA2" : "RSA");
85 |
86 | keyValues.put("timestamp", getTimeYMDHMS());
87 | // keyValues.put("timestamp", DatetimeUtil.formatDateTime(new Date()));
88 | keyValues.put("notify_url", notify_url);//回调地址
89 |
90 | keyValues.put("version", "1.0");
91 |
92 | return keyValues;
93 | }
94 |
95 | /**
96 | * 构造支付订单参数信息
97 | *
98 | * @param map
99 | * 支付订单参数
100 | * @return
101 | */
102 | public static String buildOrderParam(Map map) {
103 | List keys = new ArrayList(map.keySet());
104 |
105 | StringBuilder sb = new StringBuilder();
106 | for (int i = 0; i < keys.size() - 1; i++) {
107 | String key = keys.get(i);
108 | String value = map.get(key);
109 | sb.append(buildKeyValue(key, value, true));
110 | sb.append("&");
111 | }
112 |
113 | String tailKey = keys.get(keys.size() - 1);
114 | String tailValue = map.get(tailKey);
115 | sb.append(buildKeyValue(tailKey, tailValue, true));
116 |
117 | return sb.toString();
118 | }
119 |
120 | /**
121 | * 拼接键值对
122 | *
123 | * @param key
124 | * @param value
125 | * @param isEncode
126 | * @return
127 | */
128 | private static String buildKeyValue(String key, String value, boolean isEncode) {
129 | StringBuilder sb = new StringBuilder();
130 | sb.append(key);
131 | sb.append("=");
132 | if (isEncode) {
133 | try {
134 | sb.append(URLEncoder.encode(value, "UTF-8"));
135 | } catch (UnsupportedEncodingException e) {
136 | sb.append(value);
137 | }
138 | } else {
139 | sb.append(value);
140 | }
141 | return sb.toString();
142 | }
143 |
144 | /**
145 | * 对支付参数信息进行签名
146 | *
147 | * @param map
148 | * 待签名授权信息
149 | *
150 | * @return
151 | */
152 | public static String getSign(Map map, String rsaKey, boolean rsa2) {
153 | List keys = new ArrayList(map.keySet());
154 | // key排序
155 | Collections.sort(keys);
156 |
157 | StringBuilder authInfo = new StringBuilder();
158 | for (int i = 0; i < keys.size() - 1; i++) {
159 | String key = keys.get(i);
160 | String value = map.get(key);
161 | authInfo.append(buildKeyValue(key, value, false));
162 | authInfo.append("&");
163 | }
164 |
165 | String tailKey = keys.get(keys.size() - 1);
166 | String tailValue = map.get(tailKey);
167 | authInfo.append(buildKeyValue(tailKey, tailValue, false));
168 |
169 | String oriSign = SignUtils.sign(authInfo.toString(), rsaKey, rsa2);
170 | String encodedSign = "";
171 |
172 | try {
173 | encodedSign = URLEncoder.encode(oriSign, "UTF-8");
174 | } catch (UnsupportedEncodingException e) {
175 | e.printStackTrace();
176 | }
177 | return "sign=" + encodedSign;
178 | }
179 |
180 | /**
181 | * 要求外部订单号必须唯一。
182 | * @return
183 | */
184 | private static String getOutTradeNo() {
185 | SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
186 | Date date = new Date();
187 | String key = format.format(date);
188 |
189 | Random r = new Random();
190 | key = key + r.nextInt();
191 | key = key.substring(0, 15);
192 | return key;
193 | }
194 |
195 |
196 | private static String getTimeYMDHMS() {
197 | Calendar c = Calendar.getInstance();// 可以对每个时间域单独修改
198 |
199 | int year = c.get(Calendar.YEAR);
200 | int month = c.get(Calendar.MONTH) + 1;
201 | int date = c.get(Calendar.DATE);
202 | int hour = c.get(Calendar.HOUR_OF_DAY);
203 | int minute = c.get(Calendar.MINUTE);
204 | int second = c.get(Calendar.SECOND);
205 | String monthstr = "";
206 | String datestr = "";
207 | String hourstr = "";
208 | String minutestr = "";
209 | String secondstr = "";
210 | if (month < 10) {
211 | monthstr = "0" + month;
212 | } else {
213 | monthstr = month + "";
214 | }
215 | if (date < 10) {
216 | datestr = "0" + date;
217 | } else {
218 | datestr = date + "";
219 | }
220 | if (hour < 10) {
221 | hourstr = "0" + hour;
222 | } else {
223 | hourstr = hour + "";
224 | }
225 | if (minute < 10) {
226 | minutestr = "0" + minute;
227 | } else {
228 | minutestr = minute + "";
229 | }
230 | if (second < 10) {
231 | secondstr = "0" + second;
232 | } else {
233 | secondstr = second + "";
234 | }
235 | String time = year + "-" + monthstr + "-" + datestr + " " + hourstr + ":"
236 | + minutestr + ":" + secondstr;
237 | return time;
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/PayResult.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
import android.text.TextUtils;
import java.util.Map;
public class PayResult {
private String resultStatus;
private String result;
private String memo;
public PayResult(Map rawResult) {
if (rawResult == null) {
return;
}
for (String key : rawResult.keySet()) {
if (TextUtils.equals(key, "resultStatus")) {
resultStatus = rawResult.get(key);
} else if (TextUtils.equals(key, "result")) {
result = rawResult.get(key);
} else if (TextUtils.equals(key, "memo")) {
memo = rawResult.get(key);
}
}
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}
}
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/alipay/SignUtils.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.alipay;
2 |
3 | import android.os.Build;
4 |
5 | import java.security.KeyFactory;
6 | import java.security.PrivateKey;
7 | import java.security.spec.PKCS8EncodedKeySpec;
8 |
9 | public class SignUtils {
10 |
11 | private static final String ALGORITHM = "RSA";
12 |
13 | private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
14 |
15 | private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
16 |
17 | private static final String DEFAULT_CHARSET = "UTF-8";
18 |
19 | private static String getAlgorithms(boolean rsa2) {
20 | return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
21 | }
22 |
23 | public static String sign(String content, String privateKey, boolean rsa2) {
24 | try {
25 | PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
26 | Base64.decode(privateKey));
27 | KeyFactory keyf;
28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
29 | keyf = KeyFactory.getInstance("RSA"); //适配Android P及以后版本,否则报错NoSuchAlgorithmException
30 | } else {
31 | keyf = KeyFactory.getInstance("RSA", "BC");
32 | }
33 | PrivateKey priKey = keyf.generatePrivate(priPKCS8);
34 |
35 | java.security.Signature signature = java.security.Signature
36 | .getInstance(getAlgorithms(rsa2));
37 |
38 | signature.initSign(priKey);
39 | signature.update(content.getBytes(DEFAULT_CHARSET));
40 |
41 | byte[] signed = signature.sign();
42 |
43 | return Base64.encode(signed);
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | }
47 |
48 | return null;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/pay/AliPay.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.pay;
2 |
3 | import android.app.Activity;
4 |
5 | import com.zys.paylib.alipay.AlipayUtil;
6 |
7 |
8 | public class AliPay implements IPay {
9 | @Override
10 | public void pay(Activity activity, String paynumbe, double price,
11 | AlipayUtil.AlipayCallBack callback) {
12 | AlipayUtil.getInstance().pay(activity, paynumbe, price + "", callback);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/pay/IPay.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.pay;
2 |
3 | import android.app.Activity;
4 |
5 | import com.zys.paylib.alipay.AlipayUtil;
6 |
7 |
8 | public interface IPay {
9 | void pay(Activity activity, String paynumbe, double price, AlipayUtil.AlipayCallBack callback);
10 | }
11 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/pay/PayTools.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.pay;
2 |
3 | import android.app.Activity;
4 | import android.support.annotation.NonNull;
5 | import android.text.TextUtils;
6 |
7 | import com.zys.paylib.PayConfig;
8 | import com.zys.paylib.alipay.AlipayUtil;
9 | import com.zys.paylib.wxpay.ParameterConfig;
10 | import com.zys.paylib.wxpay.WXPayInfo;
11 | import com.zys.paylib.wxpay.WXPayUtil;
12 |
13 |
14 | public class PayTools {
15 | // private IPay iPay;
16 |
17 | // public PayTools(IPay iPay) {
18 | // this.iPay = iPay;
19 | // }
20 | //
21 | // public void pay(Activity activity, String paynumbe, double price,
22 | // AlipayUtil.AlipayCallBack callback) {
23 | // this.iPay.pay(activity, paynumbe, price, callback);
24 | // }
25 |
26 | public static AlipayTool aliPay(Activity activity) {
27 | return new AlipayTool(activity);
28 | }
29 |
30 | public static class AlipayTool {
31 | private Activity activity;
32 | private String trade_number;
33 | private String intro;
34 | private double money;
35 | private AlipayUtil.AlipayCallBack callBack;
36 |
37 |
38 | /**
39 | * @param activity activity
40 | */
41 | public AlipayTool(Activity activity) {
42 | this.activity = activity;
43 | }
44 |
45 | /**
46 | * @param trade_number 三方预支付订单号
47 | */
48 | public AlipayTool tradeNumber(String trade_number) {
49 | this.trade_number = trade_number;
50 | return this;
51 | }
52 |
53 | /**
54 | * @param intro 支付宝窗口显示的订单信息:默认为 "订单-实际订单号",'-实际订单号'为固定值
55 | * 这里可以修改 "订单-"这两个字,修改为 "测试订单-实际订单号"
56 | * 非必填
57 | */
58 | public AlipayTool intro(String intro) {
59 | this.intro = intro;
60 | return this;
61 | }
62 |
63 | /**
64 | * @param money 实付金额>=0
65 | **/
66 | public AlipayTool money(double money) {
67 | this.money = money;
68 | return this;
69 | }
70 |
71 | /**
72 | * @param callBack 支付宝交易结果回调
73 | */
74 | public void pay(AlipayUtil.AlipayCallBack callBack) {
75 | this.callBack = callBack;
76 | if (null==activity) {
77 | throw new NullPointerException("Activity为空");
78 | }
79 | if (TextUtils.isEmpty(trade_number)) {
80 | throw new NullPointerException("预支付订单号trade_number为空");
81 | }
82 | if (money <= 0) {
83 | throw new NullPointerException("支付金额不能小于0");
84 | }
85 | if (null == callBack) {
86 | throw new NullPointerException("支付回调callBack为空");
87 | }
88 | AlipayUtil.getInstance().pay(activity, trade_number, intro, money + "", callBack);
89 | }
90 |
91 | }
92 |
93 | public static WXPayTool wxPay(Activity activity) {
94 | return new WXPayTool(activity);
95 | }
96 |
97 | public static class WXPayTool {
98 | private Activity activity;
99 | private String trade_number;
100 | private String intro;
101 | private double money;
102 |
103 | /**
104 | * @param activity activity
105 | */
106 | public WXPayTool(Activity activity) {
107 | this.activity = activity;
108 | }
109 |
110 | /**
111 | * @param trade_number 三方预支付订单号
112 | */
113 | public WXPayTool tradeNumber(String trade_number) {
114 | this.trade_number = trade_number;
115 | return this;
116 | }
117 |
118 | /**
119 | * @param intro 支付宝窗口显示的订单信息:默认为 "订单-实际订单号",'-实际订单号'为固定值
120 | * 这里可以修改 "订单-"这两个字,修改为 "测试订单-实际订单号"
121 | * 非必填
122 | */
123 | public WXPayTool intro(String intro) {
124 | this.intro = intro;
125 | return this;
126 | }
127 |
128 | /**
129 | * @param money 实付金额>=0
130 | */
131 | public WXPayTool money(double money) {
132 | this.money = money;
133 | return this;
134 | }
135 |
136 | public void pay() {
137 | if (null == activity) {
138 | throw new NullPointerException("Activity为空");
139 | }
140 | if (TextUtils.isEmpty(trade_number)) {
141 | throw new NullPointerException("预支付订单号trade_number为空");
142 | }
143 | if (money <= 0) {
144 | throw new NullPointerException("支付金额不能小于0");
145 | }
146 | if (TextUtils.isEmpty(intro)) {
147 | new WXPayUtil(activity, new WXPayInfo(ParameterConfig.getIntro(), money),
148 | trade_number);
149 | } else {
150 | new WXPayUtil(activity, new WXPayInfo(intro, money), trade_number);
151 | }
152 | }
153 | }
154 |
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/pay/WxPay.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.pay;
2 |
3 | import android.app.Activity;
4 |
5 | import com.zys.paylib.alipay.AlipayUtil;
6 | import com.zys.paylib.wxpay.ParameterConfig;
7 | import com.zys.paylib.wxpay.WXPayInfo;
8 | import com.zys.paylib.wxpay.WXPayUtil;
9 |
10 |
11 | public class WxPay implements IPay {
12 |
13 | @Override
14 | public void pay(Activity activity, String paynumbe, double price, AlipayUtil.AlipayCallBack callback) {
15 | new WXPayUtil(activity, new WXPayInfo(ParameterConfig.getIntro(), price), paynumbe);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/wxpay/ParameterConfig.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.wxpay;
2 |
3 |
4 |
5 | public class ParameterConfig {
6 | // appid
7 | private static String WX_APP_ID = "";
8 | // 商户号
9 | private static String WX_MCH_ID = "";
10 | // API密钥,在商户平台设置
11 | private static String WX_API_KEY = "";
12 | //自己服务器回调地址
13 | private static String WX_notifyUrl = "";
14 | private static String intro = "订单-";
15 |
16 | public static String getWxAppId() {
17 | return WX_APP_ID;
18 | }
19 |
20 | public static void setWxAppId(String wxAppId) {
21 | WX_APP_ID = wxAppId;
22 | }
23 |
24 | public static String getWxMchId() {
25 | return WX_MCH_ID;
26 | }
27 |
28 | public static void setWxMchId(String wxMchId) {
29 | WX_MCH_ID = wxMchId;
30 | }
31 |
32 | public static String getWxApiKey() {
33 | return WX_API_KEY;
34 | }
35 |
36 | public static void setWxApiKey(String wxApiKey) {
37 | WX_API_KEY = wxApiKey;
38 | }
39 |
40 | public static String getWX_notifyUrl() {
41 | return WX_notifyUrl;
42 | }
43 |
44 | public static void setWX_notifyUrl(String WX_notifyUrl) {
45 | ParameterConfig.WX_notifyUrl = WX_notifyUrl;
46 | }
47 |
48 | public static String getIntro() {
49 | return intro;
50 | }
51 |
52 | public static void setIntro(String i) {
53 | intro = i;
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/wxpay/WXPayInfo.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.wxpay;
2 |
3 | import java.io.Serializable;
4 |
5 |
6 | public class WXPayInfo implements Serializable {
7 | private String productname;
8 | private double totalamount;
9 |
10 | public WXPayInfo(String productname, double totalamount) {
11 | this.productname = productname;
12 | this.totalamount = totalamount;
13 | }
14 |
15 | public String getProductname() {
16 | return productname;
17 | }
18 |
19 | public void setProductname(String productname) {
20 | this.productname = productname;
21 | }
22 |
23 | public double getTotalamount() {
24 | return totalamount;
25 | }
26 |
27 | public void setTotalamount(double totalamount) {
28 | this.totalamount = totalamount;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/paylib/src/main/java/com/zys/paylib/wxpay/WXPayUtil.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib.wxpay;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.app.ProgressDialog;
6 | import android.content.Context;
7 | import android.content.DialogInterface;
8 | import android.os.AsyncTask;
9 | import android.text.TextUtils;
10 | import android.util.Log;
11 | import android.util.Xml;
12 | import android.widget.Toast;
13 |
14 | import com.tencent.mm.opensdk.modelpay.PayReq;
15 | import com.tencent.mm.opensdk.openapi.IWXAPI;
16 | import com.tencent.mm.opensdk.openapi.WXAPIFactory;
17 |
18 | import org.apache.http.HttpResponse;
19 | import org.apache.http.HttpStatus;
20 | import org.apache.http.HttpVersion;
21 | import org.apache.http.NameValuePair;
22 | import org.apache.http.client.HttpClient;
23 | import org.apache.http.client.methods.HttpPost;
24 | import org.apache.http.conn.ClientConnectionManager;
25 | import org.apache.http.conn.scheme.PlainSocketFactory;
26 | import org.apache.http.conn.scheme.Scheme;
27 | import org.apache.http.conn.scheme.SchemeRegistry;
28 | import org.apache.http.conn.ssl.SSLSocketFactory;
29 | import org.apache.http.conn.util.InetAddressUtils;
30 | import org.apache.http.entity.StringEntity;
31 | import org.apache.http.impl.client.DefaultHttpClient;
32 | import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
33 | import org.apache.http.message.BasicNameValuePair;
34 | import org.apache.http.params.BasicHttpParams;
35 | import org.apache.http.params.HttpParams;
36 | import org.apache.http.params.HttpProtocolParams;
37 | import org.apache.http.protocol.HTTP;
38 | import org.apache.http.util.EntityUtils;
39 | import org.xmlpull.v1.XmlPullParser;
40 |
41 | import java.io.IOException;
42 | import java.io.StringReader;
43 | import java.net.InetAddress;
44 | import java.net.NetworkInterface;
45 | import java.net.Socket;
46 | import java.net.SocketException;
47 | import java.net.UnknownHostException;
48 | import java.security.KeyManagementException;
49 | import java.security.KeyStore;
50 | import java.security.KeyStoreException;
51 | import java.security.MessageDigest;
52 | import java.security.NoSuchAlgorithmException;
53 | import java.security.UnrecoverableKeyException;
54 | import java.security.cert.X509Certificate;
55 | import java.util.Enumeration;
56 | import java.util.HashMap;
57 | import java.util.LinkedList;
58 | import java.util.List;
59 | import java.util.Map;
60 | import java.util.Random;
61 |
62 | import javax.net.ssl.SSLContext;
63 | import javax.net.ssl.TrustManager;
64 | import javax.net.ssl.X509TrustManager;
65 |
66 |
67 |
68 | public class WXPayUtil {
69 | private IWXAPI api;
70 | private WXPayInfo order;
71 | private PayReq req;
72 | private Map resultunifiedorder;
73 | private Context context;
74 | private String tradenumber;
75 |
76 | public WXPayUtil(Context mcontext, WXPayInfo order, String tradenumber){//初始化微信支付
77 | this.order=order;
78 | this.context=mcontext;
79 | this.tradenumber = tradenumber;
80 | if (TextUtils.isEmpty(ParameterConfig.getWxAppId()) || TextUtils.isEmpty(ParameterConfig.getWxMchId()) || TextUtils.isEmpty(ParameterConfig.getWxApiKey())|| TextUtils.isEmpty(ParameterConfig.getWX_notifyUrl())) {
81 | new AlertDialog.Builder(context).setTitle("警告").setMessage("需要配置WX_APP_ID | WX_MCH_ID| WX_API_KEY| WX_NOTIFY_URL\n请调用PayConfig进行初始化配置")
82 | .setPositiveButton("确定", new DialogInterface.OnClickListener() {
83 | @Override
84 | public void onClick(DialogInterface dialoginterface, int i) {
85 | }
86 | }).show();
87 | return;
88 | }
89 |
90 | api = WXAPIFactory.createWXAPI(context, null);
91 | api.registerApp(ParameterConfig.getWxAppId());
92 | boolean isWXAppInstalled=api.isWXAppInstalled();
93 | if (!isWXAppInstalled){
94 | Toast.makeText(mcontext,"未安装微信,请先安装微信!", Toast.LENGTH_SHORT).show();
95 | return ;
96 | }
97 | req = new PayReq();
98 | //生成prepay_id
99 | GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
100 | getPrepayId.execute();
101 | }
102 |
103 |
104 | /**
105 | * 用于获取
106 | * @author 95
107 | *
108 | */
109 | private class GetPrepayIdTask extends AsyncTask> {
110 |
111 | private ProgressDialog dialog;
112 | @Override
113 | protected void onPreExecute() {
114 | dialog = ProgressDialog.show(context, "提示", "正在获取预支付订单...");
115 | }
116 |
117 | @Override
118 | protected void onPostExecute(Map result) {
119 | if (dialog != null) {
120 | dialog.dismiss();
121 | }
122 | resultunifiedorder=result;
123 | Log.e("resultunifiedorder",resultunifiedorder.toString());
124 | genPayReq();
125 | //sendPayReq();
126 | }
127 |
128 | @Override
129 | protected void onCancelled() {
130 | super.onCancelled();
131 | }
132 |
133 | @Override
134 | protected Map doInBackground(Void... params) {
135 |
136 | String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
137 | String entity = genProductArgs();
138 |
139 | byte[] buf = httpPost(url,entity);
140 | String content = new String(buf);
141 | Map xml=decodeXml(content);
142 | return xml;
143 | }
144 | }
145 |
146 | private void genPayReq() {
147 |
148 | req.appId = ParameterConfig.getWxAppId();
149 | req.partnerId = ParameterConfig.getWxMchId();
150 | req.prepayId = resultunifiedorder.get("prepay_id");
151 | //req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");
152 | req.packageValue = "Sign=WXPay";
153 | req.nonceStr = genNonceStr();
154 | req.timeStamp = String.valueOf(genTimeStamp());
155 |
156 |
157 | List signParams = new LinkedList();
158 | signParams.add(new BasicNameValuePair("appid", req.appId));
159 | signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
160 | signParams.add(new BasicNameValuePair("package", req.packageValue));
161 | signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
162 | signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
163 | signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
164 |
165 | req.sign = genAppSign(signParams);
166 | Log.e("orion", signParams.toString());
167 | sendPayReq();
168 | }
169 | private void sendPayReq() {
170 | // api.registerApp(ParameterConfig.getWxAppId());
171 | api.sendReq(req);
172 |
173 | }
174 |
175 | private String genProductArgs() {
176 | StringBuffer xml = new StringBuffer();
177 |
178 | try {
179 | String nonceStr = genNonceStr();
180 | xml.append("");
181 | List packageParams = new LinkedList();
182 | packageParams.add(new BasicNameValuePair("appid", ParameterConfig.getWxAppId()));
183 | packageParams.add(new BasicNameValuePair("body", order.getProductname()));
184 | packageParams.add(new BasicNameValuePair("mch_id", ParameterConfig.getWxMchId()));
185 | packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
186 | packageParams.add(new BasicNameValuePair("notify_url", ParameterConfig.getWX_notifyUrl()));
187 | packageParams.add(new BasicNameValuePair("out_trade_no",tradenumber));//订单号
188 | packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
189 | packageParams.add(new BasicNameValuePair("total_fee", String.valueOf((int)(order.getTotalamount()*100)+"")));
190 | packageParams.add(new BasicNameValuePair("trade_type", "APP"));
191 |
192 | String sign = genPackageSign(packageParams);
193 | packageParams.add(new BasicNameValuePair("sign", sign));
194 | String xmlstring =toXml(packageParams);
195 | return new String(xmlstring.toString().getBytes(), "ISO8859-1");
196 | //return xmlstring;
197 |
198 | } catch (Exception e) {
199 | return null;
200 | }
201 | }
202 | //获取手机IP
203 | public String getLocalHostIp() {
204 | String ipaddress = "";
205 | try {
206 | Enumeration en = NetworkInterface.getNetworkInterfaces();
207 | // 遍历所用的网络接口
208 | while (en.hasMoreElements()) {
209 | NetworkInterface nif = en.nextElement();// 得到每一个网络接口绑定的所有ip
210 | Enumeration inet = nif.getInetAddresses();
211 | // 遍历每一个接口绑定的所有ip
212 | while (inet.hasMoreElements()) {
213 | InetAddress ip = inet.nextElement();
214 | if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip.getHostAddress())) {
215 | return ip.getHostAddress();
216 | }
217 | }
218 | }
219 | }
220 | catch (SocketException e) {
221 | Log.e("feige", "获取本地ip地址失败");
222 | e.printStackTrace();
223 | }
224 | return ipaddress;
225 | }
226 |
227 | private String genAppSign(List params) {
228 | StringBuilder sb = new StringBuilder();
229 |
230 | for (int i = 0; i < params.size(); i++) {
231 | sb.append(params.get(i).getName());
232 | sb.append('=');
233 | sb.append(params.get(i).getValue());
234 | sb.append('&');
235 | }
236 | sb.append("key=");
237 | sb.append(ParameterConfig.getWxApiKey());
238 |
239 |
240 | String appSign = getMessageDigest(sb.toString().getBytes());
241 | Log.e("orion",appSign);
242 | return appSign;
243 | }
244 |
245 |
246 | private static class SSLSocketFactoryEx extends SSLSocketFactory {
247 |
248 | SSLContext sslContext = SSLContext.getInstance("TLS");
249 |
250 | public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
251 | super(truststore);
252 |
253 | TrustManager tm = new X509TrustManager() {
254 |
255 | @Override
256 | public X509Certificate[] getAcceptedIssuers() {
257 | return null;
258 | }
259 |
260 | @Override
261 | public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
262 | }
263 |
264 | @Override
265 | public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
266 | }
267 | };
268 |
269 | sslContext.init(null, new TrustManager[] { tm }, null);
270 | }
271 |
272 | @Override
273 | public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
274 | return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
275 | }
276 |
277 | @Override
278 | public Socket createSocket() throws IOException {
279 | return sslContext.getSocketFactory().createSocket();
280 | }
281 | }
282 | public static byte[] httpPost(String url, String entity) {
283 | if (url == null || url.length() == 0) {
284 | return null;
285 | }
286 |
287 | HttpClient httpClient = getNewHttpClient();
288 |
289 | HttpPost httpPost = new HttpPost(url);
290 |
291 | try {
292 | httpPost.setEntity(new StringEntity(entity));
293 | httpPost.setHeader("Accept", "application/json");
294 | httpPost.setHeader("Content-type", "application/json");
295 |
296 | HttpResponse resp = httpClient.execute(httpPost);
297 | if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
298 | return null;
299 | }
300 |
301 | return EntityUtils.toByteArray(resp.getEntity());
302 | } catch (Exception e) {
303 | e.printStackTrace();
304 | Log.e("orion--------","报错了");
305 | return null;
306 | }
307 | }
308 |
309 | private static HttpClient getNewHttpClient() {
310 | try {
311 | KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
312 | trustStore.load(null, null);
313 |
314 | SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
315 | sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
316 |
317 | HttpParams params = new BasicHttpParams();
318 | HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
319 | HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
320 |
321 | SchemeRegistry registry = new SchemeRegistry();
322 | registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
323 | registry.register(new Scheme("https", sf, 443));
324 |
325 | ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
326 |
327 | return new DefaultHttpClient(ccm, params);
328 | } catch (Exception e) {
329 | return new DefaultHttpClient();
330 | }
331 | }
332 |
333 |
334 | private String genOutTradNo() {
335 | Random random = new Random();
336 | return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
337 | }
338 |
339 | public Map decodeXml(String content) {
340 |
341 | try {
342 | Map xml = new HashMap();
343 | XmlPullParser parser = Xml.newPullParser();
344 | parser.setInput(new StringReader(content));
345 | int event = parser.getEventType();
346 | while (event != XmlPullParser.END_DOCUMENT) {
347 |
348 | String nodeName=parser.getName();
349 | switch (event) {
350 | case XmlPullParser.START_DOCUMENT:
351 |
352 | break;
353 | case XmlPullParser.START_TAG:
354 |
355 | if("xml".equals(nodeName)==false){
356 | //实例化student对象
357 | xml.put(nodeName,parser.nextText());
358 | }
359 | break;
360 | case XmlPullParser.END_TAG:
361 | break;
362 | }
363 | event = parser.next();
364 | }
365 |
366 | return xml;
367 | } catch (Exception e) {
368 | Log.e("orion",e.toString());
369 | }
370 | return null;
371 |
372 | }
373 |
374 | private String genNonceStr() {
375 | Random random = new Random();
376 | return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
377 | }
378 |
379 | private long genTimeStamp() {
380 | return System.currentTimeMillis() / 1000;
381 | }
382 |
383 | public String getMessageDigest(byte[] buffer) {
384 | char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
385 | try {
386 | MessageDigest mdTemp = MessageDigest.getInstance("MD5");
387 | mdTemp.update(buffer);
388 | byte[] md = mdTemp.digest();
389 | int j = md.length;
390 | char str[] = new char[j * 2];
391 | int k = 0;
392 | for (int i = 0; i < j; i++) {
393 | byte byte0 = md[i];
394 | str[k++] = hexDigits[byte0 >>> 4 & 0xf];
395 | str[k++] = hexDigits[byte0 & 0xf];
396 | }
397 | return new String(str);
398 | } catch (Exception e) {
399 | return null;
400 | }
401 | }
402 |
403 | /**
404 | 生成签名
405 | */
406 |
407 | private String genPackageSign(List params) {
408 | StringBuilder sb = new StringBuilder();
409 |
410 | for (int i = 0; i < params.size(); i++) {
411 | sb.append(params.get(i).getName());
412 | sb.append('=');
413 | sb.append(params.get(i).getValue());
414 | sb.append('&');
415 | }
416 | sb.append("key=");
417 | sb.append(ParameterConfig.getWxApiKey());
418 |
419 |
420 | String packageSign = getMessageDigest(sb.toString().getBytes()).toUpperCase();
421 | Log.e("orion",packageSign);
422 | return packageSign;
423 | }
424 |
425 | private String toXml(List params) {
426 | StringBuilder sb = new StringBuilder();
427 | sb.append("");
428 | for (int i = 0; i < params.size(); i++) {
429 | sb.append("<"+params.get(i).getName()+">");
430 |
431 |
432 | sb.append(params.get(i).getValue());
433 | sb.append(""+params.get(i).getName()+">");
434 | }
435 | sb.append("");
436 |
437 | Log.e("orion",sb.toString());
438 | return sb.toString();
439 | }
440 | }
441 |
--------------------------------------------------------------------------------
/paylib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | paylib
3 |
4 |
--------------------------------------------------------------------------------
/paylib/src/test/java/com/zys/paylib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zys.paylib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.zys.zyspay.demo"
7 | minSdkVersion 19
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'com.android.support:appcompat-v7:28.0.0'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
28 | implementation project(':paylib')
29 | }
30 |
--------------------------------------------------------------------------------
/sample/class_files.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/class_files.txt
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\AndroidSDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 | #指定代码的压缩级别
27 | -optimizationpasses 5
28 |
29 | #包明不混合大小写
30 | -dontusemixedcaseclassnames
31 |
32 | #不去忽略非公共的库类
33 | -dontskipnonpubliclibraryclasses
34 |
35 | #优化 不优化输入的类文件
36 | -dontoptimize
37 |
38 | #预校验
39 | -dontpreverify
40 |
41 | #混淆时是否记录日志
42 | -verbose
43 |
44 | # 混淆时所采用的算法
45 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
46 |
47 | #保护注解
48 | -keepattributes *Annotation*
49 |
50 | # 保持哪些类不被混淆
51 | -keep public class * extends android.app.Fragment
52 | -keep public class * extends android.app.Activity
53 | -keep public class * extends android.app.Application
54 | -keep public class * extends android.app.Service
55 | -keep public class * extends android.content.BroadcastReceiver
56 | -keep public class * extends android.content.ContentProvider
57 | -keep public class * extends android.app.backup.BackupAgentHelper
58 | -keep public class * extends android.preference.Preference
59 | -keep public class com.android.vending.licensing.ILicensingService
60 | #如果有引用v4包可以添加下面这行
61 | -keep public class * extends android.support.v4.app.Fragment
62 |
63 | ##忽略警告
64 | #-dontwarn
65 | -ignorewarnings
66 | ##记录生成的日志数据,gradle build时在本项目根目录输出##
67 | #apk 包内所有 class 的内部结构
68 | -dump proguard/class_files.txt
69 | #未混淆的类和成员
70 | -printseeds proguard/seeds.txt
71 | #列出从 apk 中删除的代码
72 | -printusage proguard/unused.txt
73 | #混淆前后的映射
74 | -printmapping proguard/mapping.txt
75 | ########记录生成的日志数据,gradle build时 在本项目根目录输出-end######
76 |
77 | #如果引用了v4或者v7包
78 | -dontwarn android.support.**
79 |
80 | ####混淆保护自己项目的部分代码以及引用的第三方jar包library-end####
81 |
82 |
83 |
84 | #保持 native 方法不被混淆
85 | -keepclasseswithmembernames class * {
86 | native ;
87 | }
88 |
89 | #保持自定义控件类不被混淆
90 | -keepclasseswithmembers class * {
91 | public (android.content.Context, android.util.AttributeSet);
92 | }
93 |
94 | #保持自定义控件类不被混淆
95 | -keepclassmembers class * extends android.app.Activity {
96 | public void *(android.view.View);
97 | }
98 |
99 | -keep public class * extends android.view.View {
100 | public (android.content.Context);
101 | public (android.content.Context, android.util.AttributeSet);
102 | public (android.content.Context, android.util.AttributeSet, int);
103 | public void set*(...);
104 | }
105 |
106 | #保持 Parcelable 不被混淆
107 | -keep class * implements android.os.Parcelable {
108 | public static final android.os.Parcelable$Creator *;
109 | }
110 |
111 | #保持 Serializable 不被混淆
112 | -keepnames class * implements java.io.Serializable
113 |
114 | #保持 Serializable 不被混淆并且enum 类也不被混淆
115 | -keepclassmembers class * implements java.io.Serializable {
116 | static final long serialVersionUID;
117 | private static final java.io.ObjectStreamField[] serialPersistentFields;
118 | !static !transient ;
119 | !private ;
120 | !private ;
121 | private void writeObject(java.io.ObjectOutputStream);
122 | private void readObject(java.io.ObjectInputStream);
123 | java.lang.Object writeReplace();
124 | java.lang.Object readResolve();
125 | }
126 |
127 | #保持枚举 enum 类不被混淆
128 | -keepclassmembers enum * {
129 | public static **[] values();
130 | public static ** valueOf(java.lang.String);
131 | }
132 |
133 | -keepclassmembers class * {
134 | public void *ButtonClicked(android.view.View);
135 | }
136 |
137 | #不混淆资源类
138 | -keepclassmembers class **.R$* {
139 | public static ;
140 | }
141 |
142 | #避免混淆泛型 如果混淆报错建议关掉
143 | #-keepattributes Signature
144 |
145 | #移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
146 | -assumenosideeffects class android.util.Log {
147 | public static *** v(...);
148 | public static *** i(...);
149 | public static *** d(...);
150 | public static *** w(...);
151 | public static *** e(...);
152 | }
153 |
154 | #############################################################################################
155 | ######################## 以上通用 ##################################
156 | #############################################################################################
157 | #gson
158 | #如果用用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错。
159 | -keepattributes Signature
160 | # Gson specific classes
161 | -keep class sun.misc.Unsafe { *; }
162 | # Application classes that will be serialized/deserialized over Gson
163 | -keep class com.google.gson.** { *; }
164 | -keep class com.google.gson.stream.** { *; }
165 |
166 | #极光
167 | -dontoptimize
168 | -dontpreverify
169 |
170 | -dontwarn cn.jpush.**
171 | -keep class cn.jpush.** { *; }
172 |
173 | -dontwarn cn.jiguang.**
174 | -keep class cn.jiguang.** { *; }
175 |
176 | #友盟
177 | -dontusemixedcaseclassnames
178 | -dontshrink
179 | -dontoptimize
180 | -dontwarn com.google.android.maps.**
181 | -dontwarn android.webkit.WebView
182 | -keep public class javax.**
183 | -keep public class android.webkit.**
184 | -dontwarn android.support.v4.**
185 | -keep enum com.facebook.**
186 | -keepattributes Exceptions,InnerClasses,Signature
187 | -keepattributes *Annotation*
188 | -keepattributes SourceFile,LineNumberTable
189 |
190 | -keep public interface com.facebook.**
191 | -keep public interface com.tencent.**
192 | -keep public interface com.umeng.socialize.**
193 | -keep public interface com.umeng.socialize.sensor.**
194 | -keep public interface com.umeng.scrshot.**
195 | -keep class com.android.dingtalk.share.ddsharemodule.** { *; }
196 | -keep public class com.umeng.socialize.* {*;}
197 |
198 |
199 | -keep class com.tencent.** {*;}
200 | -dontwarn com.tencent.**
201 | -keep public class com.umeng.com.umeng.soexample.R$*{
202 | public static final int *;
203 | }
204 | -keep public class com.linkedin.android.mobilesdk.R$*{
205 | public static final int *;
206 | }
207 | -keepclassmembers enum * {
208 | public static **[] values();
209 | public static ** valueOf(java.lang.String);
210 | }
211 |
212 | -keep class com.tencent.open.TDialog$*
213 | -keep class com.tencent.open.TDialog$* {*;}
214 | -keep class com.tencent.open.PKDialog
215 | -keep class com.tencent.open.PKDialog {*;}
216 | -keep class com.tencent.open.PKDialog$*
217 | -keep class com.tencent.open.PKDialog$* {*;}
218 |
219 | -keep class com.sina.** {*;}
220 | -dontwarn com.sina.**
221 | -keep class com.alipay.share.sdk.** {
222 | *;
223 | }
224 | -keepnames class * implements android.os.Parcelable {
225 | public static final ** CREATOR;
226 | }
227 |
228 | -keep class com.linkedin.** { *; }
229 | -keepattributes Signature
230 |
231 | #支付宝
232 | #-libraryjars libs/alipaysingle-20170510.jar
233 |
234 | -keep class com.alipay.android.app.IAlixPay{*;}
235 | -keep class com.alipay.android.app.IAlixPay$Stub{*;}
236 | -keep class com.alipay.android.app.IRemoteServiceCallback{*;}
237 | -keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
238 | -keep class com.alipay.sdk.app.PayTask{ public *;}
239 | -keep class com.alipay.sdk.app.AuthTask{ public *;}
240 |
241 | -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep class com.tencent.android.tpush.** {* ;}
242 | -keep class com.tencent.mid.** {* ;}
243 |
244 | -keep class butterknife.** { *; }
245 | -dontwarn butterknife.internal.**
246 | -keep class **$$ViewBinder { *; }
247 |
248 | -keepclasseswithmembernames class * {
249 | @butterknife.* ;
250 | }
251 |
252 | -keepclasseswithmembernames class * {
253 | @butterknife.* ;
254 | }
255 | -keep class com.baidu.** {*;}
256 | -keep class vi.com.** {*;}
257 | -dontwarn com.baidu.**
258 |
259 | -dontwarn com.yanzhenjie.album.**
260 | -keep class com.yanzhenjie.album.**{*;}
261 |
262 | -keep class cn.finalteam.galleryfinal.widget.*{*;}
263 | -keep class cn.finalteam.galleryfinal.widget.crop.*{*;}
264 | -keep class cn.finalteam.galleryfinal.widget.zoonview.*{*;}
265 |
266 | -keep class cn.sharesdk.**{*;}
267 | -keep class com.sina.**{*;}
268 | -keep class **.R$* {*;}
269 | -keep class **.R{*;}
270 | -keep class com.mob.**{*;}
271 | -dontwarn com.mob.**
272 | -dontwarn cn.sharesdk.**
273 | -dontwarn **.R$*
274 |
275 | -keep class com.qiyukf.** {*;}
276 | -dontwarn com.qiyukf.**
277 | -keep public class com.alibaba.android.arouter.routes.**{*;}
278 | -keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
279 |
280 | -dontwarn com.google.**
281 |
282 | -dontwarn com.android.**
283 |
284 |
285 | #如果你使用全文检索插件,需要加入
286 | -dontwarn org.apache.lucene.**
287 | -keep class org.apache.lucene.** {*;}
288 |
289 |
290 |
--------------------------------------------------------------------------------
/sample/src/androidTest/java/com/zys/zyspay/demo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zys.zyspay.demo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.zys.zyspay.demo", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/zys/zyspay/demo/App.java:
--------------------------------------------------------------------------------
1 | package com.zys.zyspay.demo;
2 |
3 | import android.app.Application;
4 |
5 | import com.zys.paylib.PayConfig;
6 |
7 | public class App extends Application {
8 |
9 | private final String RSA_PRIVATE = "MIIEv****很长很长******stnwxntWIrgr/fvtXuyXSfI=";
10 |
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 |
16 | //用到支付宝的时候配置
17 | PayConfig.alipay()
18 | .appId("2017******3659")
19 | .rsa(RSA_PRIVATE)
20 | .notifyUrl("http://www.xx**xx.com/api/trade/notify/alipay")
21 | .intro("支付宝订单-")//非必填
22 | .init();
23 |
24 | //用到微信的时候配置
25 | PayConfig.wxpay()
26 | .appId("wx62*******87")
27 | .mchId("15******1")
28 | .apiKey("Rd88G******I0ci406")
29 | .notifyUrl("http://www.xx**xx.com/api/trade/notify/wxpay")
30 | .intro("微信订单-")//非必填
31 | .init();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/zys/zyspay/demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.zys.zyspay.demo;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 |
6 | import com.zys.paylib.alipay.AlipayUtil;
7 | import com.zys.paylib.pay.AliPay;
8 | import com.zys.paylib.pay.PayTools;
9 | import com.zys.paylib.pay.WxPay;
10 |
11 | public class MainActivity extends AppCompatActivity {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 | setContentView(R.layout.activity_main);
17 |
18 | }
19 |
20 |
21 | private void toAliPay() {
22 | String tradenumber = "这里是实际交易订单号-服务器返回";
23 | double money=0.01;//需要支付的金额
24 | PayTools.aliPay(this)
25 | .tradeNumber(tradenumber)
26 | .money(money)
27 | .intro("订单-")//(非必填)
28 | .pay(new AlipayUtil.AlipayCallBack() {
29 | @Override
30 | public void success(String ordernumber, String resultInfo) {
31 |
32 | }
33 |
34 | @Override
35 | public void fail(String resultInfo) {
36 |
37 | }
38 |
39 | });
40 |
41 | }
42 |
43 | private void toWXPay() {
44 | String tradenumber = "这里是实际交易订单号-服务器返回";
45 | double money=0.01;//需要支付的金额
46 | PayTools.wxPay(this)
47 | .tradeNumber(tradenumber)
48 | .intro("订单-")//(非必填)
49 | .money(money)
50 | .pay();//支付回调在WXPayEntryActivity
51 |
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/zys/zyspay/demo/wxapi/WXPayEntryActivity.java:
--------------------------------------------------------------------------------
1 | package com.zys.zyspay.demo.wxapi;
2 |
3 |
4 | import android.app.Activity;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import com.tencent.mm.opensdk.constants.ConstantsAPI;
11 | import com.tencent.mm.opensdk.modelbase.BaseReq;
12 | import com.tencent.mm.opensdk.modelbase.BaseResp;
13 | import com.tencent.mm.opensdk.openapi.IWXAPI;
14 | import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
15 | import com.tencent.mm.opensdk.openapi.WXAPIFactory;
16 | import com.zys.paylib.wxpay.ParameterConfig;
17 | import com.zys.zyspay.demo.R;
18 |
19 |
20 | public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
21 | private IWXAPI api;
22 |
23 | // private TextView reulttv;
24 | @Override
25 | public void onCreate(Bundle savedInstanceState) {
26 | try {
27 | super.onCreate(savedInstanceState);
28 | } catch (Exception e) {
29 | e.printStackTrace();
30 | }
31 | setContentView(R.layout.wx_pay_result);
32 | api = WXAPIFactory.createWXAPI(this, ParameterConfig.getWxAppId());
33 | api.handleIntent(getIntent(), this);
34 | }
35 |
36 | @Override
37 | protected void onNewIntent(Intent intent) {
38 | super.onNewIntent(intent);
39 | setIntent(intent);
40 | api.handleIntent(intent, this);
41 | }
42 |
43 | @Override
44 | public void onReq(BaseReq req) {
45 |
46 | }
47 |
48 | @Override
49 | public void onResp(BaseResp resp) {
50 | if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
51 | Log.e("WXPayEntryActivity",resp.toString());
52 | int code = resp.errCode;
53 | switch (code) {
54 | case 0:
55 | Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();
56 | //可以使用EventBus通知支付成功
57 | // EventBusUtil.post(EventConstant.WXPAYORDERSUCCESS);
58 | finish();
59 | break;
60 | case -1:
61 | Toast.makeText(this, "支付失败", Toast.LENGTH_SHORT).show();
62 | finish();
63 | break;
64 | case -2:
65 | Toast.makeText(this, "支付取消", Toast.LENGTH_SHORT).show();
66 | finish();
67 | break;
68 | default:
69 | break;
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
21 |
26 |
31 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
71 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
116 |
121 |
126 |
131 |
136 |
141 |
146 |
151 |
156 |
161 |
166 |
171 |
172 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
23 |
24 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/wx_pay_result.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Equalzys/PayLib/613b325496b6f03843be57ba8f817f3a9feab226/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ZYSPayDemo
3 |
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/src/test/java/com/zys/zyspay/demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zys.zyspay.demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':paylib'
2 |
--------------------------------------------------------------------------------