最近几天采坑了微信代扣,开发流程很简单,但是官方文档实在缺少一个具体的指引,导致走了很多弯路,因此本文分享一下自己的经验。
微信代扣开发者文档: https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_1
上图是文档的网页截图,其中红框里的 SDK 需要配置一下,APP跳转签约页面方法指引 是外部唤起微信的方法,(话说这个入口我找了好久才发现,一把辛酸泪……)
文档很长,对于各个端做什么也没有明确描述,所以我站在 Android 端的角度,讲一下开发流程。总共分以下三步:
1、调用服务端接口进行签约
服务端接口的返回类型是自定义的 Contract 类,其中 contractId
和 contractUrl
是 Android 端能用到的。(接口格式以你们服务端给的为准,此处仅供参考)
//签约
@POST("/xxx/contracts")
Observable<Response<Contract>> getContract();
public class Contract {
@JsonProperty("contract_id")
public String contractId; // 微信给的签约合同号
@JsonProperty("contract_url")
public String contractUrl;// 可以调起微信的url
@JsonProperty("product_id")
public String productId; // IOS 会用到的 id,Android 端可以直接忽略
}
2、利用服务端返回的 contractUrl
调起微信签约付款页
private void toWeChatScan(String url) {
try {
WeChatPayUtil.pay(getActivity(), url);
} catch (Exception e) {
//若无法正常跳转,在此进行错误处理
Toast.makeText(getContext(), "跳转到微信失败",Toast.LENGTH_SHORT).show();
}
}
public class WeChatPayUtil {
private static IWXAPI sWXAPI;
/**
* 微信代扣
* @param pActivity
* @param url
* @return
* @throws Exception
*/
public static boolean pay(Activity pActivity, String url) throws Exception {
if (sWXAPI == null) {
sWXAPI = WXAPIFactory.createWXAPI(pActivity, WeChatHelper.WECHAT_APP_ID);
}
if (微信未安装) {
ToastUtils.showLongToast(pActivity, R.string.toast_text_weixin_not_installed);
return false;
}
toWechatContractPay(url);
return true;
}
private static void toWechatContractPay(String url) {
OpenWebview.Req req = new OpenWebview.Req();
req.url = url;
sWXAPI.sendReq(req);
}
}
3、调用服务端接口轮询检查支付状态
微信代付的话,在微信中支付完成后,并不会同步返回结果给我们的 app,只会把支付结果通知我们的服务器,所以需要在我们的 app 中对服务器进行轮询来检查支付结果。
检查也不需要很多次,我们项目里是轮询 5 次,1 秒一次,已经足够了。
(接口格式以你们服务端给的为准,此处仅供参考)
/**
* 查看自动续费签约状态
*
* @param packageId
* @param contractId
* @return
*/
@GET("/xxx/contracts/{contract_id}")
Observable<Response<OrderStatus>> getOrderStatus(@Path("contract_id") String contractId);
其中的 contract_id
是在步骤1中返回的,这里需要用这个合同号来检查状态。
public class OrderStatus {
@JsonProperty("status")
public String status;//granted, ungranted, pending, unsubscribed
@JsonProperty("singed_at")
public long singedAt;//签约成功的时间(这个只有在 granted 状态时才有效)
@JsonProperty("contract_type")
public String contractType;//wechat, iap
@JsonProperty("withhold")
public OrderStatusWithhold withhold;
}
public class OrderStatusWithhold {
@JsonProperty("status")
public String status;//<"created", "pending", "succeeded", "failed">
@JsonProperty("error_message")
public String errorMessage;
}
需要注意上面两个 status 代表不同的意义, orderStatus.status
是签约状态,而orderStatusWithhold.status
是扣款状态,有可能签约成功,但是扣款时因为余额不足等原因而失败。
附一个讲代扣整体过程的文章,要开发的话值得一看:
http://jverson.com/2015/12/20/wechat/