cordova/ionic alipay 支付宝插件
来源:互联网 发布:斯托克斯矩阵 编辑:程序博客网 时间:2024/04/30 06:52
最近在做的一个项目中涉及到了支付宝支付。在尝试了网络上的几个插件之后,发现都因为版本太老,支付宝官方提供的接口已经发生了改变,所以无法使用。于是决定自己动手编写一个最新版的支付宝插件,下面我们进入主题。
1、创建插件目录
新建一个文件夹,作为插件根目录,在根目录中新建两个文件夹,一个为src存放原生代码源文件,一个为www存放插件js文件。另外在根目录下创建plugin.xml文件,用于写入插件配置。
2、编写alipay.js
var exec = require('cordova/exec');var Alipay = { /** * 支付宝支付业务 * * @param price 付款金额 * @param subject 主题 * @param body 详情 * @param tradeNo 订单号 */ pay:function(onSuccess, onError, price, subject, body, tradeNo) { exec( onSuccess, onError, "AlipayPlugin", "alipay", [price, subject, body, tradeNo] ); }}module.exports = Alipay;
第一个参数为支付成功后的回调方法,第二个参数为失败后的回调方法。
3、编写原生代码
3.1 Andoid原生
首先在src目录下,创建android和ios目录,用于存放两个平台的原生代码及库文件,在这里我用的是支付宝的20161222版本,是截止到本文发布时的最新版本。
去支付宝官网下载最新demo,然后将其中的工具类、jar包以及资源文件拷贝到android目录下,新建一个类命名为AlipayPlugin.java,继承CordovaPlugin,用于存放支付宝的支付逻辑。
package com.beanyon.alipay;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.widget.Toast;import com.alipay.sdk.app.PayTask;import com.beanyon.alipay.util.OrderInfoUtil2_0;import org.apache.cordova.CallbackContext;import org.apache.cordova.CordovaPlugin;import org.json.JSONArray;import org.json.JSONException;import java.util.Map;/** * Created by BeanYon on 2017/1/6. */public class AlipayPlugin extends CordovaPlugin { private Context mContext = null; private final String ACTION_FLAG = "alipay";//传入的action参照 CallbackContext currentCallbackContext;//回调参数 /** * 支付宝支付业务:入参app_id */ public static final String APPID = "你的app_id"; /** 商户私钥,pkcs8格式 */ /** 如下私钥,RSA2_PRIVATE 或者 RSA_PRIVATE 只需要填入一个 */ /** 如果商户两个都设置了,优先使用 RSA2_PRIVATE */ /** RSA2_PRIVATE 可以保证商户交易在更加安全的环境下进行,建议使用 RSA2_PRIVATE */ /** 获取 RSA2_PRIVATE,建议使用支付宝提供的公私钥生成工具生成, */ /** * 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1 */ public static final String RSA2_PRIVATE = "your_private_key"; public static final String RSA_PRIVATE = ""; private static final int SDK_PAY_FLAG = 1; @Override public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { currentCallbackContext = callbackContext; mContext = cordova.getActivity(); if (ACTION_FLAG.equals(action)) { return payV2(args.getString(0),args.getString(1),args.getString(2),args.getString(3));//调用支付宝付款 } return true; } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @SuppressWarnings("unused") public void handleMessage(Message msg) { switch (msg.what) { case SDK_PAY_FLAG: { @SuppressWarnings("unchecked") PayResult payResult = new PayResult((Map<String, String>) msg.obj); /** *对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。 */ String resultInfo = payResult.getResult();// 同步返回需要验证的信息 String resultStatus = payResult.getResultStatus(); // 判断resultStatus 为9000则代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { // 该笔订单是否真实支付成功,需要依赖服务端的异步通知。 Toast.makeText(mContext, "支付成功", Toast.LENGTH_SHORT).show(); currentCallbackContext.success(resultStatus); } else { // 该笔订单真实的支付结果,需要依赖服务端的异步通知。 Toast.makeText(mContext, "支付失败", Toast.LENGTH_SHORT).show(); } break; } default: break; } } ; }; /** * 支付宝支付业务 * * @param price 付款金额 * @param subject 主题 * @param body 详情 * @param tradeNo 订单号 */ public boolean payV2(String price, String subject, String body, String tradeNo) { /** * 这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成; * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成; * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险; * * orderInfo的获取必须来自服务端; */ boolean rsa2 = (RSA2_PRIVATE.length() > 0); Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID, rsa2, price, subject, body, tradeNo); String orderParam = OrderInfoUtil2_0.buildOrderParam(params); String privateKey = rsa2 ? RSA2_PRIVATE : RSA_PRIVATE; String sign = OrderInfoUtil2_0.getSign(params, privateKey, rsa2); final String orderInfo = orderParam + "&" + sign; Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask((Activity) mContext); Map<String, String> result = alipay.payV2(orderInfo, true); Log.i("msp", result.toString()); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; Thread payThread = new Thread(payRunnable); payThread.start(); return true; }}adnroid目录下的文件结构如下图所示
3.2 iOS原生
同样在插件的ios目录下,将支付宝官方提供的demo中必要的库文件以及支持工具类拷贝进去,官方的openssl文件夹引入的时候出现了一些问题,所以我把这个文件夹以framework的形式引入。必要的库文件在这里不赘述,大家下载官方demo就可以看到了。以下同样是iOS插件类的源码,里面调用了支付逻辑。
AlipayPlugin.h
#import <Foundation/Foundation.h>#import <Cordova/CDV.h>#import <Cordova/CDVPlugin.h>@interface AlipayPlugin : CDVPlugin- (void)alipay:(CDVInvokedUrlCommand*)command;@end
AlipayPlugin.m
#import "AlipayPlugin.h"#import "Order.h"#import "RSADataSigner.h"#import <AlipaySDK/AlipaySDK.h>@implementation AlipayPlugin- (void)alipay:(CDVInvokedUrlCommand *)command{//重要说明 //这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成; //真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成; //防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;/*============================================================================*//*=======================需要填写商户app申请的===================================*//*============================================================================*/ NSString *appID = @"app_id"; // 如下私钥,rsa2PrivateKey 或者 rsaPrivateKey 只需要填入一个 // 如果商户两个都设置了,优先使用 rsa2PrivateKey // rsa2PrivateKey 可以保证商户交易在更加安全的环境下进行,建议使用 rsa2PrivateKey // 获取 rsa2PrivateKey,建议使用支付宝提供的公私钥生成工具生成, // 工具地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=106097&docType=1 NSString *rsa2PrivateKey = @"your_private_key"; NSString *rsaPrivateKey = @"";/*============================================================================*//*============================================================================*//*============================================================================*//* *获取插件传参 */NSString* price = [command.arguments objectAtIndex:0];// NSLog([@"BeanYon:" stringByAppendingString:myarg]);NSString* subject = [command.arguments objectAtIndex:1];// NSLog([@"BeanYon:" stringByAppendingString:myarg2]);NSString* body = [command.arguments objectAtIndex:2];// NSLog([@"BeanYon:" stringByAppendingString:myarg3]);NSString* tradeNo = [NSString stringWithFormat:@"%d", [command.arguments objectAtIndex:3]];// NSLog([@"BeanYon:" stringByAppendingString:[NSString stringWithFormat:@"%d", [command.arguments objectAtIndex:3]]]); /* *生成订单信息及签名 */ //将商品信息赋予AlixPayOrder的成员变量 Order* order = [Order new]; // NOTE: app_id设置 order.app_id = appID; // NOTE: 支付接口名称 order.method = @"alipay.trade.app.pay"; // NOTE: 参数编码格式 order.charset = @"utf-8"; // NOTE: 当前时间点 NSDateFormatter* formatter = [NSDateFormatter new]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; order.timestamp = [formatter stringFromDate:[NSDate date]]; // NOTE: 支付版本 order.version = @"1.0"; // NOTE: sign_type 根据商户设置的私钥来决定 order.sign_type = (rsa2PrivateKey.length > 1)?@"RSA2":@"RSA"; // NOTE: 商品数据 order.biz_content = [BizContent new]; order.biz_content.body = body; order.biz_content.subject = subject; order.biz_content.out_trade_no = tradeNo; //订单ID(由商家自行制定) order.biz_content.timeout_express = @"30m"; //超时时间设置 order.biz_content.total_amount = price; //商品价格 //将商品信息拼接成字符串 NSString *orderInfo = [order orderInfoEncoded:NO]; NSString *orderInfoEncoded = [order orderInfoEncoded:YES]; NSLog(@"orderSpec = %@",orderInfo); // NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露; // 需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode NSString *signedString = nil; RSADataSigner* signer = [[RSADataSigner alloc] initWithPrivateKey:((rsa2PrivateKey.length > 1)?rsa2PrivateKey:rsaPrivateKey)]; if ((rsa2PrivateKey.length > 1)) { signedString = [signer signString:orderInfo withRSA2:YES]; } else { signedString = [signer signString:orderInfo withRSA2:NO]; } // NOTE: 如果加签成功,则继续执行支付 if (signedString != nil) { //应用注册scheme,在AliSDKDemo-Info.plist定义URL types NSString *appScheme = @"alisdkdemo"; // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式 NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@", orderInfoEncoded, signedString]; // NOTE: 调用支付结果开始支付 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { NSLog(@"reslut = %@",resultDic); }]; }}@end
4、插件配置文件
最后,为插件写好配置文件,以便于安装插件的时候将所有的资源文件加入到Android、iOS平台中打包编译。
plugin.xml
<?xml version="1.0" encoding="UTF-8"?><plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="com.beanyon.alipay" version="0.0.1"> <name>AlipayPlugin</name> <description>Cordova Alipay</description> <license>Apache 2.0</license> <keywords>cordova alipay</keywords> <js-module name="AlipayPlugin" src="www/alipay.js"> <clobbers target="cordova.plugins.AlipayPlugin"/> </js-module> <!-- android --> <platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> <feature name="AlipayPlugin"> <param name="android-package" value="com.beanyon.alipay.AlipayPlugin" /><!-- 此处根据自己定义的包名修改 --> </feature> </config-file> <config-file target="AndroidManifest.xml" parent="/*"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </config-file> <source-file src="src/android/AlipayPlugin.java" target-dir="src/com/beanyon/alipay"/> <source-file src="src/android/Base64.java" target-dir="src/com/beanyon/alipay"/> <source-file src="src/android/ExternalFragment.java" target-dir="src/com/beanyon/alipay"/> <source-file src="src/android/PayResult.java" target-dir="src/com/beanyon/alipay"/> <source-file src="src/android/SignUtils.java" target-dir="src/com/beanyon/alipay"/> <source-file src="src/android/util/OrderInfoUtil2_0.java" target-dir="src/com/beanyon/alipay/util"/> <source-file src="src/android/lib/alipaySdk-20161222.jar" target-dir="libs" /> <source-file src="src/android/lib/android-support-v13.jar" target-dir="libs" /> <source-file src="src/android/xml/pay_external.xml" target-dir="res/layout" /> <source-file src="src/android/xml/pay_main.xml" target-dir="res/layout" /> <source-file src="src/android/drawable/msp_demo_title.png" target-dir="res/drawable" /> <source-file src="src/android/drawable/msp_demo_title_bg.png" target-dir="res/drawable" /> </platform> <platform name="ios"> <!--ios9不允许http访问,需要使用https访问,添加以下属性使http正常使用 --> <config-file target="*-Info.plist" parent="NSAppTransportSecurity"> <dict> <key>NSAllowsArbitraryLoads</key> <true /> </dict> </config-file> <!-- build setting header search path $(SRCROOT)/X5 --> <header-file src="src/ios/AlipayPlugin.h" /> <source-file src="src/ios/AlipayPlugin.m" /> <header-file src="src/ios/Order.h" /> <source-file src="src/ios/Order.m" /> <!-- Util --> <header-file src="src/ios/Util/base64.h" /> <source-file src="src/ios/Util/base64.m" /> <header-file src="src/ios/Util/config.h" /> <header-file src="src/ios/Util/NSDataEx.h" /> <source-file src="src/ios/Util/NSDataEx.m" /> <header-file src="src/ios/Util/openssl_wrapper.h" /> <source-file src="src/ios/Util/openssl_wrapper.m" /> <header-file src="src/ios/Util/RSADataSigner.h" /> <source-file src="src/ios/Util/RSADataSigner.m" /> <header-file src="src/ios/Util/RSADataVerifier.h" /> <source-file src="src/ios/Util/RSADataVerifier.m" /> <resource-file src="src/ios/AlipaySDK.bundle"/> <config-file target="config.xml" parent="/*"> <feature name="AlipayPlugin"> <param name="ios-package" value="AlipayPlugin" /> <param name="onload" value="true" /> </feature> </config-file> <source-file src="src/ios/libcrypto.a" framework="true" /> <source-file src="src/ios/libssl.a" framework="true" /> <!-- 手动copy framework bundle 文件 --> <!-- afnetworking 依赖security.framework --> <framework src="libsqlite3.0.tbd"/> <framework src="libz.1.2.5.tbd" /> <framework src="CoreTelephony.framework" /> <framework src="SystemConfiguration.framework" /> <framework src="Security.framework" /> <framework src="libstdc++.6.0.9.tbd" /> <framework src="AssetsLibrary.framework"/> <framework src="libz.tbd"/> <framework src="libc++.tbd"/> <framework src="CoreMotion.framework"/> <framework src="src/ios/AlipaySDK.framework" custom="true" /> <framework src="src/ios/openssl.framework" custom="true" /> </platform></plugin>
5、调用
cordova.plugins.AlipayPlugin.pay( function(resultStatus){ alert("调用成功:"+resultStatus); }, function(){ alert("调用失败"); }, price, subject, body, tradeNo);
欢迎各位一起交流讨论,集思广益。
0 0
- cordova/ionic alipay 支付宝插件
- ionic如何使用cordova-plugin-alipay支付
- ionic项目中使用cordova插件支付宝支付
- ionic 用 cordova插件,ping++方式 实现支付宝,微信支付
- 支付宝Alipay 支付
- ionic cordova 插件 资源
- ionic cordova keyboard插件
- phonegap cordova ionic插件
- alipay支付宝招聘
- java 支付宝支付alipay
- Cordova支付宝插件的那些坑
- 自定义cordova插件(phonegap、ionic)
- ionic之cordova插件自定义
- Ionic— Cordova 插件开发
- ionic添加ng-cordova插件
- ionic添加cordova插件-Splashscreen
- ionic添加cordova插件-StatusBar
- ionic添加cordova插件-Badge
- 从ASP.NET Web API 2 (C#)开始说起
- 小程序wx:key的作用
- Unity3d:Occlusion Culling
- c# donald gerald robert
- c/c++调用Java
- cordova/ionic alipay 支付宝插件
- 数据库设计原则
- 【BZOJ 2084】[Poi2010]Antisymmetry manacher
- 我的2016年个人总结
- 原码、反码、补码、负数的移位
- DB2常用函数详解(一):字符串函数
- [51Nod 1189阶乘分数]数学
- Launcher介绍
- 静态成员