diff --git a/README.md b/README.md index 716897f..257bedd 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,13 @@ [![Bintray](https://img.shields.io/bintray/v/jamling/maven/af-pay.svg?maxAge=86400)](https://bintray.com/jamling/maven/af-pay) [![Jitpack](https://jitpack.io/v/Jamling/af-pay.svg)](https://jitpack.io/#Jamling/af-pay) -Af-pay原为[QuickAF](一个快速的Android开发框架)中的支付组件,现已抽取出来作为一个单独的Android支付库, 支持支付宝,微信支付,并且同时支持客户端下单与服务端下单。 - -## 引入 -**注:如果不想引入支付依赖的jar,请使用`pure`分支或版本** +af-pay原为[QuickAF](一个快速的Android开发框架)中的支付组件,现已抽取出来作为一个单独的Android支付库, 支持支付宝,微信支付,并且同时支持客户端下单与服务端下单。 +af-pay有两个版本 +- 完整版本:包含支付宝等支付平台的依赖jar +- 纯净版本:*不*包含支付宝等支付平台的依赖jar,以避免和其它库(如友盟分享库)冲突,需要你自己引入相关的jar,否则运行时将crash。 +## 在gradle中引入 +**再次提醒:如果不想引入支付依赖的jar,请使用`pure`分支或版本** *`pure`版本不包含任何支付平台的相关jar包,如果您的工程中原来已经包含了如微信分享(libammsdk.jar)jar,则会出现冲突,导致打包失败。建议引入纯净版* ### 在Android中直接使用 @@ -16,19 +18,19 @@ Af-pay原为[QuickAF](一个快速的Android开发框架)中的支付组件 - 引入完整版本,包含支付平台相关的jar包 ```gradle dependencies { - compile 'cn.ieclipse.af:af-pay:0.0.1' + compile 'cn.ieclipse.af:af-pay:0.0.2' } ``` - 引入纯净版本 ```gradle dependencies { - compile 'cn.ieclipse.af:af-pay-pure:0.0.1' + compile 'cn.ieclipse.af:af-pay-pure:0.0.2' } ``` ### 使用jitpack.io仓库 -1,要工程根目录中的build.gradle中添加jitpack仓库 +1,在工程根目录中的build.gradle中添加jitpack仓库 ```gradle allprojects { @@ -112,50 +114,60 @@ Af-pay原为[QuickAF](一个快速的Android开发框架)中的支付组件 ### 微信支付 ```java - private void doWxpay(String orderInfo) { - final Activity activity = this; - Wxpay wxpay = Wxpay.getInstance(activity); - wxpay.setPayListener(new cn.ieclipse.pay.wxpay.Wxpay.PayListener() { - @Override - public void onPaySuccess(BaseResp resp) { - showToast(activity, "支付成功:" + resp.errStr); - } - - @Override - public void onPayCanceled(BaseResp resp) { - showToast(activity, "支付取消"); - } - - @Override - public void onPayFailure(BaseResp resp) { - showToast(activity, "支付失败:" + resp.errStr); - } - }); - if (!TextUtils.isEmpty(orderInfo)) { - PayReq req = OrderInfoUtil.getPayReq(orderInfo); - wxpay.pay(req); +private void doWxpay(String orderInfo) { + final Activity activity = this; + // 获取支付类 + Wxpay wxpay = Wxpay.getInstance(activity); + // 设置支付回调监听 + wxpay.setPayListener(new Wxpay.PayListener() { + @Override + public void onPaySuccess(BaseResp resp) { + showToast(activity, "支付成功"); } - else { - Wxpay.DEBUG = true; - Wxpay.Config.api_key = ""; - Wxpay.Config.app_id = ""; - Wxpay.Config.mch_id = ""; - Wxpay.Config.notify_url = "app/pay/wxpay_notify.do"; - - Wxpay.DefaultOrderTask task = new Wxpay.DefaultOrderTask(wxpay); - String trans_order_id = OrderInfoUtil2_0.genOutTradeNo(); - task.setParams(OrderInfoUtil.buildOrderParamMap(trans_order_id, "测试支付", "", "1", null, null, null)); - task.execute(); + + @Override + public void onPayCanceled(BaseResp resp) { + showToast(activity, "支付取消"); + } + + @Override + public void onPayFailure(BaseResp resp) { + showToast(activity, "支付失败"); } + }); + // 这里是服务端下单,内容是统一下单返回的xml + if (!TextUtils.isEmpty(orderInfo)) { + PayReq req = OrderInfoUtil.getPayReq(orderInfo); + wxpay.pay(req); + } + else { // 客户端下单 + Wxpay.DEBUG = true; // 开启日志 + // API密钥,在微信商户平台设置 + Wxpay.Config.api_key = "32位的字串"; + // APPID,在微信开放平台创建应用后生成 + Wxpay.Config.app_id = "wx..."; + // 商户ID,注册商户平台后生成 + Wxpay.Config.mch_id = "14..."; + // 支付结果异步通知接口,由后台开发提供 + Wxpay.Config.notify_url = "http://www.ieclipse.cn/app/pay/wxpay_notify.do"; + // 创建统一下单异步任务 + Wxpay.DefaultOrderTask task = new Wxpay.DefaultOrderTask(wxpay); + // 这个商户订单号,由后台返回,在这里随便生成一个 + String outTradeNo = OrderInfoUtil2_0.genOutTradeNo(); + // 设置统一下单的请求参数 + task.setParams(OrderInfoUtil.buildOrderParamMap(outTradeNo, "测试支付", "", "1", null, null, null)); + task.execute(); } +} ``` ## 说明 -- 因本demo未申请支付宝支付和微信支付,所以在demo中无法支付成功。 +- 因本demo未申请支付宝支付和微信支付,所以在示例中无法支付成功。 - 如果项目中已经包含或依赖的第三方库中已包含libammsdk.jar(微信sdk),在引入af-pay后,出现因jar版本不致导致编译不通过,建议引入`pure`分支版本。 - af-pay原来是包含在[QuickAF]中,建议使用[QuickAF]的同学们更新依赖。 - 日志tag为`pay_sdk`,可以设置`Wxpay.DEUBG = true`或`Alipay.DEUBG = true`来开启日志。 - 更多请加入![QQ群: 629153672](http://dl.ieclipse.cn/screenshots/quickaf_group.png) +- 0.0.2版本,微信依赖改为`com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+` [QuickAF]: https://github.com/Jamling/QuickAF diff --git a/app/src/main/java/cn/ieclipse/pay/demo/MainActivity.java b/app/src/main/java/cn/ieclipse/pay/demo/MainActivity.java index 3922fc5..5eba9e6 100644 --- a/app/src/main/java/cn/ieclipse/pay/demo/MainActivity.java +++ b/app/src/main/java/cn/ieclipse/pay/demo/MainActivity.java @@ -9,8 +9,8 @@ import android.widget.TextView; import android.widget.Toast; -import com.tencent.mm.sdk.modelbase.BaseResp; -import com.tencent.mm.sdk.modelpay.PayReq; +import com.tencent.mm.opensdk.modelbase.BaseResp; +import com.tencent.mm.opensdk.modelpay.PayReq; import java.util.Map; @@ -26,26 +26,26 @@ public class MainActivity extends Activity implements View.OnClickListener { private EditText et1; private Button tv3; private Button tv4; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - + tv1 = (TextView) findViewById(R.id.tv1); tv2 = (TextView) findViewById(R.id.tv2); et1 = (EditText) findViewById(R.id.et1); tv3 = (Button) findViewById(R.id.tv3); tv4 = (Button) findViewById(R.id.tv4); - + tv1.setOnClickListener(this); tv2.setOnClickListener(this); tv3.setOnClickListener(this); tv4.setOnClickListener(this); - + setTitle("支付示例"); } - + @Override public void onClick(View v) { if (v == tv1) { @@ -63,9 +63,9 @@ else if (v == tv4) { doWxpay(info); } } - + private void doAlipay(String orderInfo) { - + final Activity activity = this; Alipay alipay = new Alipay(activity); alipay.setPayListener(new Alipay.PayListener() { @@ -73,23 +73,23 @@ private void doAlipay(String orderInfo) { public void onPaySuccess(PayResult payResult) { showToast(activity, "支付成功"); } - + @Override public void onPayWaiting(PayResult payResult) { showToast(activity, "支付结果确认中..."); } - + @Override public void onPayCancel(PayResult payResult) { showToast(activity, "您已取消支付"); } - + @Override public void onPayFailure(PayResult payResult) { showToast(activity, "支付失败\n" + payResult.getMemo()); } }); - + if (TextUtils.isEmpty(orderInfo)) { // set v1 config Alipay.DEBUG = true; @@ -97,61 +97,70 @@ public void onPayFailure(PayResult payResult) { Alipay.Config.rsa_private = ""; Alipay.Config.rsa_public = ""; Alipay.Config.notify_url = "app/pay/alipay_notify.do"; - + if (!alipay.check()) { showToast(activity, "缺少配置,无法支付"); return; } - + String trans_order_id = OrderInfoUtil2_0.genOutTradeNo(); Map map = OrderInfoUtil2_0.buildOrderParamMap(trans_order_id, "测试支付", "测试商品1,测试商品2", String.valueOf(0.01f), null); orderInfo = OrderInfoUtil2_0.getOrderInfo(map); - + alipay.payV1(orderInfo); } else { alipay.payV2(orderInfo); } } - + private void doWxpay(String orderInfo) { final Activity activity = this; + // 获取支付类 Wxpay wxpay = Wxpay.getInstance(activity); - wxpay.setPayListener(new cn.ieclipse.pay.wxpay.Wxpay.PayListener() { + // 设置支付回调监听 + wxpay.setPayListener(new Wxpay.PayListener() { @Override public void onPaySuccess(BaseResp resp) { - showToast(activity, "支付成功:" + resp.errStr); + showToast(activity, "支付成功"); } - + @Override public void onPayCanceled(BaseResp resp) { showToast(activity, "支付取消"); } - + @Override public void onPayFailure(BaseResp resp) { - showToast(activity, "支付失败:" + resp.errStr); + showToast(activity, "支付失败"); } }); + // 这里是服务端下单,内容是统一下单返回的xml if (!TextUtils.isEmpty(orderInfo)) { PayReq req = OrderInfoUtil.getPayReq(orderInfo); wxpay.pay(req); } - else { - Wxpay.DEBUG = true; + else { // 客户端下单 + Wxpay.DEBUG = true; // 开启日志 + // API密钥,在微信商户平台设置 Wxpay.Config.api_key = ""; + // APPID,在微信开放平台创建应用后生成 Wxpay.Config.app_id = ""; + // 商户ID,注册商户平台后生成 Wxpay.Config.mch_id = ""; - Wxpay.Config.notify_url = "app/pay/wxpay_notify.do"; - + // 支付结果异步通知接口,由后台开发提供 + Wxpay.Config.notify_url = "http://www.ieclipse.cn/app/pay/wxpay_notify.do"; + // 创建统一下单异步任务 Wxpay.DefaultOrderTask task = new Wxpay.DefaultOrderTask(wxpay); - String trans_order_id = OrderInfoUtil2_0.genOutTradeNo(); - task.setParams(OrderInfoUtil.buildOrderParamMap(trans_order_id, "测试支付", "", "1", null, null, null)); + // 这个商户订单号,由后台返回,在这里随便生成一个 + String outTradeNo = OrderInfoUtil2_0.genOutTradeNo(); + // 设置统一下单的请求参数 + task.setParams(OrderInfoUtil.buildOrderParamMap(outTradeNo, "测试支付", "", "1", null, null, null)); task.execute(); } } - + private void showToast(Activity activity, String msg) { Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); } diff --git a/library/build.gradle b/library/build.gradle index 521df5a..2b5587d 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -41,13 +41,16 @@ ext { } dependencies { - if (pure) + if (pure) { provided fileTree(include: ['*.jar'], dir: 'libs') - else + provided 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+' + } else { compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+' + } } -tasks.withType(org.gradle.api.tasks.javadoc.Javadoc){ +tasks.withType(org.gradle.api.tasks.javadoc.Javadoc) { options { links "http://docs.oracle.com/javase/7/docs/api/" linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" @@ -60,17 +63,18 @@ tasks.withType(org.gradle.api.tasks.javadoc.Javadoc){ } } +// ./gradlew clean library:build bintrayUpload -PbintrayUser=BINTRAY_USERNAME -PbintrayKey=BINTRAY_KEY -PdryRun=false publish { userOrg = 'jamling' groupId = 'cn.ieclipse.af' artifactId = pure ? "af-pay-pure" : 'af-pay' - publishVersion = '0.0.1' + publishVersion = '0.0.2' desc = 'An Android pay sdk' website = 'https://github.com/Jamling/af-pay' bintrayUser = 'jamling' bintrayKey = '832bbe2d2e86f4644c948dc82aa69cc4fa30c16f' dryRun = true } -task hello(){ - println (pure) +task hello() { + println(pure) } \ No newline at end of file diff --git a/library/gradle.properties b/library/gradle.properties index ce3f8e9..adb30c5 100644 --- a/library/gradle.properties +++ b/library/gradle.properties @@ -8,7 +8,7 @@ systemProp.socksProxyHost=127.0.0.1 systemProp.socksProxyPort=1080 # artifact -ART_VER=1.0.1 +ART_VER=0.0.2 ART_GROUP=cn.ieclipse.af ART_ARTIFACT=af-pay ART_ARTIFACT_PURE=af-pay-pure @@ -30,7 +30,7 @@ LIC_DESC= SCM_URL=https://github.com/Jamling/af-pay SCM_REPO=https://github.com/Jamling/af-pay.git SCM_DEV=git@github.com:Jamling/af-pay.git -SCM_TAG= +SCM_TAG=v0.0.2 # MAVEN DEV DEV_NAME=QuickAF Project diff --git a/library/libs/libammsdk.jar b/library/libs/libammsdk.jar deleted file mode 100644 index 7d6300f..0000000 Binary files a/library/libs/libammsdk.jar and /dev/null differ diff --git a/library/src/main/java/cn/ieclipse/pay/wxpay/AppRegister.java b/library/src/main/java/cn/ieclipse/pay/wxpay/AppRegister.java index 6667c49..087c90a 100644 --- a/library/src/main/java/cn/ieclipse/pay/wxpay/AppRegister.java +++ b/library/src/main/java/cn/ieclipse/pay/wxpay/AppRegister.java @@ -4,8 +4,8 @@ import android.content.Context; import android.content.Intent; -import com.tencent.mm.sdk.openapi.IWXAPI; -import com.tencent.mm.sdk.openapi.WXAPIFactory; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; public class AppRegister extends BroadcastReceiver { diff --git a/library/src/main/java/cn/ieclipse/pay/wxpay/OrderInfoUtil.java b/library/src/main/java/cn/ieclipse/pay/wxpay/OrderInfoUtil.java index 0eff6cf..eaf3677 100644 --- a/library/src/main/java/cn/ieclipse/pay/wxpay/OrderInfoUtil.java +++ b/library/src/main/java/cn/ieclipse/pay/wxpay/OrderInfoUtil.java @@ -18,7 +18,7 @@ import android.text.TextUtils; import android.util.Xml; -import com.tencent.mm.sdk.modelpay.PayReq; +import com.tencent.mm.opensdk.modelpay.PayReq; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; @@ -109,7 +109,7 @@ public static Map parseJsonResponse(String content) { } /** - * Get {@link com.tencent.mm.sdk.modelpay.PayReq} from order map result. + * Get {@link com.tencent.mm.opensdk.modelpay.PayReq} from order map result. * * @param result order result map * @@ -127,25 +127,34 @@ public static PayReq getPayReq(Map result) { req.prepayId = result.get("prepay_id"); req.timeStamp = String.valueOf(System.currentTimeMillis() / 1000); req.sign = result.get("sign"); - - Map sortedMap = new TreeMap<>(); - sortedMap.put("appid", req.appId); - sortedMap.put("noncestr", req.nonceStr); - sortedMap.put("partnerid", req.partnerId); - sortedMap.put("prepayid", req.prepayId); - sortedMap.put("timestamp", req.timeStamp); - sortedMap.put("package", req.packageValue); - String sign = OrderInfoUtil.genSign(sortedMap); - if (Wxpay.DEBUG) { - Wxpay.log("客户端支付签名:" + sign); - } - req.sign = sign; + signPayReq(req); } return req; } /** - * Get {@link com.tencent.mm.sdk.modelpay.PayReq} from order xml result. + * 重新签名,当客户端下单的时候,统一订单接口并未返回timestamp,加上timestamp后,需要重新签名。 + * 如果是服务端下单,如果服务端已经重新生成了签名,那么无需客户端重新签名,直接拿PayReq对象去支付就可以了。 + * + * @param req 将要调用微信客户端 + */ + public static void signPayReq(PayReq req) { + Map sortedMap = new TreeMap<>(); + sortedMap.put("appid", req.appId); + sortedMap.put("noncestr", req.nonceStr); + sortedMap.put("partnerid", req.partnerId); + sortedMap.put("prepayid", req.prepayId); + sortedMap.put("timestamp", req.timeStamp); + sortedMap.put("package", req.packageValue); + String sign = OrderInfoUtil.genSign(sortedMap); + if (Wxpay.DEBUG) { + Wxpay.log("客户端支付重签名:" + sign); + } + req.sign = sign; + } + + /** + * Get {@link com.tencent.mm.opensdk.modelpay.PayReq} from order xml result. * * @param xmlResultContent order result xml content * diff --git a/library/src/main/java/cn/ieclipse/pay/wxpay/WXPayActivity.java b/library/src/main/java/cn/ieclipse/pay/wxpay/WXPayActivity.java index d292763..73da6d2 100644 --- a/library/src/main/java/cn/ieclipse/pay/wxpay/WXPayActivity.java +++ b/library/src/main/java/cn/ieclipse/pay/wxpay/WXPayActivity.java @@ -19,10 +19,10 @@ import android.content.Intent; import android.os.Bundle; -import com.tencent.mm.sdk.constants.ConstantsAPI; -import com.tencent.mm.sdk.modelbase.BaseReq; -import com.tencent.mm.sdk.modelbase.BaseResp; -import com.tencent.mm.sdk.openapi.IWXAPIEventHandler; +import com.tencent.mm.opensdk.constants.ConstantsAPI; +import com.tencent.mm.opensdk.modelbase.BaseReq; +import com.tencent.mm.opensdk.modelbase.BaseResp; +import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; /** * Description diff --git a/library/src/main/java/cn/ieclipse/pay/wxpay/Wxpay.java b/library/src/main/java/cn/ieclipse/pay/wxpay/Wxpay.java index 518612c..8fe8a47 100644 --- a/library/src/main/java/cn/ieclipse/pay/wxpay/Wxpay.java +++ b/library/src/main/java/cn/ieclipse/pay/wxpay/Wxpay.java @@ -23,13 +23,13 @@ import android.util.Log; import android.widget.Toast; -import com.tencent.mm.sdk.constants.Build; -import com.tencent.mm.sdk.modelbase.BaseResp; -import com.tencent.mm.sdk.modelpay.PayReq; -import com.tencent.mm.sdk.modelpay.PayResp; -import com.tencent.mm.sdk.openapi.IWXAPI; -import com.tencent.mm.sdk.openapi.IWXAPIEventHandler; -import com.tencent.mm.sdk.openapi.WXAPIFactory; +import com.tencent.mm.opensdk.constants.Build; +import com.tencent.mm.opensdk.modelbase.BaseResp; +import com.tencent.mm.opensdk.modelpay.PayReq; +import com.tencent.mm.opensdk.modelpay.PayResp; +import com.tencent.mm.opensdk.openapi.IWXAPI; +import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; +import com.tencent.mm.opensdk.openapi.WXAPIFactory; import java.util.Iterator; import java.util.Map; @@ -245,7 +245,9 @@ protected String map2xmlStr(Map params) { sb.append(""); String xml = ""; try { - xml = new String(sb.toString().getBytes(), "UTF-8"); + // 使用HttpClient,需设置ISO-8859-1编码 + // xml = new String(sb.toString().getBytes(), "UTF-8"); + xml = sb.toString(); } catch (Exception e) { if (Wxpay.DEBUG) { Wxpay.log(e.getMessage());